--[[ Guild Event Manager by Kiki of European Cho'gall (Alliance) Communication module (parse/send) Chaque message envoyé est de la forme : --[GEM_TOKEN]* - GEM_CMD : Entier -- Type de paquet - Stamp : Entier -- Stamp de l'emetteur au moment de l'envoi du message, relatif au leader de l'event EventID - EventID : String -- EventID de l'event (identifiant unique) - Param : -- Parametres associés au type de paquet Events : ------ - Update/Create Event : - Close Event : Nothing Commands : -------- Each command has at least the following fields : - event leader - event date - ACK type (0 or 1) - player affected - player from [P] Permanent command (stored) [V] Volative command (not stored) Leader commands : - [P] TITULAR : -- Informs player he is in titular list - [P] SUBSTITUTE : -- Informs player he is in substitute list - [P] REPLACEMENT : -- Informs player he is in replacement list - [P] KICK : [Reason] -- Informs player he has been kicked from event - [P] BAN : [Reason] -- Informs player he has been banned from event - [P] UNBAN : -- Informs player he has been unbanned from event - [V] LEADER : -- Informs player he is now the new leader - [V] INFOS : -- Give informations about me Non-leader commands : - [P] SUBSCRIBE : [Comment] -- Subscribe to an event -- (1/0) informs the leader if you want to be put directly in substitute queue (so he will invite you only if he don't find someone to replace you) - [P] UNSUBSCRIBE : [Comment] -- Unsubscribe from an event ]] --------------- Shared variables --------------- GEM_GLOBAL_CMD = "GlobalEventId1"; -- special ev_id tag for global commands GEM_CMD_EVENT_UPDATE = "01"; -- Event updated (or created) GEM_CMD_EVENT_CLOSE = "02"; -- Event closed GEM_CMD_CMD_SUBSCRIBE = "03"; -- Subscribe : GEM_CMD_CMD_UNSUBSCRIBE = "04"; -- Unsubscribe : GEM_CMD_CMD_TITULAR = "05"; -- Titular GEM_CMD_CMD_SUBSTITUTE = "06"; -- Substitute GEM_CMD_CMD_REPLACEMENT = "07"; -- Replacement GEM_CMD_CMD_KICK = "08"; -- Kick GEM_CMD_CMD_BAN = "09"; -- Ban GEM_CMD_CMD_UNBAN = "10"; -- UnBan GEM_CMD_EVENT_LEADER = "11"; -- New event leader GEM_CMD_PLAYER_INFOS = "12"; -- New infos about myself GEM_CMD_CMD_ASSISTANT = "13"; -- Add assistant -- GUI notify values GEM_NOTIFY_NEW_EVENT = 1; GEM_NOTIFY_CLOSE_EVENT = 2; GEM_NOTIFY_EVENT_UPDATE = 3; GEM_NOTIFY_SUBSCRIBER = 4; GEM_NOTIFY_UNSUBSCRIBER = 5; GEM_NOTIFY_MY_SUBSCRIPTION = 6; GEM_NOTIFY_PLAYER_INFOS = 7; -- Other variables GEM_COM_Channels = nil; GEM_COM_LastJoinerTime = 0; --------------- Local variables --------------- --local _GEM_TOKEN = '\35'; -- Debug value --local _GEM_TOKEN_SUB_TOKEN = '\38'; -- Debug value --local _GEM_TOKEN_EMPTY = '\36'; -- Debug value --local _GEM_TOKEN_MORE = '\33'; -- Debug value local _GEM_TOKEN = '\30'; local _GEM_TOKEN_SUB_TOKEN = '\29'; local _GEM_TOKEN_EMPTY = '\28'; local _GEM_TOKEN_MORE = '\27'; local _GEM_PARSE_PATTERN = "([^".._GEM_TOKEN.."]+)"; local _GEM_PARSE_PATTERN_SUB_PATTERN = "([^".._GEM_TOKEN_SUB_TOKEN.."]+)"; local _GEM_NotifyCallBackFunction = nil; local _GEM_IntToClass = { ["1"] = "WARRIOR"; ["2"] = "PALADIN"; ["3"] = "SHAMAN"; ["4"] = "ROGUE"; ["5"] = "MAGE"; ["6"] = "WARLOCK"; ["7"] = "HUNTER"; ["8"] = "DRUID"; ["9"] = "PRIEST" }; local _GEM_ClassToInt = { ["WARRIOR"] = "1"; ["PALADIN"] = "2"; ["SHAMAN"] = "3"; ["ROGUE"] = "4"; ["MAGE"] = "5"; ["WARLOCK"] = "6"; ["HUNTER"] = "7"; ["DRUID"] = "8"; ["PRIEST"] = "9" }; local _GEMComm_ScheduledUpdates = {}; local _GEMComm_Dispatch = {}; local _GEM_MoreCounter = 1; local _GEMComm_MultiplePackets = {}; local _GEM_COM_QueuedMessages = {}; local _GEM_COM_RoutineScheduled = false; local _GEM_COM_LastPlayerInfosSend = 0; -- Consts local _GEM_MAX_STRING_LENGTH = 240; local _GEM_PIPE_ENTITIE = "\127p"; local _GEM_COM_MaxSendPerSchedule = 1; local _GEM_COM_ScheduledTaskInterval = 1.500; local _GEM_COM_PlayersInfosInterval = 5*60; -- 5 min --------------- Internal functions --------------- local function _GEM_COM_NameFromAlias(alias) for name,chantab in GEM_COM_Channels do if(chantab.aliasSet and chantab.aliasSet == alias) then return chantab.id; end end return nil; end _GEM_COM_oldSendChatMessage = SendChatMessage; local function _GEM_COM_newSendChatMessage(msg,sys,lang,name) local id = _GEM_COM_NameFromAlias(sys); if(id) then return _GEM_COM_oldSendChatMessage(string.gsub(msg,"|",_GEM_PIPE_ENTITIE),"CHANNEL",lang,id); end return _GEM_COM_oldSendChatMessage(msg,sys,lang,name); end SendChatMessage = _GEM_COM_newSendChatMessage; local function _GEM_COM_ScheduledPlayerInfos() if(_GEM_COM_LastPlayerInfosSend + _GEM_COM_PlayersInfosInterval < time()) then GEM_ChatDebug(GEM_DEBUG_GLOBAL,"_GEM_COM_ScheduledPlayerInfos : Too long since last player infos send."); GEM_COM_PlayerInfos(); end -- Reschedule routine GEMSystem_Schedule(10,_GEM_COM_ScheduledPlayerInfos); end local function _GEM_COM_ScheduledSendRoutine() local msg_sent = 0; while(table.getn(_GEM_COM_QueuedMessages) > 0 and not GEM_YouAreDrunk) do local channel = _GEM_COM_QueuedMessages[1].channel; local cmd = _GEM_COM_QueuedMessages[1].cmd; local ev_id = _GEM_COM_QueuedMessages[1].ev_id; local stamp = _GEM_COM_QueuedMessages[1].stamp; local msgstring = _GEM_COM_QueuedMessages[1].msgstring; while(GEM_COM_Channels[channel] == nil) do GEM_ChatDebug(GEM_DEBUG_CHANNEL,"_GEM_COM_ScheduledSendRoutine : GEM_COM_Channels["..tostring(channel).."] is nil (left channel ?). Discarding message !"); table.remove(_GEM_COM_QueuedMessages,1); if(table.getn(_GEM_COM_QueuedMessages) == 0) then break; end -- Re-read params local channel = _GEM_COM_QueuedMessages[1].channel; local cmd = _GEM_COM_QueuedMessages[1].cmd; local ev_id = _GEM_COM_QueuedMessages[1].ev_id; local stamp = _GEM_COM_QueuedMessages[1].stamp; local msgstring = _GEM_COM_QueuedMessages[1].msgstring; end if(GEM_COM_Channels[channel].id == 0) -- Channel not init ! then GEM_ChatDebug(GEM_DEBUG_CHANNEL,"_GEM_COM_ScheduledSendRoutine : ChannelID = "..tostring(GEM_COM_Channels[channel].id).." for "..tostring(channel)); GEM_InitChannels(false); if(GEM_COM_Channels[channel].id == 0) -- Still not joined ? then GEM_ChatDebug(GEM_DEBUG_CHANNEL,"_GEM_COM_ScheduledSendRoutine : Channel '"..tostring(channel).."' still not init, rescheduling send later"); break; end end -- DEBUG if(GEM_Events.debug == 1) then if(GetChannelName(channel) ~= GEM_COM_Channels[channel].id) then if(GetChannelName(channel) ~= 0) then GEM_ChatWarning("_GEM_COM_ScheduledSendRoutine : CurrentChanID differs from saved one : "..GetChannelName(channel).." - "..GEM_COM_Channels[channel].id); else GEM_ChatWarning("_GEM_COM_ScheduledSendRoutine : If you've left GEM's channel by hand, ignore this message, otherwise please contact Kiki"); end table.remove(_GEM_COM_QueuedMessages,1); break; end end -- END DEBUG if(cmd == GEM_CMD_EVENT_UPDATE) -- Special case, we must set the real stamp when sending (we specified the offset) then stamp = time() - stamp; end GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_ScheduledSendRoutine : Sending command "..cmd.." for EventID "..ev_id.." on Channel "..channel); local prefix = ""..cmd.."-"..stamp.."-"..ev_id; local msg = prefix..msgstring; while(string.len(msg) > _GEM_MAX_STRING_LENGTH) do local submsg = string.sub(msg,1,_GEM_MAX_STRING_LENGTH); if(string.sub(submsg,string.len(submsg)) == _GEM_TOKEN) then submsg = submsg.._GEM_TOKEN_EMPTY; end submsg = submsg.._GEM_TOKEN.._GEM_TOKEN_MORE.._GEM_MoreCounter; local addmsg = string.sub(msg,_GEM_MAX_STRING_LENGTH+1); if(string.sub(addmsg,1,1) == _GEM_TOKEN) then addmsg = _GEM_TOKEN_EMPTY..addmsg; end msg = prefix.._GEM_TOKEN_MORE.._GEM_MoreCounter.."-"..addmsg; _GEM_COM_newSendChatMessage(submsg,"CHANNEL",nil,GEM_COM_Channels[channel].id); msg_sent = msg_sent + 1; GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_ScheduledSendRoutine : Splitted command, MoreCounter is ".._GEM_MoreCounter.." : "..submsg); end _GEM_MoreCounter = _GEM_MoreCounter + 1; _GEM_COM_newSendChatMessage(msg,"CHANNEL",nil,GEM_COM_Channels[channel].id); msg_sent = msg_sent + 1; GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_ScheduledSendRoutine : Sending last msg part : "..msg); table.remove(_GEM_COM_QueuedMessages,1); if(msg_sent >= _GEM_COM_MaxSendPerSchedule) then break; end end -- Reschedule routine GEMSystem_Schedule(_GEM_COM_ScheduledTaskInterval,_GEM_COM_ScheduledSendRoutine); end local function _GEM_COM_QueueMessage(channel,cmd,ev_id,stamp,msgstring) -- Queue the message table.insert(_GEM_COM_QueuedMessages, { channel=channel, cmd=cmd, ev_id=ev_id, stamp=stamp, msgstring=msgstring }); end local function _GEM_COM_UnpackClasses(clas) local classes = {}; if(clas and clas ~= "") then for c in string.gfind(clas,_GEM_PARSE_PATTERN_SUB_PATTERN) do if(c ~= "") then local _,_,id,mini,maxi,tit,sub,repl = string.find(c,"(%d+):([-]?%d+):([-]?%d+):(%d+):(%d+):(%d+)"); if(id ~= nil) then local name = _GEM_IntToClass[id]; classes[name] = {}; classes[name].min = tonumber(mini,10); classes[name].max = tonumber(maxi,10); classes[name].tit_count = tonumber(tit,10); classes[name].sub_count = tonumber(sub,10); classes[name].repl_count = tonumber(repl,10); end end end end return classes; end local function _GEM_COM_UnpackSubscribers(subs,subtype) local subscribers = {}; local pos = 1; if(subs and subs ~= "") then for c in string.gfind(subs,_GEM_PARSE_PATTERN_SUB_PATTERN) do if(c ~= "") then local _,_,pl_name,id,level_str = string.find(c,"([^:]+):(%d+):(%d+)"); if(id ~= nil) then local class = _GEM_IntToClass[id]; local level = tonumber(level_str,10); tinsert(subscribers, {place = subtype..pos; name = pl_name; guild=GEM_NA_FORMAT; class=class; level=level}); pos = pos + 1; end end end end return subscribers; end local function _GEM_COM_UnpackPlayers(pls) local players = {}; if(pls and pls ~= "") then for c in string.gfind(pls,_GEM_PARSE_PATTERN_SUB_PATTERN) do if(c ~= "") then local _,_,pl_name,id,level_str,stamp_str,forcesub_str,guild,comment = string.find(c,"([^:]+):(%d+):(%d+):(%d+):(%d+):([^:]*):(.*)"); if(id ~= nil) then local class = _GEM_IntToClass[id]; local level = tonumber(level_str,10); local stamp = tonumber(stamp_str,10); local forcesub = tonumber(forcesub_str,10); players[pl_name] = {class=class; level=level; update_time=stamp; forcesub=forcesub; guild=guild; comment=comment}; end end end end return players; end local function _GEM_COM_UnpackBanned(bans) local banned = {}; if(bans and bans ~= "") then for c in string.gfind(bans,_GEM_PARSE_PATTERN_SUB_PATTERN) do if(c ~= "") then local _,_,pl_name,reason = string.find(c,"([^:]+):(.*)"); if(id ~= nil) then banned[pl_name] = reason; end end end end return banned; end local function _GEM_COM_GetPreviousPacket(from,ev_id,w) local _,_,MoreCounter,param = string.find(w,_GEM_TOKEN_MORE.."(%d+)-(.*)"); if(MoreCounter == nil) then GEM_ChatWarning("_GEM_COM_GetPreviousPacket : Failed to find MoreCounter in '"..w.."' from "..from); return nil; end local params = _GEMComm_MultiplePackets[from..ev_id..MoreCounter]; if(params == nil) then --GEM_ChatWarning("_GEM_COM_GetPreviousPacket : Params is nil in '"..w.."' from "..from); return nil; end if(param == _GEM_TOKEN_EMPTY) then param = ""; end params[table.getn(params)] = params[table.getn(params)]..param; return params,MoreCounter; end local function _GEM_COM_SaveMultiplePacket(from,ev_id,w,params) local _,_,MoreCounter = string.find(w,_GEM_TOKEN_MORE.."(%d+)"); if(MoreCounter == nil) then GEM_ChatWarning("_GEM_COM_SaveMultiplePacket : Failed to find MoreCounter in '"..w.."' from "..from); return; end _GEMComm_MultiplePackets[from..ev_id..MoreCounter] = params; end local function _GEM_COM_ClearMultiplePacket(from,ev_id,MoreCounter) _GEMComm_MultiplePackets[from..ev_id..MoreCounter] = nil; end function GEM_COM_PurgeQueueMessageForChannel(channel) local i = 1; while(i <= table.getn(_GEM_COM_QueuedMessages)) do local queue_chan = _GEM_COM_QueuedMessages[i].channel; if(queue_chan == channel) then table.remove(_GEM_COM_QueuedMessages,i); else i = i + 1; end end end --[[ function GEM_COM_ParseChannelMessage Channel parsing function. ]] function GEM_COM_ParseChannelMessage(channel,from,message) if(from == GEM_PlayerName) then return; end; -- Not interested by messages from me GEM_CheckPlayerJoined(channel,from); local _,i,version,cmd_stamp_id = string.find(message,"^]+)>(%d+-%d+-[^%s%d-]+%d+)"); if(cmd_stamp_id == nil) then return; end; local _,_,cmd,stamp_str,ev_id = string.find(cmd_stamp_id,"(%d+)-(%d+)-([^%s%d-]+%d+)"); if(cmd == nil or stamp_str == nil or ev_id == nil) then return; end; local stamp = tonumber(stamp_str,10); if(stamp == nil) then return; end; -- Check version local _,_,major,minor = string.find(version,"([^.]+)%.(.+)"); if(major == nil) then GEM_ChatDebug(GEM_DEBUG_GLOBAL,from.." is using an old major version of GEM."); return; end if(major ~= GEM_MAJOR) then if(major > GEM_MAJOR) then if(GEM_OldVersion == false) then GEM_ChatPrint(GEM_TEXT_UPGRADE_NEEDED); GEM_ChatPrint("GEM home page : http://christophe.calmejane.free.fr/wow/gem"); GEM_OldVersion = true; end else GEM_ChatDebug(GEM_DEBUG_GLOBAL,from.." is using an old major version of GEM."); end return; end if(minor ~= GEM_MINOR) then if(minor > GEM_MINOR) then if(GEM_NewMinorVersion == false) then GEM_ChatPrint(GEM_TEXT_UPGRADE_SUGGESTED); GEM_ChatPrint("GEM home page : http://christophe.calmejane.free.fr/wow/gem"); GEM_NewMinorVersion = true; end else GEM_ChatDebug(GEM_DEBUG_GLOBAL,from.." is using an old minor version of GEM."); end end local msg = strsub(message,i+1); if(ev_id ~= GEM_GLOBAL_CMD and GEM_EVT_CheckExpiredEvent(ev_id)) -- Message for an expired event, just return then return; end if(GEM_Events.realms[GEM_Realm].ignore[ev_id]) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"Event "..ev_id.." is in ignore list, discarding message"); return; end if(_GEMComm_Dispatch[cmd] == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"Unknown command : "..cmd.." from "..from); return; end local params = {}; local MoreCounter = nil; for w in string.gfind(msg,_GEM_PARSE_PATTERN) do if(string.find(w,_GEM_TOKEN_MORE) ~= nil) -- Multiple packet then if(table.getn(params) == 0) -- First param -> Continued packet then params,MoreCounter = _GEM_COM_GetPreviousPacket(from,ev_id,w); if(params == nil) -- Cannot find previous packet, just discard this one then return; end else -- Continued multiple packets _GEM_COM_SaveMultiplePacket(from,ev_id,w,params); MoreCounter = nil; return; end else -- Not multiple packet if(w == nil or w == _GEM_TOKEN_EMPTY) then table.insert(params,""); else table.insert(params,w); end end end if(MoreCounter ~= nil) then _GEM_COM_ClearMultiplePacket(from,ev_id,MoreCounter); end if(ev_id ~= GEM_GLOBAL_CMD and cmd ~= GEM_CMD_EVENT_UPDATE and cmd ~= GEM_CMD_EVENT_CLOSE and cmd ~= GEM_CMD_EVENT_LEADER) -- Not an Event msg (-> a cmd message) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"GEM_COM_ParseChannelMessage : Received command "..cmd.." from "..from.." for EventID "..ev_id); if(GEM_CMD_ReceivedCommand(channel,cmd,from,stamp,ev_id,params) == false) -- This command does not need more processing, don't dispatch, and return now then return; end end GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"GEM_COM_ParseChannelMessage : Dispatching command "..cmd.." from "..from.." for EventID "..ev_id.." : "..message); _GEMComm_Dispatch[cmd](channel,from,stamp,ev_id,params); end local function _GEM_COM_BuildClassesString(classes) local clas = ""; if(classes ~= nil) then for name,tab in classes do clas = clas.._GEM_TOKEN_SUB_TOKEN.._GEM_ClassToInt[name]..":"..tab.min..":"..tab.max..":"..tab.tit_count..":"..tab.sub_count..":"..tab.repl_count; end end return clas; end local function _GEM_COM_BuildSubscribersStrings(event) local tits = ""; local subs = ""; local repls = ""; for pos,tab in event.titulars do tits = tits.._GEM_TOKEN_SUB_TOKEN..tab.name..":".._GEM_ClassToInt[tab.class]..":"..tab.level; end for pos,tab in event.substitutes do subs = subs.._GEM_TOKEN_SUB_TOKEN..tab.name..":".._GEM_ClassToInt[tab.class]..":"..tab.level; end for pos,tab in event.replacements do repls = repls.._GEM_TOKEN_SUB_TOKEN..tab.name..":".._GEM_ClassToInt[tab.class]..":"..tab.level; end return tits,subs,repls; end local function _GEM_COM_BuildPlayersString(event) local pls = ""; for name,tab in event.players do pls = pls.._GEM_TOKEN_SUB_TOKEN..name..":".._GEM_ClassToInt[tab.class]..":"..tab.level..":"..tab.update_time..":"..tab.forcesub..":"..tab.guild..":"..tab.comment; end return pls; end local function _GEM_COM_BuildBannedString(event) local bans = ""; for name,reason in event.banned do bans = bans.._GEM_TOKEN_SUB_TOKEN..name..":"..reason; end return bans; end --[[ function _GEM_COM_SendMessage Low level sending function channel : String -- Channel to send message to cmd : String -- Command to send ev_id : String -- EventId command is refering to stamp : Integer -- TimeStamp of the send (relative to leader of ev_id) params : String/Int -- Params associated with command ]] local function _GEM_COM_SendMessage(channel,cmd,ev_id,stamp,...) if(channel == nil) then channel = GEM_DefaultSendChannel; -- DEBUG GEM_ChatWarning("_GEM_COM_SendMessage : Channel not nil !!"); end local msg = ""; for i=1, arg.n do local val = arg[i]; if(val == nil) then val = _GEM_TOKEN_EMPTY; elseif((type(val) == "string") and (val == "")) then val = _GEM_TOKEN_EMPTY; end; msg = msg.._GEM_TOKEN..val; end _GEM_COM_QueueMessage(channel,cmd,ev_id,stamp,msg); end --[[ function _GEM_COM_PrepareAndSendCommand Low level command storing and sending function ev_id : String -- EventId command is refering to cmd : String -- Command to store/send pl_dest : String -- Name of player the command is destinated to pl_src : String -- Name of player the command is originating from ... : String/Int -- Params associated with command ]] local function _GEM_COM_PrepareAndSendCommand(ev_id,cmd,pl_dest,pl_src,...) local stamp = time() - GEM_GetOffsetTime(ev_id); local cmd_id = pl_dest.."-"..pl_src.."-"..stamp.."-"..cmd; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; local params = {}; if(event == nil) then return; end tinsert(params,event.leader); tinsert(params,event.ev_date); tinsert(params,"0"); -- Not ACKed tinsert(params,pl_dest); tinsert(params,pl_src); for i=1, arg.n do -- Build params array to store command if(arg[i] == nil) then tinsert(params,""); else tinsert(params,arg[i]); end end -- Create the CMD struct for this ev_id, if it does not exist if(GEM_Events.realms[GEM_Realm].commands[ev_id] == nil) then GEM_CMD_CreateCommands(event.channel,ev_id,event.leader,event.ev_date); end -- Save the command GEM_CMD_CreateCommandId(ev_id,cmd_id,cmd,stamp,params); _GEM_COM_SendMessage(event.channel,cmd,ev_id,stamp,event.leader,event.ev_date,0,pl_dest,pl_src,unpack(arg)); end --------------- Process functions --------------- --[[ Process EventUpdate : Params[1] = update_time (INT) Params[2] = leader (STRING) Params[3] = ev_date (INT) Params[4] = ev_place (STRING) Params[5] = ev_comment (STRING) Params[6] = max_count (INT) Params[7] = min_lvl (INT) Params[8] = max_lvl (INT) Params[9] = classes (STRING) Params[10] = Titulars (STRING) Params[11] = Substitutes (STRING) Params[12] = Replacements (STRING) Params[13] = Sorttype (STRING) Params[14] = Closed comment (STRING) ]] local function _GEM_COM_Process_EventUpdate(channel,from,stamp,ev_id,params) local update_time = tonumber(params[1],10); local ev_date = tonumber(params[3],10); local max_count = tonumber(params[6],10); local min_lvl = tonumber(params[7],10); local max_lvl = tonumber(params[8],10); if(update_time == nil or ev_date == nil or max_count == nil or min_lvl == nil or max_lvl == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_EventUpdate : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_EventUpdate : From="..from.." at "..date("%c",stamp).." for "..ev_id); if(GEM_EVT_UpdateEvent(channel,ev_id,update_time,params[2],ev_date,params[4],params[5],max_count,min_lvl,max_lvl,_GEM_COM_UnpackClasses(params[9]),_GEM_COM_UnpackSubscribers(params[10],"P"),_GEM_COM_UnpackSubscribers(params[11],"S"),_GEM_COM_UnpackSubscribers(params[12],"R"),params[13],params[14])) then if((GEM_Events.realms[GEM_Realm].events[ev_id].offset_time == 0) or (params[2] == from)) -- Update offset, if I don't have one, or if msg is from the leader then GEM_SetOffsetStamp(ev_id,stamp); end end end --[[ Process EventClose : Params[1] = Comment (STRING) ]] local function _GEM_COM_Process_EventClose(channel,from,stamp,ev_id,params) GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_EventClose : Close event not used right anymore !!"); --GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_EventClose : From="..from.." at "..date("%c",stamp).." for "..ev_id); --GEM_EVT_ClearEvent(ev_id,params[1],false); --GEM_QUE_RemoveEventFromQueue(ev_id); end --[[ Process EventLeader : Params[1] = update_time (INT) Params[2] = new leader (STRING) Params[3] = ev_date (INT) Params[4] = ev_place (STRING) Params[5] = ev_comment (STRING) Params[6] = max_count (INT) Params[7] = min_lvl (INT) Params[8] = max_lvl (INT) Params[9] = classes (STRING) Params[10] = Titulars (STRING) Params[11] = Substitutes (STRING) Params[12] = Replacements (STRING) Params[13] = Sorttype (STRING) Params[13] = Players (STRING) Params[13] = Banned (STRING) ]] local function _GEM_COM_Process_EventLeader(channel,from,stamp,ev_id,params) if(GEM_IsMyReroll(params[2])) -- If I'm the new leader, process then local update_time = tonumber(params[1],10); local ev_date = tonumber(params[3],10); local max_count = tonumber(params[6],10); local min_lvl = tonumber(params[7],10); local max_lvl = tonumber(params[8],10); GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_EventLeader : From="..from.." at "..date("%c",stamp).." for "..ev_id..". I'm the new leader !"); -- Remove event, so I can re-create it GEM_Events.realms[GEM_Realm].events[ev_id] = nil; GEM_EVT_AddEvent(channel,ev_id,time(),params[2],ev_date,params[4],params[5],max_count,min_lvl,max_lvl,_GEM_COM_UnpackClasses(params[9]),_GEM_COM_UnpackSubscribers(params[10],"P"),_GEM_COM_UnpackSubscribers(params[11],"S"),_GEM_COM_UnpackSubscribers(params[12],"R"),params[13]); GEM_Events.realms[GEM_Realm].events[ev_id].players = _GEM_COM_UnpackPlayers(params[14]); GEM_Events.realms[GEM_Realm].events[ev_id].banned = _GEM_COM_UnpackBanned(params[15]); -- Update my list GEM_NotifyGUI(GEM_NOTIFY_EVENT_UPDATE,ev_id); -- Broadcast event, and we are done --GEM_COM_BroadcastEvent(GEM_Events.realms[GEM_Realm].events[ev_id]); GEM_COM_NotifyEventUpdate(ev_id); end end --[[ Process CmdSubscribe : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params Params[6] = Class (STRING) -- Class of the subscribing player Params[7] = Guild (STRING) -- Guild of the subscribing player Params[8] = Level (INT) -- Level of the subscribing player Params[9] = ForceSub (INT) -- <1/0> Force or not, subscribing player to replacement queue Params[10] = Comment (STRING) -- Subscribe comment string ]] local function _GEM_COM_Process_CmdSubscribe(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_level = tonumber(params[8],10); local forcesub = tonumber(params[9],10); local leader = params[1]; local pl_name = params[5]; local pl_class = params[6]; local pl_guild = params[7]; local pl_comment = params[10]; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) then return; end if(ev_date == nil or pl_level == nil or forcesub == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdSubscribe : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdSubscribe : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4].." : "..params[6].." - "..pl_level.." - "..params[10]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdSubscribe : Processing a command not for me"); end -- Check player's level if(pl_level < event.min_lvl or pl_level > event.max_lvl) then GEM_COM_KickPlayer(ev_id,pl_name,GEM_TEXT_ERR_LEVEL_FAILED); return; end if((event.players[pl_name] == nil) or (stamp > event.players[pl_name].update_time)) -- First time I see this, or the command is more recent than the last received then if(GEM_EVT_IsBanned(ev_id,pl_name)) -- Check player for BAN then GEM_COM_BanPlayer(ev_id,pl_name); -- Resend a BAN command return; -- Then return (just ignore this CMD) end GEM_SUB_CreateSubscriber(ev_id,stamp,pl_name,pl_class,pl_guild,pl_level,pl_comment,forcesub,0); -- Creates the subscribe GEM_NotifyGUI(GEM_NOTIFY_SUBSCRIBER,ev_id,pl_name); end end --[[ Process CmdUnsubscribe : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params Params[6] = Comment (STRING) -- Unsubscribe comment string ]] local function _GEM_COM_Process_CmdUnsubscribe(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local leader = params[1]; local pl_name = params[5]; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) then return; end if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdUnsubscribe : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdUnsubscribe : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4].." : "..params[6]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdUnsubscribe : Processing a command not for me"); end if((event.players[pl_name] ~= nil) and (stamp > event.players[pl_name].update_time)) -- Player exists, and the command is more recent than the last received then GEM_SUB_RemoveSubscriber(ev_id,pl_name,params[6]); -- Removes the subscriber GEM_NotifyGUI(GEM_NOTIFY_UNSUBSCRIBER,ev_id,pl_name); end end --[[ Process CmdTitular : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params ]] local function _GEM_COM_Process_CmdTitular(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_name = params[4]; if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdTitular : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdTitular : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdTitular : Processing a command not for me"); end GEM_SUB_SetTitular(ev_id,stamp,pl_name); end --[[ Process CmdSubstitute : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params ]] local function _GEM_COM_Process_CmdSubstitute(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_name = params[4]; if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdSubstitute : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdSubstitute : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdSubstitute : Processing a command not for me"); end GEM_SUB_SetSubstitute(ev_id,stamp,pl_name); end --[[ Process CmdReplacement : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params ]] local function _GEM_COM_Process_CmdReplacement(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_name = params[4]; if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdReplacement : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdReplacement : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdReplacement : Processing a command not for me"); end GEM_SUB_SetReplacement(ev_id,stamp,pl_name); end --[[ Process CmdKick : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params Params[6] = Reason (STRING) -- Reason of the kick ]] local function _GEM_COM_Process_CmdKick(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_name = params[4]; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdKick : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdKick : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4].." : "..params[6]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdKick : Processing a command not for me"); end GEM_Events.realms[GEM_Realm].subscribed[ev_id] = nil; GEM_Events.realms[GEM_Realm].kicked[ev_id] = params[6]; if(event == nil) then return; end GEM_ChatPrint(GEM_TEXT_CHAT_KICKED..event.ev_place.." ("..event.leader..") : "..params[6]); GEM_NotifyGUI(GEM_NOTIFY_MY_SUBSCRIPTION,ev_id); end --[[ Process CmdBan : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params Params[6] = Reason (STRING) -- Reason of the ban ]] local function _GEM_COM_Process_CmdBan(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_name = params[4]; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdBan : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdBan : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4].." : "..params[6]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdBan : Processing a command not for me"); end GEM_Events.realms[GEM_Realm].subscribed[ev_id] = nil; GEM_Events.realms[GEM_Realm].banned[ev_id] = params[6]; if(event == nil) then return; end GEM_ChatPrint(GEM_TEXT_CHAT_BANNED..event.ev_place.." ("..event.leader..") : "..params[6]); GEM_NotifyGUI(GEM_NOTIFY_MY_SUBSCRIPTION,ev_id); end --[[ Process CmdUnBan : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params ]] local function _GEM_COM_Process_CmdUnBan(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_name = params[4]; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdUnBan : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdUnBan : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdUnBan : Processing a command not for me"); end GEM_Events.realms[GEM_Realm].banned[ev_id] = nil; if(event == nil) then return; end GEM_ChatPrint(GEM_TEXT_CHAT_UNBANNED..event.ev_place.." ("..event.leader..")"); GEM_NotifyGUI(GEM_NOTIFY_MY_SUBSCRIPTION,ev_id); end --[[ Process PlayerInfos : Params[1] = name (STRING) Params[2] = guild (STRING) Params[3] = location (STRING) Params[4] = level (INT) Params[5] = class (STRING) Params[6] = officer (INT) Params[7] = rank name (STRING) Params[8] = rank idx (INT) Params[9] = GEM-Version (STRING) Params[10] = Comment (STRING) ]] local function _GEM_COM_Process_Global_PlayerInfos(channel,from,stamp,ev_id,params) local pl_level = tonumber(params[4],10); local g_rank_idx = tonumber(params[8],10); if(params[6] == nil or params[6] == "") then params[6] = "0"; end local officer = tonumber(params[6],10); GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_Global_PlayerInfos : From="..from.." at "..date("%c",stamp).." Fill infos : "..params[2].." : "..params[3].." : "..pl_level.." : "..params[5]); GEM_PLAY_FillPlayerInfos(channel,params[1],params[2],params[3],pl_level,params[5],officer,params[7],g_rank_idx,params[9],params[10]); GEM_NotifyGUI(GEM_NOTIFY_PLAYER_INFOS); end --[[ Process CmdAssistant : -- Common Cmd params Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from -- Specific Cmd params ]] local function _GEM_COM_Process_CmdAssistant(channel,from,stamp,ev_id,params) local ev_date = tonumber(params[2],10); local pl_name = params[4]; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_PROTOCOL,"_GEM_COM_Process_CmdAssistant : WARNING : Malformed event from "..from.." for EventID "..ev_id); return; end GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_COM_Process_CmdAssistant : From="..from.." at "..date("%c",stamp).." for "..ev_id.." : From "..params[5].." to "..params[4]); if(not GEM_IsMyReroll(params[4])) -- Not for me ?? then GEM_ChatWarning("_GEM_COM_Process_CmdAssistant : Processing a command not for me"); end GEM_Events.realms[GEM_Realm].assistant[ev_id] = true; if(event == nil) then return; end GEM_ChatPrint(GEM_TEXT_CHAT_ASSISTANT..event.ev_place.." ("..event.leader..")"); GEM_NotifyGUI(GEM_NOTIFY_MY_SUBSCRIPTION,ev_id); end --------------- Exported functions --------------- GEM_oldChatFrame_OnEvent = ChatFrame_OnEvent; function GEM_newChatFrame_OnEvent(event) local channel = nil; if(arg9) then channel = strlower(arg9); end -- There is a channel if ( strsub(event, 1, 8) == "CHAT_MSG" and channel and GEM_Realm and GEM_IsChannelInList(channel)) then local type = strsub(event, 10); if(string.find(type,"^CHANNEL")) then if(type == "CHANNEL") then if(string.find(arg1,"^ strlen(value) ) then -- arg9 is the channel name without the number in front... if ( ((arg7 > 0) and (this.zoneChannelList[index] == arg7)) or (strlower(value) == channel) ) 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,_GEM_PIPE_ENTITIE,"|"); -- Check for alias if(GEM_COM_Channels[channel].aliasSet and GEM_COM_Channels[channel].aliasSet ~= "") -- Alias set ? Show alias name then event = "CHAT_MSG_"..GEM_COM_Channels[channel].aliasSet; arg4 = ""; --arg9 = GEM_COM_Channels[channel].aliasSet; end elseif(type ~= "CHANNEL_LIST") then return; end end end GEM_oldChatFrame_OnEvent(event); end ChatFrame_OnEvent = GEM_newChatFrame_OnEvent; function GEM_COM_InitRoutines() -- Schedule routine if(_GEM_COM_RoutineScheduled == false) then GEMSystem_Schedule(0.050,_GEM_COM_ScheduledSendRoutine); GEMSystem_Schedule(10,_GEM_COM_ScheduledPlayerInfos); _GEM_COM_RoutineScheduled = true; end end function GEM_COM_JoinChannel(channel,password) if(GetChannelName(channel) == 0) then GEM_ConnectedPlayers[channel] = {}; -- Reset players GEM_ChatDebug(GEM_DEBUG_CHANNEL,"GEM_JoinChannel : Joining channel "..channel.." with password ("..tostring(password)..")"); local zoneChannel, channelName = JoinChannelByName(channel,password,DEFAULT_CHAT_FRAME:GetID()); if(channelName) then channel = channelName; end if(not zoneChannel) then return; end local i = 1; while(DEFAULT_CHAT_FRAME.channelList[i]) do i = i + 1; end DEFAULT_CHAT_FRAME.channelList[i] = channel; DEFAULT_CHAT_FRAME.zoneChannelList[i] = zoneChannel; else GEM_ChatDebug(GEM_DEBUG_CHANNEL,"GEM_COM_JoinChannel : Already in channel "..channel); end end function GEM_COM_LeaveChannel(channel) if(channel and GEM_COM_Channels[channel] and GEM_COM_Channels[channel].id ~= 0) then GEM_ChatDebug(GEM_DEBUG_CHANNEL,"GEM_COM_LeaveChannel : Leaving channel "..channel); LeaveChannelByName(channel); GEM_COM_Channels[channel].id = 0; GEM_COM_Channels[channel].aliasSet = nil; end end function GEM_Comm_test() --GEM_ChatPrint("ok"); end function GEM_COM_AliasChannel(channel,alias,slash) if(alias == nil or alias == "") then GEM_ChatDebug(GEM_DEBUG_CHANNEL,"GEM_COM_AliasChannel : Not installing Channel Alias and Slash command, no alias defined"); return; end if(GEM_IsChannelJoined(channel)) then local id = GEM_COM_Channels[channel].id; local upper = string.upper(slash); GEM_COM_Channels[channel].aliasSet = upper; ChatTypeInfo[upper] = ChatTypeInfo["CHANNEL"..id]; ChatTypeInfo[upper].sticky = 1; setglobal("CHAT_MSG_"..upper,alias); setglobal("CHAT_"..upper.."_GET", "["..alias.."] %s:\32"); setglobal("CHAT_"..upper.."_SEND", alias..":\32"); SlashCmdList[upper] = GEM_Comm_test; setglobal("SLASH_"..upper.."1", "/"..slash); GEM_ChatDebug(GEM_DEBUG_CHANNEL,"GEM_COM_AliasChannel : Channel Alias and Slash command initialized !"); else GEM_ChatDebug(GEM_DEBUG_CHANNEL,"GEM_COM_AliasChannel : Not installing Channel Alias and Slash command, channel not joined yet"); end end function GEM_COM_UnAliasChannel(channel,alias,slash) if(alias and alias ~= "") then local upper = string.upper(slash); if(DEFAULT_CHAT_FRAME.editBox.stickyType == upper) then DEFAULT_CHAT_FRAME.editBox.chatType = "SAY"; DEFAULT_CHAT_FRAME.editBox.stickyType = "SAY"; end setglobal("CHAT_MSG_"..upper, nil); setglobal("CHAT_"..upper.."_GET", nil); setglobal("CHAT_"..upper.."_SEND", nil); SlashCmdList[upper] = nil; setglobal("SLASH_"..upper.."1", nil); GEM_COM_Channels[channel].aliasSet = nil; GEM_ChatDebug(GEM_DEBUG_CHANNEL,"GEM_COM_UnAliasChannel : Channel Alias and Slash command Uninitialized !"); end end --[[ function GEM_COM_BroadcastEvent : Broadcast an event event : Array -- The event struct to broadcast ]] function GEM_COM_BroadcastEvent(event) if(event == nil) then return; end; local clas = _GEM_COM_BuildClassesString(event.classes); local tits,subs,repls = _GEM_COM_BuildSubscribersStrings(event); _GEM_COM_SendMessage(event.channel,GEM_CMD_EVENT_UPDATE,event.id,event.offset_time,event.update_time,event.leader,event.ev_date,event.ev_place,event.ev_comment,event.max_count,event.min_lvl,event.max_lvl,clas,tits,subs,repls,event.sorttype,event.closed_comment); end --[[ function GEM_COM_SendAckCommand : Send an ACK for a cmd ev_id : String -- Event ID cmd_id : String -- Cmd ID to ACK ]] function GEM_COM_SendAckCommand(ev_id,cmd_id) local cmds = GEM_CMD_GetCommands(ev_id); cmds.cmds[cmd_id].LastSend = time(); _GEM_COM_SendMessage(cmds.channel,cmds.cmds[cmd_id].cmd,ev_id,cmds.cmds[cmd_id].stamp,cmds.leader,cmds.ev_date,1,cmds.cmds[cmd_id].params[4],cmds.cmds[cmd_id].params[5]); end --[[ function GEM_COM_SendForwardCommand : Forward the command to the new leader ]] function GEM_COM_SendForwardCommand(channel,cmd,ev_id,stamp,params) _GEM_COM_SendMessage(channel,cmd,ev_id,stamp,unpack(params)); end --[[ function GEM_COM_BroadcastCommand Broadcast an ACK for a cmd ev_id : String -- Event ID cmd_id : String -- Cmd ID to send ]] function GEM_COM_BroadcastCommand(ev_id,cmd_id) local cmds = GEM_Events.realms[GEM_Realm].commands[ev_id]; local cmdtab = cmds.cmds[cmd_id]; if(cmdtab == nil) then GEM_ChatWarning("GEM_COM_BroadcastCommand : Failed to find cmd_id '"..cmd_id.."'"); return; end if(not GEM_CMD_IsCommandAcked(ev_id,cmd_id)) then _GEM_COM_SendMessage(cmds.channel,cmdtab.cmd,ev_id,cmdtab.stamp,unpack(cmdtab.params)); end end function GEM_NotifyGUI(cmd,...) if(_GEM_NotifyCallBackFunction == nil) then return; end; _GEM_NotifyCallBackFunction(cmd,unpack(arg)); end --------------- GUI Exported functions --------------- --[[ - GUI ENTRY POINT function GEM_SetNotifyCallback : Sets the Callback function for GUI notifications. CBFunc : Function -- The CB function : void (*func)(NotifyCommand,...) ]] function GEM_SetNotifyCallback(CBfunc) _GEM_NotifyCallBackFunction = CBfunc; end --[[ - GUI ENTRY POINT function GEM_COM_CreateNewEvent : Creates a new event and broadcast it. channel : String -- Channel where is event is to be created ev_date : Integer -- Date/Hour of the event (number of sec since 1970) ev_place : String -- Place of the event ev_comment : String -- Comment for the event max_count : Integer -- Max players for the event min_lvl : Integer -- Minimum level max_lvl : Integer -- Maximim level classes : Array{class={min,max,tit_count,sub_count,repl_count},...} -- Min/Max/Titulars/Substitutes/Replacements players of each listed class for the event sorttype : String -- Sorting type to use -- Returns the event ID (String) used to Broadcast the event ]] function GEM_COM_CreateNewEvent(channel,ev_date,ev_place,ev_comment,max_count,min_lvl,max_lvl,classes,sorttype) local ev_id; local creat_time = time(); local selected = GEM_GetSelectedReroll(); local infos = GEM_Events.realms[GEM_Realm].my_names[selected]; GEM_Events.next_event_id = GEM_Events.next_event_id + 1; ev_id = selected..GEM_Events.next_event_id; GEM_EVT_AddEvent(channel,ev_id,creat_time,selected,ev_date,ev_place,ev_comment,max_count,min_lvl,max_lvl,classes,{},{},{},sorttype); GEM_SUB_CreateSubscriber(ev_id,creat_time,selected,infos.class,infos.guild,infos.level,"",0,0); GEM_NotifyGUI(GEM_NOTIFY_NEW_EVENT,ev_id); return ev_id; end --[[ - GUI ENTRY POINT function GEM_COM_ChangeLeader : Changes the leader of an event, and send him all needed data. New leader must have subscribed, and be online. ev_id : String -- Event ID to change leader of new_leader : String -- Name of the new leader ]] function GEM_COM_ChangeLeader(ev_id,new_leader) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event ~= nil) then if(event.players[new_leader] == nil) then GEM_ChatPrint("Cannot change leader of EventID "..ev_id..", because "..new_leader.." never subscribed to the event"); return; end if(not GEM_IsPlayerConnected(event.channel,new_leader)) then GEM_ChatPrint("Cannot change leader of EventID "..ev_id..", because "..new_leader.." is not connected"); return; end -- Tag myself as having subscribed to the event local myself = event.players[event.leader]; if(myself ~= nil) then GEM_EVT_SubscribeMyself(ev_id,event.leader,myself.guild,myself.level,myself.class,myself.comment,myself.forcesub,"1"); -- Titular end local clas = _GEM_COM_BuildClassesString(event.classes); local tits,subs,repls = _GEM_COM_BuildSubscribersStrings(event); local pls = _GEM_COM_BuildPlayersString(event); local bans = _GEM_COM_BuildBannedString(event); _GEM_COM_SendMessage(event.channel,GEM_CMD_EVENT_LEADER,event.id,time(),event.update_time,new_leader,event.ev_date,event.ev_place,event.ev_comment,event.max_count,event.min_lvl,event.max_lvl,clas,tits,subs,repls,event.sorttype,pls,bans); -- Remove the event, and set new forwarder GEM_Events.realms[GEM_Realm].forward[ev_id] = new_leader; event.leader = new_leader; -- Change leader, and wait for update GEM_NotifyGUI(GEM_NOTIFY_EVENT_UPDATE,ev_id); end end local function _GEM_COM_NotifyEventUpdate_Schedule(ev_id) -- Scheduled CB function if(_GEMComm_ScheduledUpdates[ev_id] == nil or GEM_Events.realms[GEM_Realm].events[ev_id] == nil) then return; end local event = GEM_Events.realms[GEM_Realm].events[ev_id]; event.update_time = time(); GEM_COM_BroadcastEvent(event); _GEMComm_ScheduledUpdates[ev_id] = nil; end --[[ - GUI ENTRY POINT function GEM_NotifyEventUpdate : Notify all players of an update in the event (called only by leader of ev_id). ev_id : String -- Event ID to notify an update from ]] function GEM_COM_NotifyEventUpdate(ev_id) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event ~= nil) then if(not GEM_IsMyReroll(event.leader)) then GEM_ChatPrint("GEM_COM_NotifyEventUpdate : This Event ID does not belong to me ("..ev_id..")"); return; end if(_GEMComm_ScheduledUpdates[ev_id] == nil) -- Not yet scheduled for update then _GEMComm_ScheduledUpdates[ev_id] = 1; GEMSystem_Schedule(10,_GEM_COM_NotifyEventUpdate_Schedule,ev_id); -- Schedule in 10s end GEM_NotifyGUI(GEM_NOTIFY_EVENT_UPDATE,ev_id); end end --[[ - GUI ENTRY POINT function GEM_COM_CloseEvent : Closes an event and broadcast it (called only by leader of ev_id). ev_id : String -- Event ID to close comment : String -- comment for closed event ]] function GEM_COM_CloseEvent(ev_id,comment) --local event = GEM_Events.realms[GEM_Realm].events[ev_id]; --if(event and (event.LastCloseSent == nil or event.LastCloseSent < GEM_COM_LastJoinerTime)) --then --_GEM_COM_SendMessage(event.channel,GEM_CMD_EVENT_CLOSE,ev_id,time(),comment); --event.LastCloseSent = time(); --end --GEM_EVT_ClearEvent(ev_id,comment,false); GEM_ChatWarning("Call to GEM_COM_CloseEvent"); end --[[ - GUI ENTRY POINT function GEM_COM_Subscribe : Subscribes to an event and broadcast it (Sent by player, once). ev_id : String -- Event ID to subscribe to forcesub : Int -- <1/0> If you want to be put directly in replacement queue ("take me if you can't find anyone") comment : String -- Comment to send with subscription -- Returns nil if ok, error string otherwise. ]] function GEM_COM_Subscribe(ev_id,forcesub,comment) local selected = GEM_GetSelectedReroll(); local infos = GEM_Events.realms[GEM_Realm].my_names[selected]; local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) -- Event does not exist anymore then return "Event "..ev_id.." does not exist anymore"; end if(GEM_IsMyReroll(event.leader)) -- I'm the leader then return "Cannot re-subscribe my own event"; end if(GEM_Events.realms[GEM_Realm].banned[ev_id] ~= nil) then GEM_ChatPrint("I am banned from EventID "..ev_id.." : "..GEM_Events.realms[GEM_Realm].banned[ev_id]); return "I'm banned from Event "..ev_id.." : "..GEM_Events.realms[GEM_Realm].banned[ev_id]; end if(GEM_Events.realms[GEM_Realm].subscribed[ev_id] ~= nil) then GEM_ChatDebug(GEM_DEBUG_GLOBAL,"GEM_COM_Subscribe : Already tagged for subscription !!"); return "Internal error : Already tagged for subscription"; end _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_SUBSCRIBE,event.leader,selected,infos.class,infos.guild,infos.level,forcesub,comment); GEM_EVT_SubscribeMyself(ev_id,selected,infos.class,infos.level,infos.class,comment,forcesub,"0"); -- Tag myself as having sent a subscription GEM_NotifyGUI(GEM_NOTIFY_MY_SUBSCRIPTION,ev_id); return nil; end --[[ - GUI ENTRY POINT function GEM_COM_Unsubscribe : Unsubscribes from an event and broadcast it (Sent by player, once). ev_id : String -- Event ID to unsubscribe from comment : String -- Comment to send with unsubscription ]] function GEM_COM_Unsubscribe(ev_id,comment) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) -- Event does not exist anymore then return; end if(GEM_IsMyReroll(event.leader)) -- Cannot remove ourself then GEM_ChatPrint("GEM_COM_Unsubscribe : Cannot unsubscribe from your own event !"); return; end if(GEM_Events.realms[GEM_Realm].subscribed[ev_id] == nil) then GEM_ChatDebug(GEM_DEBUG_GLOBAL,"GEM_COM_Unsubscribe : I'm not tagged as having sent subscription !!"); return; end _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_UNSUBSCRIBE,event.leader,GEM_Events.realms[GEM_Realm].subscribed[ev_id].name,comment); GEM_Events.realms[GEM_Realm].subscribed[ev_id] = nil; GEM_Events.realms[GEM_Realm].assistant[ev_id] = nil; -- Reset assistant status GEM_NotifyGUI(GEM_NOTIFY_MY_SUBSCRIPTION,ev_id); end --[[ - GUI ENTRY POINT function GEM_COM_TitularPlayer : Informs a player he is titular, from an event I'm the leader. ev_id : String -- Event ID pl_name : String -- Player to inform ]] function GEM_COM_TitularPlayer(ev_id,pl_name) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event ~= nil) then if(not GEM_IsMyReroll(event.leader)) then GEM_ChatPrint("GEM_COM_TitularPlayer : This Event ID does not belong to me ("..ev_id..")"); return; end if(GEM_IsMyReroll(pl_name)) -- pl_name is me ! then return; end _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_TITULAR,pl_name,event.leader); end end --[[ - GUI ENTRY POINT function GEM_COM_SubstitutePlayer : Informs a player he is Substitute, from an event I'm the leader. ev_id : String -- Event ID pl_name : String -- Player to inform ]] function GEM_COM_SubstitutePlayer(ev_id,pl_name) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event ~= nil) then if(not GEM_IsMyReroll(event.leader)) then GEM_ChatPrint("GEM_COM_SubstitutePlayer : This Event ID does not belong to me ("..ev_id..")"); return; end if(GEM_IsMyReroll(pl_name)) -- pl_name is me ! then return; end local stamp = time(); _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_SUBSTITUTE,pl_name,event.leader); end end --[[ - GUI ENTRY POINT function GEM_COM_ReplacementPlayer : Informs a player he is Replacement, from an event I'm the leader. ev_id : String -- Event ID pl_name : String -- Player to inform ]] function GEM_COM_ReplacementPlayer(ev_id,pl_name) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event ~= nil) then if(not GEM_IsMyReroll(event.leader)) then GEM_ChatPrint("GEM_COM_ReplacementPlayer : This Event ID does not belong to me ("..ev_id..")"); return; end if(GEM_IsMyReroll(pl_name)) -- pl_name is me ! then return; end local stamp = time(); _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_REPLACEMENT,pl_name,event.leader); end end --[[ - GUI ENTRY POINT function GEM_COM_KickPlayer : Kicks a player from an event I'm the leader. ev_id : String -- Event ID pl_name : String -- Player to kick from event reason : String -- Why you kick him ]] function GEM_COM_KickPlayer(ev_id,pl_name,reason) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) -- Event does not exist anymore then return; end if(GEM_IsMyReroll(pl_name)) -- Cannot remove ourself then GEM_ChatPrint("Cannot kick myself !"); return; end _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_KICK,pl_name,event.leader,reason); GEM_SUB_RemoveSubscriber(ev_id,pl_name,reason); -- Removes the subscriber GEM_NotifyGUI(GEM_NOTIFY_UNSUBSCRIBER,ev_id,pl_name); end --[[ - GUI ENTRY POINT function GEM_COM_BanPlayer : Bans a player from an event I'm the leader. ev_id : String -- Event ID pl_name : String -- Player to ban from event reason : String -- Why you ban him ]] function GEM_COM_BanPlayer(ev_id,pl_name,reason) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) -- Event does not exist anymore then return; end if(GEM_IsMyReroll(pl_name)) -- Cannot remove ourself then GEM_ChatPrint("Cannot ban myself !"); return; end _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_BAN,pl_name,event.leader,reason); GEM_SUB_RemoveSubscriber(ev_id,pl_name,reason); -- Removes the subscriber GEM_EVT_SetBanned(ev_id,pl_name,reason); -- And now ban him GEM_NotifyGUI(GEM_NOTIFY_UNSUBSCRIBER,ev_id,pl_name); end --[[ - GUI ENTRY POINT function GEM_COM_UnBanPlayer : UnBans a player from an event I'm the leader. ev_id : String -- Event ID pl_name : String -- Player to unban from event ]] function GEM_COM_UnBanPlayer(ev_id,pl_name) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) -- Event does not exist anymore then return; end _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_UNBAN,pl_name,event.leader); GEM_EVT_SetUnBanned(ev_id,pl_name); -- And now unban him end --[[ - GUI ENTRY POINT function GEM_COM_PlayerInfos : Sends my player informations to all channels. ]] function GEM_COM_PlayerInfos() for channel,chantab in GEM_COM_Channels do if(chantab.id ~= 0) then _GEM_COM_LastPlayerInfosSend = time(); _GEM_COM_SendMessage(channel,GEM_CMD_PLAYER_INFOS,GEM_GLOBAL_CMD,time(),GEM_PLAY_GetMyPlayerInfos(channel)); end end end --[[ - GUI ENTRY POINT function GEM_COM_PlayerInfosSingle : Sends my player informations to a single channel. ]] function GEM_COM_PlayerInfosSingle(channel) _GEM_COM_LastPlayerInfosSend = time(); _GEM_COM_SendMessage(channel,GEM_CMD_PLAYER_INFOS,GEM_GLOBAL_CMD,time(),GEM_PLAY_GetMyPlayerInfos(channel)); end --[[ - GUI ENTRY POINT function GEM_COM_AddAssistant : Promotes a player assistant of an event I'm the leader. ev_id : String -- Event ID pl_name : String -- Player to promote assistant ]] function GEM_COM_AddAssistant(ev_id,pl_name) local event = GEM_Events.realms[GEM_Realm].events[ev_id]; if(event == nil) -- Event does not exist anymore then return; end event.assistants[pl_name] = 1; _GEM_COM_PrepareAndSendCommand(ev_id,GEM_CMD_CMD_ASSISTANT,pl_name,event.leader); end --------------- Plugin API --------------- --[[ - PLUGIN API ENTRY POINT function GEM_COM_API_AddDispatchFunction : Adds a command dispatch callback function opcode : String -- Unique Opcode you want to use (must represent an Int) func : Function -- Function to be called when you receive this Opcode Prototype for command related to an event = function CallbackFunc(channel,from,stamp,ev_id,params) : - channel = Channel event is linked to - from = Sender of the message - stamp = Stamp the command was issued by the author of the cmd (not necessary same person than 'from') - ev_id = EventId the command is related to - Common Cmd 'params' = Params[1] = leader (STRING) -- Leader of the event Params[2] = ev_date (INT) -- Date of the event Params[3] = ack (STRING) -- 1 or 0, if the packet is an ack to the command or not Params[4] = pl_dest (STRING) -- Name of player the command is destinated to Params[5] = pl_src (STRING) -- Name of player the command is originating from Followed by specific Cmd 'params' you pass to the Send function Prototype for global command = function CallbackFunc(channel,from,stamp,ev_id,params) : - Same as previously, but ev_id = GEM_GLOBAL_CMD, and no 'common params', only 'specific params' Global commands are volatile (not stored nor forwarded by other players), while event related commands are stored and broadcasted when a new player arrives. Returns true on success, false if opcode is already in use ]] function GEM_COM_API_AddDispatchFunction(opcode,func) if(_GEMComm_Dispatch[tostring(opcode)] ~= nil) then return false; end _GEMComm_Dispatch[tostring(opcode)] = func; return true; end --[[ - PLUGIN API ENTRY POINT function GEM_COM_API_SendVolatileCommand : Sends a volatile command (not stored nor forwarded by other players) channel : String -- Channel to send message to opcode : String -- Unique Opcode you want to use (must represent an Int) params : Table -- Array of your params (must be Int index based, use table.insert()) Returns true on success. ]] function GEM_COM_API_SendVolatileCommand(channel,opcode,params) _GEM_COM_SendMessage(channel,tostring(opcode),GEM_GLOBAL_CMD,time(),unpack(params)); return true; end --[[ - PLUGIN API ENTRY POINT function GEM_COM_API_SendCommand : Sends an event related command (stored and broadcasted when a new player arrives) channel : String -- Channel to send message to opcode : String -- Unique Opcode you want to use (must represent an Int) ev_id : String -- EventId command is related to pl_dest : String -- Recipient player the message is addressed to pl_src : String -- Originator player (often the event.leader) params : Table -- Array of your params (must be Int index based, use table.insert()) Returns true on success, false if event is unknown. ]] function GEM_COM_API_SendCommand(channel,opcode,ev_id,pl_dest,pl_src,params) if(GEM_Events.realms[GEM_Realm].events[ev_id] == nil) then return false; end _GEM_COM_PrepareAndSendCommand(ev_id,tostring(opcode),pl_dest,pl_src,unpack(params)); return true; end --------------- Init dispatch table --------------- _GEMComm_Dispatch[GEM_CMD_EVENT_UPDATE] = _GEM_COM_Process_EventUpdate; _GEMComm_Dispatch[GEM_CMD_EVENT_CLOSE] = _GEM_COM_Process_EventClose; _GEMComm_Dispatch[GEM_CMD_EVENT_LEADER] = _GEM_COM_Process_EventLeader; _GEMComm_Dispatch[GEM_CMD_CMD_SUBSCRIBE] = _GEM_COM_Process_CmdSubscribe; _GEMComm_Dispatch[GEM_CMD_CMD_UNSUBSCRIBE] = _GEM_COM_Process_CmdUnsubscribe; _GEMComm_Dispatch[GEM_CMD_CMD_TITULAR] = _GEM_COM_Process_CmdTitular; _GEMComm_Dispatch[GEM_CMD_CMD_SUBSTITUTE] = _GEM_COM_Process_CmdSubstitute; _GEMComm_Dispatch[GEM_CMD_CMD_REPLACEMENT] = _GEM_COM_Process_CmdReplacement; _GEMComm_Dispatch[GEM_CMD_CMD_KICK] = _GEM_COM_Process_CmdKick; _GEMComm_Dispatch[GEM_CMD_CMD_BAN] = _GEM_COM_Process_CmdBan; _GEMComm_Dispatch[GEM_CMD_CMD_UNBAN] = _GEM_COM_Process_CmdUnBan; _GEMComm_Dispatch[GEM_CMD_PLAYER_INFOS] = _GEM_COM_Process_Global_PlayerInfos; _GEMComm_Dispatch[GEM_CMD_CMD_ASSISTANT] = _GEM_COM_Process_CmdAssistant;