internal void PushCommand(Command cmd) { if (cmd.Source == CommandSource.Client) { return; } switch (cmd.Token) { case "JCH": { var jch = cmd as Server_JCH_ChannelJoin; var character = Connection.GetOrCreateCharacter(jch.Character.Identity); if (!_Characters.Contains(character)) { _Characters.Add(character); } if (!string.IsNullOrEmpty(jch.Title)) { _Title = jch.Title; Joined = true; } else { OnUserJoin?.Invoke(this, new ChannelUserEntryEventArgs(this, character, jch)); } } return; case "LCH": { var lch = cmd as Server_LCH_ChannelLeave; var character = GetCharacter(lch.Character); _Characters.Remove(character); if (character.Name == Connection.LocalCharacter.Name) { Dispose(); } else { OnUserLeave?.Invoke(this, new ChannelUserEntryEventArgs(this, character, lch)); } } return; case "ICH": { var ich = cmd as Server_ICH_ChannelInitialData; _ChannelMode = ich.Mode; Joined = true; foreach (var user in ich.Users) { var ch = GetCharacter(user.Identity); if (!_Characters.Contains(ch)) { _Characters.Add(ch); } } } return; case "COL": { var col = cmd as Server_COL_ChannelGetOPs; foreach (var op in col.OPs) { if (!string.IsNullOrWhiteSpace(op)) { _OPs.Add(GetCharacter(op)); } } } return; case "CDS": { var cds = cmd as Server_CDS_ChannelChangeDescription; OnDescriptionChange?.Invoke(this, new ChannelEntryEventArgs <string>(this, cds.Description, cds)); _Description = cds.Description; } return; case "RMO": { var rmo = cmd as Server_RMO_ChannelSetMode; OnModeChange?.Invoke(this, new ChannelEntryEventArgs <ChannelMode>(this, rmo.Mode, rmo)); _ChannelMode = rmo.Mode; } return; case "CSO": { var cso = cmd as Server_CSO_ChannelSetOwner; OnOwnerChange?.Invoke(this, new ChannelEntryEventArgs <Character>(this, GetCharacter(cso.Character), cso)); _OwnerName = cso.Character; } return; case "RST": { var rst = cmd as Server_RST_ChannelSetStatus; OnStatusChange?.Invoke(this, new ChannelEntryEventArgs <ChannelStatus>(this, rst.Status, rst)); _Status = rst.Status; } return; case "COA": { var coa = cmd as Server_COA_ChannelMakeOP; var character = GetCharacter(coa.Character); _OPs.Add(character); OnOPAdded?.Invoke(this, new ChannelUserEntryEventArgs(this, character, coa)); } return; case "COR": { var cor = cmd as Server_COR_ChannelRemoveOP; var character = GetCharacter(cor.Character); _OPs.Remove(character); OnOPRemoved?.Invoke(this, new ChannelUserEntryEventArgs(this, character, cor)); } return; case "CKU": { var cku = cmd as Server_CKU_ChannelKickCharacter; var character = GetCharacter(cku.Character); _Characters.Remove(character); OnUserKicked?.Invoke(this, new ChannelAdminActionEventArgs(this, character, GetCharacter(cku.OP), cku)); } return; case "CBU": { var cbu = cmd as Server_CBU_ChannelBanCharacter; var character = GetCharacter(cbu.Character); _Characters.Remove(character); _Banlist.Add(character); OnUserBanned?.Invoke(this, new ChannelAdminActionEventArgs(this, character, GetCharacter(cbu.OP), cbu)); } return; case "CUB": { var cub = cmd as Server_CUB_ChannelUnbanCharacter; var character = GetCharacter(cub.Character); _Banlist.Remove(character); OnUserUnbanned?.Invoke(this, new ChannelAdminActionEventArgs(this, character, GetCharacter(cub.OP), cub)); } return; case "CTU": { var ctu = cmd as Server_CTU_ChannelTimeoutCharacter; var character = GetCharacter(ctu.Character); _Characters.Remove(character); OnUserTimedout?.Invoke(this, new ChannelAdminActionEventArgs(this, character, GetCharacter(ctu.OP), ctu)); } return; case "MSG": { var msg = cmd as Server_MSG_ChannelChatMessage; OnChatMessage?.Invoke(this, new ChannelUserMessageEventArgs(this, GetCharacter(msg.Character), msg.Message, msg)); } return; case "LRP": { var lrp = cmd as Server_LRP_ChannelLFRPMessage; OnLFRPMessage?.Invoke(this, new ChannelUserMessageEventArgs(this, GetCharacter(lrp.Character), lrp.AD, lrp)); } return; case "RLL": { var rll = cmd as Server_RLL_ChannelRollMessage; OnRollMessage?.Invoke(this, new ChannelUserMessageEventArgs(this, GetCharacter(rll.Character), rll.Message, rll)); } return; case "SYS": { var sys = cmd as Server_SYS_ChatSYSMessage; OnSYSMessage?.Invoke(this, new ChannelEntryEventArgs <string>(this, sys.Message, sys)); } return; } }
private void AddDefaultHandlers() { // Meta _Handlers["!!!"] += (_, c) => { var err = c as Server_Meta_Failed; Debug.WriteLine("Invalid command recieved: {0} - {2}\n{1}", err.CMDToken, err.Data, err.Exception); }; _Handlers["???"] += (_, c) => { var err = c as Server_Meta_Unknown; Debug.WriteLine("Unknown command recieved: {0}\n{1}", err.CMDToken, err.Data); }; // Connection related _Handlers["CON"] += (_, c) => { var con = c as Server_CON_ChatConnectedUsers; _Variables.SetVariable("__connected", con.ConnectedUsers); }; _Handlers["ERR"] += (_, c) => { var err = c as Server_ERR_ChatError; OnErrorMessage?.Invoke(this, new CommandEventArgs(err)); }; _Handlers["HLO"] += (_, c) => { var hlo = c as Server_HLO_ChatHello; // TODO: Properly report server hello. Debug.WriteLine($"Hello: {hlo.Message}"); }; _Handlers["IDN"] += (_, c) => { var idn = c as Server_IDN_ChatIdentify; _Identified = true; Debug.WriteLine($"Identified as {idn.Character}"); // TODO: Handle identifying properly OnIdentified?.Invoke(this, EventArgs.Empty); }; _Handlers["PIN"] += (_, c) => { if (AutoPing) { SendCommand(new Client_PIN_ChatPing()); } }; _Handlers["SYS"] += (_, c) => { var sys = c as Server_SYS_ChatSYSMessage; if (!string.IsNullOrEmpty(sys.Channel)) { var chan = GetChannel(sys.Channel); chan.PushCommand(sys); OnChannelSYSMessage?.Invoke(this, new ChannelEntryEventArgs <string>(chan, sys.Message, sys)); } else { OnSYSMessage?.Invoke(this, new CommandEventArgs(sys)); } }; _Handlers["UPT"] += (_, c) => { var upt = c as Server_UPT_ChatUptime; _Variables.SetVariable("__boot_time", upt.StartTime); _Variables.SetVariable("__users", upt.CurrentUsers); _Variables.SetVariable("__channels", upt.Channels); _Variables.SetVariable("__connections", upt.AcceptedConnections); _Variables.SetVariable("__peak", upt.PeakUsers); foreach (var name in new[] { "__boot_time", "__users", "__channels", "__connections", "__peak" }) { OnServerVariableUpdate?.Invoke(this, new ServerVariableEventArgs(name, _Variables[name])); } }; _Handlers["VAR"] += (_, c) => { var var = c as Server_VAR_ChatVariable; _Variables.SetVariable(var.Name, var.Value); OnServerVariableUpdate?.Invoke(this, new ServerVariableEventArgs(var.Name, var.Value)); }; // Chat OP related _Handlers["ADL"] += (_, c) => { var adl = c as Server_ADL_ChatListOPs; _ChatOPs.Clear(); _ChatOPs.AddRange(adl.OPs.Select(n => GetCharacter(n))); Debug.WriteLine($"Recieved OP list with {adl.OPs.Length} entries."); }; _Handlers["AOP"] += (_, c) => { var aop = c as Server_AOP_ChatAddOP; var character = GetCharacter(aop.Character); _ChatOPs.Add(character); OnOPAdded?.Invoke(this, new CharacterEntryEventArgs(character, aop)); }; _Handlers["DOP"] += (_, c) => { var dop = c as Server_DOP_ChatRemoveOP; var character = GetCharacter(dop.Character); _ChatOPs.Remove(character); OnOPRemoved?.Invoke(this, new CharacterEntryEventArgs(character, dop)); }; // Channel list related _Handlers["CHA"] += (_, c) => { var cha = c as Server_CHA_ChatListPublicChannels; // TODO: Do this properly, sync only changes _OfficialChannels.Clear(); _OfficialChannels.AddRange(cha.Channels.Select(C => new KnownChannel { UserCount = C.Count, ID = C.Name, Title = C.Name, Mode = C.Mode })); OnOfficialListUpdate?.Invoke(this, EventArgs.Empty); }; _Handlers["ORS"] += (_, c) => { var ors = c as Server_ORS_ChatListPrivateChannels; // TODO: Do this properly, sync only changes _PrivateChannels.Clear(); _PrivateChannels.AddRange(ors.Channels.Select(C => new KnownChannel { UserCount = C.Count, ID = C.ID, Title = C.Title })); OnPrivateListUpdate?.Invoke(this, EventArgs.Empty); }; // Character list related _Handlers["FRL"] += (_, c) => { var frl = c as Server_FRL_ChatListFriends; _Friends.AddRange(frl.FriendsAndBookmarks.Select(ch => GetOrCreateCharacter(ch))); _Bookmarks.AddRange(frl.FriendsAndBookmarks.Select(ch => GetOrCreateCharacter(ch))); Debug.WriteLine($"Recieved {frl.FriendsAndBookmarks.Length} friends and bookmarks"); OnFriendsListUpdate?.Invoke(this, EventArgs.Empty); }; _Handlers["IGN"] += (_, c) => { var ign = c as Server_IGN_ChatListIgnores; // TODO: Handle ignores switch (ign.Action) { case Server_IGN_ChatListIgnores.IgnoreAction.Init: Debug.WriteLine($"Initial ignore list received. {ign.Characters.Length} entries."); break; case Server_IGN_ChatListIgnores.IgnoreAction.Add: Debug.WriteLine($"TODO: Add {ign.Character} to ignore list."); break; case Server_IGN_ChatListIgnores.IgnoreAction.Delete: Debug.WriteLine($"TODO: Remove {ign.Character} from ignore list."); break; } // TODO OnIgnoreListUpdate?.Invoke(this, EventArgs.Empty); }; _Handlers["LIS"] += (_, c) => { var lis = c as Server_LIS_ChatListUsers; foreach (var character in lis.CharacterData) { var charObj = GetOrCreateCharacter(character[0]); charObj.Gender = JsonEnumConverter.Convert <Genders>(character[1]); charObj.Status = JsonEnumConverter.Convert <CharacterStatus>(character[2]); charObj.StatusMessage = character[3]; } }; // Channel entry related _Handlers["JCH"] += (_, c) => { var jch = c as Server_JCH_ChannelJoin; var chan = GetChannel(jch.Channel); if (jch.Character.Identity != LocalCharacter.Name) { OnChannelUserJoin?.Invoke(this, new ChannelUserEntryEventArgs(chan, GetCharacter(jch.Character.Identity), jch)); } }; _Handlers["LCH"] += (_, c) => { var lch = c as Server_LCH_ChannelLeave; var chan = GetChannel(lch.Channel); if (lch.Character == LocalCharacter.Name) { OnChannelLeave?.Invoke(this, new ChannelEntryEventArgs(chan, lch)); } else { OnChannelUserLeave?.Invoke(this, new ChannelUserEntryEventArgs(chan, GetCharacter(lch.Character), lch)); } }; _Handlers["ICH"] += (_, c) => { var ich = c as Server_ICH_ChannelInitialData; var chan = GetOrCreateChannel(ich.Channel); OnChannelJoin?.Invoke(this, new ChannelEntryEventArgs(chan, ich)); }; // Channel admin related _Handlers["CKU"] += (_, c) => { var cku = c as Server_CKU_ChannelKickCharacter; var chan = GetChannel(cku.Channel); OnChannelUserKicked?.Invoke(this, new ChannelAdminActionEventArgs(chan, GetCharacter(cku.Character), GetCharacter(cku.OP), cku)); }; _Handlers["CBU"] += (_, c) => { var cbu = c as Server_CBU_ChannelBanCharacter; var chan = GetChannel(cbu.Channel); OnChannelUserBanned?.Invoke(this, new ChannelAdminActionEventArgs(chan, GetCharacter(cbu.Character), GetCharacter(cbu.OP), cbu)); }; _Handlers["CUB"] += (_, c) => { var cub = c as Server_CUB_ChannelUnbanCharacter; var chan = GetChannel(cub.Channel); OnChannelUserUnbanned?.Invoke(this, new ChannelAdminActionEventArgs(chan, GetCharacter(cub.Character), GetCharacter(cub.OP), cub)); }; _Handlers["CTU"] += (_, c) => { var ctu = c as Server_CTU_ChannelTimeoutCharacter; var chan = GetChannel(ctu.Channel); OnChannelUserTimedout?.Invoke(this, new ChannelAdminActionEventArgs(chan, GetCharacter(ctu.Character), GetCharacter(ctu.OP), ctu)); }; // Channel status related _Handlers["CDS"] += (_, c) => { var cds = c as Server_CDS_ChannelChangeDescription; var chan = GetChannel(cds.Channel); OnChannelDescriptionChange?.Invoke(this, new ChannelEntryEventArgs <string>(chan, cds.Description, cds)); }; _Handlers["RMO"] += (_, c) => { var rmo = c as Server_RMO_ChannelSetMode; var chan = GetChannel(rmo.Channel); OnChannelModeChange?.Invoke(this, new ChannelEntryEventArgs <ChannelMode>(chan, rmo.Mode, rmo)); }; _Handlers["CSO"] += (_, c) => { var cso = c as Server_CSO_ChannelSetOwner; var chan = GetChannel(cso.Channel); OnChannelOwnerChange?.Invoke(this, new ChannelEntryEventArgs <Character>(chan, GetCharacter(cso.Character), cso)); }; _Handlers["RST"] += (_, c) => { var rst = c as Server_RST_ChannelSetStatus; var chan = GetChannel(rst.Channel); OnChannelStatusChange?.Invoke(this, new ChannelEntryEventArgs <ChannelStatus>(chan, rst.Status, rst)); }; // Channel admin related _Handlers["COA"] += (_, c) => { var coa = c as Server_COA_ChannelMakeOP; var chan = GetChannel(coa.Channel); OnChannelOPAdded?.Invoke(this, new ChannelUserEntryEventArgs(chan, GetCharacter(coa.Character), coa)); }; _Handlers["COR"] += (_, c) => { var cor = c as Server_COR_ChannelRemoveOP; var chan = GetChannel(cor.Channel); chan.PushCommand(cor); OnChannelOPRemoved?.Invoke(this, new ChannelUserEntryEventArgs(chan, GetCharacter(cor.Character), cor)); }; // Channel message related _Handlers["MSG"] += (_, c) => { var msg = c as Server_MSG_ChannelChatMessage; var chan = GetChannel(msg.Channel); OnChannelChatMessage?.Invoke(this, new ChannelUserMessageEventArgs(chan, GetCharacter(msg.Character), msg.Message, msg)); }; _Handlers["LRP"] += (_, c) => { var lrp = c as Server_LRP_ChannelLFRPMessage; var chan = GetChannel(lrp.Channel); OnChannelLFRPMessage?.Invoke(this, new ChannelUserMessageEventArgs(chan, GetCharacter(lrp.Character), lrp.AD, lrp)); }; _Handlers["RLL"] += (_, c) => { var rll = c as Server_RLL_ChannelRollMessage; var chan = GetChannel(rll.Channel); OnChannelRollMessage?.Invoke(this, new ChannelUserMessageEventArgs(chan, GetCharacter(rll.Character), rll.Message, rll)); }; // Character entry related _Handlers["FLN"] += (_, c) => { var fln = c as Server_FLN_CharacterOffline; var character = GetCharacter(fln.Character); if (character == null) { character = new Character(this, new libflist.Character(FListClient, fln.Character)); OnCharacterOffline?.Invoke(this, new CharacterEntryEventArgs(character, fln)); return; } OnCharacterOffline?.Invoke(this, new CharacterEntryEventArgs(character, fln)); character.Status = CharacterStatus.Offline; foreach (var chan in _Channels.Where(C => C.Characters.Contains(character))) { chan.PushCommand(new Server_LCH_ChannelLeave { Channel = chan.ID, Character = character.Name }); } }; _Handlers["NLN"] += (_, c) => { var nln = c as Server_NLN_CharacterOnline; var character = GetOrCreateCharacter(nln.CharacterName); character.Gender = nln.Gender; character.Status = nln.Status; OnCharacterOnline?.Invoke(this, new CharacterEntryEventArgs(character, nln)); }; _Handlers["PRI"] += (_, c) => { var pri = c as Server_PRI_CharacterChatMessage; var character = GetCharacter(pri.Character); character.IsTyping = TypingStatus.Clear; OnCharacterChatMessage?.Invoke(this, new CharacterMessageEventArgs(character, pri.Message, pri)); }; _Handlers["STA"] += (_, c) => { var sta = c as Server_STA_CharacterStatus; var character = GetCharacter(sta.Character); character.Status = sta.Status; character.StatusMessage = sta.Message; OnCharacterStatusChange?.Invoke(this, new CharacterEntryEventArgs <CharacterStatus>(character, sta.Status, sta)); }; _Handlers["TPN"] += (_, c) => { var tpn = c as Server_TPN_CharacterTypingStatus; var character = GetCharacter(tpn.Character); character.IsTyping = tpn.Status; OnCharacterTypingChange?.Invoke(this, new CharacterEntryEventArgs <TypingStatus>(character, tpn.Status, tpn)); }; /* * // Character admin events * public event EventHandler<AdminActionEventArgs> OnCharacterKicked; * public event EventHandler<AdminActionEventArgs> OnCharacterBanned; * public event EventHandler<AdminActionEventArgs> OnCharacterUnbanned; * public event EventHandler<AdminActionEventArgs> OnCharacterTimedout; */ }