SIMPLECOMM_DEBUG = false; -- output debug information SIMPLECOMM_CHARACTERSPERTICK_MAX = 512; -- char per tick SIMPLECOMM_TICK_DELAY = 1; -- delay in second between tick local PIPE_ENTITIE = "\127p"; SimpleComm_Channel = nil; SimpleComm_Password = nil; SimpleComm_ChatFrame = nil; SimpleComm_JoinHandler = nil; SimpleComm_LeaveHandler = nil; local SimpleComm_Handler = nil; local SimpleComm_Serialize = nil; local SimpleComm_Unserialize = nil; local SimpleComm_FilterText = nil; local SimpleComm_oldChatFrame_OnEvent = nil; SimpleComm_oldSendChatMessage = nil; local SimpleComm_chanSlashCmd = nil; local SimpleComm_chanSlashCmdUpper = nil; local SimpleComm_FlagListener = nil; local SimpleComm_messageQueueHeader = {}; local SimpleComm_messageQueueLast = SimpleComm_messageQueueHeader; -- .delay -- .to -- .serialized -- .next local SimpleComm_sentBytes = 0; local SimpleComm_channelName = nil; SimpleComm_Disconnected = {}; SimpleComm_DisconnectedMessage = string.format(ERR_CHAT_PLAYER_NOT_FOUND_S, "(.*)"); SimpleComm_AFK_MESSAGE = string.format(MARKED_AFK_MESSAGE, "(.*)"); SimpleComm_DND_MESSAGE = string.format(MARKED_DND, "(.*)"); SimpleComm_Flags = {}; SimpleComm_FlagTestMessage = "-= SimpleComm test message =-"; SimpleComm_WaitingForFlagTest = false; --------------------------------------------------------------------------------- -- -- Debug -- --------------------------------------------------------------------------------- local function DEBUG_MSG(msg, high) if (SIMPLECOMM_DEBUG) then if high then ChatFrame1:AddMessage(msg, 1.0, 0.0, 0.25); else ChatFrame1:AddMessage(msg, 1.0, 1.0, 0.75); end end end --------------------------------------------------------------------------------- -- -- On load -- --------------------------------------------------------------------------------- function SimpleComm_OnLoad() this:RegisterEvent("CHAT_MSG_WHISPER"); this:RegisterEvent("CHAT_MSG_CHANNEL"); this:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE"); end --------------------------------------------------------------------------------- -- -- Init -- --------------------------------------------------------------------------------- local function SimpleComm_joinChannel() DEBUG_MSG("[SimpleComm_joinChannel] begin"); if ( GetChannelName(SimpleComm_Channel) == 0) then local zoneChannel, channelName = JoinChannelByName(SimpleComm_Channel, SimpleComm_Password, SimpleComm_ChatFrame:GetID()); if (zoneChannel ~= 0) then local name = SimpleComm_Channel; if ( channelName ) then name = channelName; end local i = 1; while ( SimpleComm_ChatFrame.channelList[i] ) do i = i + 1; end SimpleComm_ChatFrame.channelList[i] = name; SimpleComm_ChatFrame.zoneChannelList[i] = zoneChannel; end DEBUG_MSG("[SimpleComm_joinChannel] end - false"); return false; else DEBUG_MSG("[SimpleComm_joinChannel] end - true"); return true; end end local function SimpleComm_leaveChannel() if ( GetChannelName(SimpleComm_Channel) ~= 0) then LeaveChannelByName(SimpleComm_Channel); SimpleComm_Channel = nil; SimpleComm_Password = nil; end end local function SimpleComm_initChannel() DEBUG_MSG("[SimpleComm_initChannel] begin"); SimpleComm_messageQueue = { }; SimpleComm.update = SIMPLECOMM_TICK_DELAY; DEBUG_MSG("[SimpleComm_initChannel] end"); return SimpleComm_joinChannel(); end local function SimpleComm_doneChannel() SimpleComm.update = nil; SimpleComm_leaveChannel(); end --------------------------------------------------------------------------------- -- -- Alias -- --------------------------------------------------------------------------------- local function SimpleComm_SetAliasChannel() id = GetChannelName( SimpleComm_Channel ); if (id~=0 and SimpleComm_aliasMustBeSet) then local id = GetChannelName( SimpleComm_Channel ); ChatTypeInfo[SimpleComm_chanSlashCmdUpper] = ChatTypeInfo["CHANNEL"..id]; ChatTypeInfo[SimpleComm_chanSlashCmdUpper].sticky = 1; setglobal("CHAT_MSG_"..SimpleComm_chanSlashCmdUpper, SimpleComm_chanAlias); setglobal("CHAT_"..SimpleComm_chanSlashCmdUpper.."_GET", "["..SimpleComm_chanAlias.."] %s:\32"); setglobal("CHAT_"..SimpleComm_chanSlashCmdUpper.."_SEND", SimpleComm_chanAlias..":\32"); SlashCmdList[SimpleComm_chanSlashCmdUpper] = SimpleComm_test; setglobal("SLASH_"..SimpleComm_chanSlashCmdUpper.."1", "/"..SimpleComm_chanSlashCmd); -- hook only one time if (not SimpleComm_oldSendChatMessage) then SimpleComm_oldSendChatMessage = SendChatMessage; SendChatMessage = SimpleComm_newSendChatMessage; end SimpleComm_aliasMustBeSet = false; end end local function SimpleComm_UnsetAliasChannel() if (SimpleComm_chanSlashCmdUpper) then if ( DEFAULT_CHAT_FRAME.editBox.stickyType == string.upper(SimpleComm_chanSlashCmdUpper) ) then DEFAULT_CHAT_FRAME.editBox.chatType = "SAY" DEFAULT_CHAT_FRAME.editBox.stickyType = "SAY" end setglobal("CHAT_MSG_"..SimpleComm_chanSlashCmdUpper, nil); setglobal("CHAT_"..SimpleComm_chanSlashCmdUpper.."_GET", nil); setglobal("CHAT_"..SimpleComm_chanSlashCmdUpper.."_SEND", nil); SlashCmdList[SimpleComm_chanSlashCmdUpper] = nil; setglobal("SLASH_"..SimpleComm_chanSlashCmdUpper.."1", nil); SimpleComm_aliasMustBeSet = true; end end function SimpleComm_newSendChatMessage(msg, sys, lang, name) -- DEBUG_MSG("SimpleComm_newSendChatMessage("..msg..","..sys..","..NoNil(lang)..","..NoNil(name)..")"); if (sys == SimpleComm_chanSlashCmdUpper) then return SimpleComm_oldSendChatMessage(string.gsub(msg, "|", PIPE_ENTITIE), "CHANNEL", lang, GetChannelName( SimpleComm_Channel )); else return SimpleComm_oldSendChatMessage(msg, sys, lang, name); end end; function SimpleComm_test() DEBUG_MSG("ok"); end --------------------------------------------------------------------------------- -- -- AFK/DND status -- --------------------------------------------------------------------------------- function SimpleComm_SetFlag(player, flag, message) if player==nil then player = UnitName("player"); if SimpleComm_FlagListener then SimpleComm_FlagListener(flag, message); end end if flag then SimpleComm_Flags[player] = { flag=flag; message=message; count = 0 }; else SimpleComm_Flags[player] = nil; end end function SimpleComm_GetFlag(player) if SimpleComm_Flags[player] then return SimpleComm_Flags[player].flag, SimpleComm_Flags[player].message; else return nil; end end function SimpleComm_AddWhisper(player) if SimpleComm_Flags[player] then SimpleComm_Flags[player].count = SimpleComm_Flags[player].count +1; end end function SimpleComm_DelWhisper(player) if SimpleComm_Flags[player] then if SimpleComm_Flags[player].count>0 then SimpleComm_Flags[player].count = SimpleComm_Flags[player].count -1; return true; end end return false; end function SimpleComm_SendFlagTest() SimpleComm_WaitingForFlagTest = time(); SendChatMessage(SimpleComm_FlagTestMessage, "WHISPER", nil, UnitName("player")); end --------------------------------------------------------------------------------- -- -- Envois -- --------------------------------------------------------------------------------- local function SimpleComm_SendQueue(elapsed) -- DEBUG_MSG("[SimpleComm_SendQueue] begin"); local clearAFK = GetCVar("autoClearAFK"); SetCVar("autoClearAFK", 0); -- GetLanguageByIndex(1), GetDefaultLanguage() SimpleComm_sentBytes = 0; SimpleComm_channelName = GetChannelName(SimpleComm_Channel); local previousMessage = SimpleComm_messageQueueHeader; local message = SimpleComm_messageQueueHeader.next; while message do -- update delay if message.delay then message.delay = message.delay-elapsed; if message.delay<=0 then message.delay = nil; end end if message.delay then -- skip the current message previousMessage = message; message = message.next; else -- check chat traffic SimpleComm_sentBytes = SimpleComm_sentBytes + string.len(message.serialized); if SimpleComm_sentBytes > SIMPLECOMM_CHARACTERSPERTICK_MAX then SimpleComm_sentBytes = SimpleComm_sentBytes - string.len(message.serialized); previousMessage = SimpleComm_messageQueueLast; break; end -- send message if message.to then if not SimpleComm_Disconnected[message.to] then -- DEBUG_MSG("Envois a("..message.to..") de("..message.serialized..")"); SendChatMessage(message.serialized, "WHISPER", nil, message.to); SimpleComm_AddWhisper(message.to); else -- Ignore the message since the player is offline. SimpleComm_sentBytes = SimpleComm_sentBytes - string.len(message.serialized); end else -- DEBUG_MSG("Envois a tous de("..message.serialized..")"); SendChatMessage(message.serialized, "CHANNEL", nil, SimpleComm_channelName); end -- delete current message in queue previousMessage.next = message.next; -- go to next message (previousMessage keeps the same value) message = message.next end end SimpleComm_messageQueueLast = previousMessage; SetCVar("autoClearAFK", clearAFK); if (SimpleComm_sentBytes > 0) then DEBUG_MSG("Octets envoyes:"..SimpleComm_sentBytes, true); end -- DEBUG_MSG("[SimpleComm_SendQueue] end"); end --------------------------------------------------------------------------------- -- -- Reception -- --------------------------------------------------------------------------------- local function SimpleComm_ParseMessage(author, text) local message = SimpleComm_Unserialize(text); if ((message) and (SimpleComm_Handler)) then SimpleComm_Handler(author, message); end end function SimpleComm_ParseEvent(event) if (SimpleComm_Channel) then -- event=CHAT_MSG_CHANNEL; arg1=chat message; arg2=author; arg3=language; arg4=channel name with number; arg8=channel number; arg9=channel name without number if ((event == "CHAT_MSG_CHANNEL") and (arg9 == SimpleComm_Channel)) then -- DEBUG_MSG("Reception depuis le channel:"..arg1); SimpleComm_Disconnected[arg2] = nil; SimpleComm_ParseMessage(arg2, arg1); elseif (event == "CHAT_MSG_WHISPER") then -- DEBUG_MSG("Reception de "..arg2..":"..arg1); SimpleComm_Disconnected[arg2] = nil; SimpleComm_ParseMessage(arg2, arg1); elseif ((event == "CHAT_MSG_CHANNEL_NOTICE") and (arg9 == SimpleComm_Channel)) then if (arg1 == "YOU_JOINED") then if (SimpleComm_Password) then SetChannelPassword(SimpleComm_Channel, SimpleComm_Password); end if (SimpleComm_chanSlashCmd) then SimpleComm_SetAliasChannel(); end if (SimpleComm_JoinHandler) then SimpleComm_JoinHandler(); end elseif (arg1 == "YOU_LEFT") then if (SimpleComm_chanSlashCmd) then SimpleComm_UnsetAliasChannel(); end if (SimpleComm_LeaveHandler) then SimpleComm_LeaveHandler(); end end end end end function SimpleComm_newChatFrame_OnEvent(event) if (SimpleComm_Channel) then if ((event == "CHAT_MSG_CHANNEL") and (arg9 == SimpleComm_Channel)) then -- Hide if this is an internal message if SimpleComm_FilterText(arg1) then return; end -- the message is shown in this ChatFrame ? local info; local found = 0; local channelLength = strlen(arg4); for index, value in this.channelList do if ( channelLength > strlen(value) ) then -- arg9 is the channel name without the number in front... if ( ((arg7 > 0) and (this.zoneChannelList[index] == arg7)) or (strupper(value) == strupper(arg9)) ) then found = 1; info = ChatTypeInfo["CHANNEL"..arg8]; break; end end end if ( (found == 0) or not info ) then return; end -- unpack PIPE_ENTITIE arg1 = string.gsub(arg1, PIPE_ENTITIE, "|") if (SimpleComm_chanSlashCmdUpper) then event = "CHAT_MSG_"..SimpleComm_chanSlashCmdUpper; arg4 = ""; -- channel name with number end end if (event == "CHAT_MSG_SYSTEM") then local iStart, iEnd, playerName = string.find(arg1, SimpleComm_DisconnectedMessage); if iStart then if SimpleComm_Disconnected[playerName] then if time()-SimpleComm_Disconnected[playerName] < 2 then return; end else SimpleComm_Disconnected[playerName] = time(); end end local iStart, iEnd, message = string.find(arg1, SimpleComm_AFK_MESSAGE); if iStart or arg1==MARKED_AFK then SimpleComm_SetFlag(nil, "AFK", message); end local iStart, iEnd, message = string.find(arg1, SimpleComm_DND_MESSAGE); if iStart then SimpleComm_SetFlag(nil, "DND", message); end if arg1==CLEARED_AFK or arg1==CLEARED_DND then SimpleComm_SetFlag(nil, nil, nil); end end if (event == "CHAT_MSG_WHISPER") then if SimpleComm_FilterText(arg1) or arg1==SimpleComm_FlagTestMessage then return; end end if (event == "CHAT_MSG_WHISPER_INFORM") then if SimpleComm_FilterText(arg1) or arg1==SimpleComm_FlagTestMessage then return; end end if (event == "CHAT_MSG_CHANNEL_JOIN") and (arg9 == SimpleComm_Channel) then SimpleComm_Disconnected[arg2] = nil; return; end if (event == "CHAT_MSG_CHANNEL_LEAVE") and (arg9 == SimpleComm_Channel) then -- to avoid bug #1315237 : guess that player is offline if he isn't on the channel SimpleComm_Disconnected[arg2] = time(); return; end if event == "CHAT_MSG_AFK" or event == "CHAT_MSG_DND" then if SimpleComm_DelWhisper(arg2) then return; elseif SimpleComm_WaitingForFlagTest and arg2==UnitName("player") then -- whisper to myself, and SimpleComm is waiting for the AFK/DND status if (SimpleComm_WaitingForFlagTest-time())<10 then -- event before 10 seconds -> the player is AFK/DND if event=="CHAT_MSG_AFK" then SimpleComm_SetFlag(nil, "AFK", arg1); elseif event=="CHAT_MSG_DND" then SimpleComm_SetFlag(nil, "DND", arg1); end SimpleComm_WaitingForFlagTest = false; return else -- event 10 seconds after the init -> the player wrote and sent a whisper to himself while he is AFK/DND. SimpleComm_WaitingForFlagTest = false; end end end else if event=="CHAT_MSG_CHANNEL" or event=="CHAT_MSG_WHISPER" or event=="CHAT_MSG_WHISPER_INFORM" then if SimpleComm_FilterText and SimpleComm_FilterText(arg1) then return; end end end SimpleComm_oldChatFrame_OnEvent(event); end SimpleComm_oldChatFrame_OnEvent = ChatFrame_OnEvent; ChatFrame_OnEvent = SimpleComm_newChatFrame_OnEvent; --------------------------------------------------------------------------------- -- -- Timer -- --------------------------------------------------------------------------------- function SimpleComm_OnUpdate(elapsed) if (this.update) then this.update = this.update - elapsed; if (this.update <=0) then SimpleComm_SendQueue(SIMPLECOMM_TICK_DELAY - this.update); this.update = SIMPLECOMM_TICK_DELAY; end elseif (this.initChannel) then this.initChannel = this.initChannel - elapsed; if (this.initChannel <= 0) then SimpleComm_initChannel(); this.initChannel = nil; end end end --------------------------------------------------------------------------------- -- -- Hook into Ephemeral -- --------------------------------------------------------------------------------- local function initEphemeralHook() if ep and ep.VERSION_NUMERIC then ep.UnregisterForEvent( "CHAT_MSG_WHISPER", ep.RespondToWhisper ) ep.UnregisterForEvent( "CHAT_MSG_WHISPER_INFORM", ep.RespondToWhisperNotice ) ep.RegisterForEvent( "CHAT_MSG_WHISPER", SimpleComm_EphemeralRespondToWhisper ) ep.RegisterForEvent( "CHAT_MSG_WHISPER_INFORM", SimpleComm_EphemeralRespondToWhisperNotice ) end end if ep and not ep.UnregisterForEvent then function ep.UnregisterForEvent(event, callback) if ep.RegisteredEvents[ event ] then for index, currentCB in ep.RegisteredEvents[ event ] do if currentCB == callback then table.remove( ep.RegisteredEvents[ event ], index); end end end end end function SimpleComm_EphemeralRespondToWhisper( event, parameters ) if not SimpleComm_FilterText(parameters[1]) then ep.RespondToWhisper(event, parameters); end end function SimpleComm_EphemeralRespondToWhisperNotice( event, parameters ) if not SimpleComm_FilterText(parameters[1]) then ep.RespondToWhisperNotice(event, parameters); end end --------------------------------------------------------------------------------- -- -- Fonctions publiques -- --------------------------------------------------------------------------------- function SimpleComm_SendMessage(who, msg, delay) if not(who and SimpleComm_Disconnected[who]) then SimpleComm_messageQueueLast.next = {to=who; serialized=SimpleComm_Serialize(msg); delay=delay }; SimpleComm_messageQueueLast = SimpleComm_messageQueueLast.next; end end function SimpleComm_SendRawMessage(who, message, delay) if not(who and SimpleComm_Disconnected[who]) then SimpleComm_messageQueueLast.next = {to=who; serialized=message; delay=delay }; SimpleComm_messageQueueLast = SimpleComm_messageQueueLast.next; end end function SimpleComm_PreInit(FilterText) SimpleComm_FilterText = FilterText; end function SimpleComm_Init(Channel, Password, ChatFrame, OnJoin, OnLeave, OnMessage, Serialize, Unserialize, FilterText) DEBUG_MSG("[SimpleComm_Init] begin"); -- Pour la reception SimpleComm_Handler = OnMessage; SimpleComm_JoinHandler = OnJoin; SimpleComm_LeaveHandler = OnLeave; SimpleComm_Serialize = Serialize; SimpleComm_Unserialize = Unserialize; SimpleComm_FilterText = FilterText; SimpleComm_ChatFrame = ChatFrame; -- Init Channel SimpleComm_Channel = Channel; SimpleComm_Password = Password; local onChannelNow = SimpleComm_initChannel(); -- Init hook into Ephemeral initEphemeralHook(); -- AFK/DND test for myself SimpleComm_SendFlagTest(); -- if (onChannelNow) then SimpleComm_JoinHandler(); end -- Set timer SimpleComm:Show(); DEBUG_MSG("[SimpleComm_Init] end"); end function SimpleComm_InitAlias(chanSlashCmd, chanAlias) DEBUG_MSG("[SimpleComm_InitAlias] begin"); -- unset previous alias if (SimpleComm_chanSlashCmd) then SimpleComm_UnsetAliasChannel(); end -- set alias SimpleComm_chanSlashCmd = chanSlashCmd; SimpleComm_chanSlashCmdUpper = string.upper(chanSlashCmd); SimpleComm_chanAlias = chanAlias; SimpleComm_aliasMustBeSet = true; SimpleComm_SetAliasChannel(); DEBUG_MSG("[SimpleComm_InitAlias] end"); end function SimpleComm_SetChannel(Channel, Password) if (Channel ~= SimpleComm_Channel) then -- done if (SimpleComm_chanSlashCmd) then SimpleComm_UnsetAliasChannel(); end SimpleComm_doneChannel(); -- set channel SimpleComm_Channel = Channel; SimpleComm_Password = Password; -- init alias / joinHandler local onChannelNow = (GetChannelName(SimpleComm_Channel) ~= 0); if (onChannelNow) then SimpleComm_JoinHandler(); if (SimpleComm_chanSlashCmd) then SimpleComm_SetAliasChannel(); end end -- call SimpleComm_initChannel in 2 seconds SimpleComm.initChannel = 2; end end function SimpleComm_SetFlagListener(flagListener) SimpleComm_FlagListener = flagListener; end