namespace AcDream.Core.Chat;
///
/// Source/transport classification for a chat channel — distinguishes
/// retail's two parallel chat channel pipelines.
///
public enum ChatChannelSource
{
/// Legacy ChatChannel bitflag id rides 0x0147 ChatChannel.
Legacy,
/// Turbine room id rides 0xF7DE TurbineChat.
Turbine,
}
///
/// Unified info about a chat channel — either a legacy ChatChannel id
/// (Fellowship, Allegiance, Vassals, Patron, Monarch, CoVassals) or a
/// Turbine room id (General, Trade, LFG, Roleplay, Society*, Olthoi).
///
///
/// Mirrors holtburger's ChatChannelInfo
/// (references/holtburger/crates/holtburger-core/src/client/types.rs
/// lines 63-102). The two retail channel pipelines run side by side —
/// legacy ChatChannel for the player-organisation channels and
/// TurbineChat for the global community rooms — and a single
/// abstraction over both keeps the chat panel and command bus from
/// having to special-case the transport at every call site.
///
///
///
/// tells callers whether the server
/// echoes the client's own outgoing messages back on this channel
/// (so the client should suppress its optimistic local echo). Per
/// holtburger's predicate at chat.rs::is_self_echo_channel
/// (lines 492-507) this is true ONLY for the legacy fellowship/vassals/
/// patron/monarch/co-vassals channels — server resends those with
/// empty sender. Turbine and tells do not echo.
///
///
public abstract record ChatChannelInfo(string DisplayName, ChatChannelSource Source)
{
/// Legacy ChatChannel bitflag id (0x00000800 etc.).
public sealed record Legacy(uint ChannelId, string DisplayName)
: ChatChannelInfo(DisplayName, ChatChannelSource.Legacy)
{
public override bool IsSelfEchoChannel()
{
// Per holtburger: the legacy fellowship + allegiance-tree
// channels are the ones the server echoes back to the sender
// with an empty sender field. Bitflag values from
// references/holtburger/.../messages/chat/types.rs::ChatChannel.
return ChannelId switch
{
0x00000800u => true, // Fellow
0x00001000u => true, // Vassals
0x00002000u => true, // Patron
0x00004000u => true, // Monarch
0x01000000u => true, // CoVassals
_ => false,
};
}
}
///
/// TurbineChat room. is the runtime channel id
/// the server hands out via SetTurbineChatChannels (0x0295).
/// classifies the room semantically (General,
/// Trade, etc.); chooses the wire dispatch
/// (SendToRoomById for outbound, SendToRoomByName for inbound events).
///
public sealed record Turbine(
uint RoomId,
uint ChatType,
uint DispatchType,
string DisplayName)
: ChatChannelInfo(DisplayName, ChatChannelSource.Turbine)
{
public override bool IsSelfEchoChannel()
{
// Turbine rooms do NOT echo the sender's own messages back.
// The client must emit its own optimistic local echo to give
// the player feedback that the message was sent.
return false;
}
}
///
/// True iff the server echoes our own outgoing messages on this
/// channel — caller should suppress optimistic local echo to avoid
/// double-printing.
///
public abstract bool IsSelfEchoChannel();
}