--[[ Guild Event Manager by Kiki of European Cho'gall (Alliance) Commands module (handle) ]] --------------- Shared variables --------------- --------------- Local variables --------------- local _GEM_CMD_CloseEventSends = {}; local _GEM_CMD_AutoAckCorrespondance = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSCRIBE] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSCRIBE][GEM_CMD_CMD_SUBSCRIBE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSCRIBE][GEM_CMD_CMD_UNSUBSCRIBE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_UNSUBSCRIBE] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_UNSUBSCRIBE][GEM_CMD_CMD_SUBSCRIBE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_UNSUBSCRIBE][GEM_CMD_CMD_UNSUBSCRIBE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_TITULAR] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_TITULAR][GEM_CMD_CMD_TITULAR] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_TITULAR][GEM_CMD_CMD_SUBSTITUTE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_TITULAR][GEM_CMD_CMD_REPLACEMENT] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_TITULAR][GEM_CMD_CMD_KICK] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_TITULAR][GEM_CMD_CMD_BAN] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSTITUTE] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSTITUTE][GEM_CMD_CMD_TITULAR] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSTITUTE][GEM_CMD_CMD_SUBSTITUTE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSTITUTE][GEM_CMD_CMD_REPLACEMENT] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSTITUTE][GEM_CMD_CMD_KICK] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_SUBSTITUTE][GEM_CMD_CMD_BAN] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_REPLACEMENT] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_REPLACEMENT][GEM_CMD_CMD_TITULAR] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_REPLACEMENT][GEM_CMD_CMD_SUBSTITUTE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_REPLACEMENT][GEM_CMD_CMD_REPLACEMENT] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_REPLACEMENT][GEM_CMD_CMD_KICK] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_REPLACEMENT][GEM_CMD_CMD_BAN] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_KICK] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_KICK][GEM_CMD_CMD_TITULAR] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_KICK][GEM_CMD_CMD_SUBSTITUTE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_KICK][GEM_CMD_CMD_REPLACEMENT] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_KICK][GEM_CMD_CMD_KICK] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_KICK][GEM_CMD_CMD_BAN] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_BAN] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_BAN][GEM_CMD_CMD_TITULAR] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_BAN][GEM_CMD_CMD_SUBSTITUTE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_BAN][GEM_CMD_CMD_REPLACEMENT] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_BAN][GEM_CMD_CMD_KICK] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_BAN][GEM_CMD_CMD_BAN] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_UNBAN] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_UNBAN][GEM_CMD_CMD_KICK] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_UNBAN][GEM_CMD_CMD_UNBAN] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_ASSISTANT] = {}; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_ASSISTANT][GEM_CMD_CMD_UNSUBSCRIBE] = 1; _GEM_CMD_AutoAckCorrespondance[GEM_CMD_CMD_ASSISTANT][GEM_CMD_CMD_ASSISTANT] = 1; --------------- Internal functions --------------- --[[ function _GEM_CMD_CheckExpiredCommand Checks if the Event has expired yet (well 10h after) ev_id : String -- EventID ev_date : Integer -- Event's date -- Returns True if the event has expired. False otherwise ]] local function _GEM_CMD_CheckExpiredCommand(ev_id,ev_date) if(ev_id == nil or ev_date == nil) then GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_CMD_CheckExpiredCommand : ev_id or ev_date is nil. Set as expired !"); return true; end local tim = time(); if((ev_date + GEM_ExpirationTime) < (tim-GEM_GetOffsetTime(ev_id))) then GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_CMD_CheckExpiredCommand : Command expired for Event "..ev_id.." ! ("..date("%c",ev_date).."--"..date("%c",tim)..")"); GEM_EVT_ClearEvent(ev_id,"Expired command",true); return true; end return false; end local function _GEM_CMD_AckCommand(ev_id,cmd_id) GEM_Events.realms[GEM_Realm].commands[ev_id].cmds[cmd_id].acked = 1; end --[[ _GEM_CMD_CheckCommandForward : 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 Returns true if command must be processed, false if it has been forwarded to the new leader ]] local function _GEM_CMD_CheckCommandForward(channel,cmd,from,stamp,ev_id,params) local forwarder = GEM_Events.realms[GEM_Realm].forward[ev_id]; -- Check if we have a forwarder set if(forwarder ~= nil) then if(cmd == GEM_CMD_CMD_SUBSCRIBE or cmd == GEM_CMD_CMD_UNSUBSCRIBE) -- For leader commands, we must forward then -- Build new params local new_params = {}; for i=1,table.getn(params) do table.insert(new_params,params[i]); end; new_params[1] = forwarder; new_params[4] = forwarder; if(new_params[3] == "1") -- A ACK then GEM_ChatWarning("_GEM_CMD_CheckCommandForward : Params[3] is acked. Must creat new_params entierely"); new_params[3] = "0"; end -- Store new command local cmd_id = forwarder.."-"..params[5].."-"..stamp.."-"..cmd; GEM_CMD_CreateCommandId(ev_id,cmd_id,cmd,stamp,new_params); -- Send the forwarded message GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_CMD_CheckCommandForward : Forwarding "..from.."'s cmd "..cmd.." from "..params[1].." to "..forwarder); GEM_COM_SendForwardCommand(channel,cmd,ev_id,stamp,new_params); return false; end end return true; end function _GEM_CMD_PurgeMultipleCommands_Sorting(a,b) if(a.stamp < b.stamp) then return true; else return false; end end local function _GEM_CMD_PurgeMultipleCommands(ev_id,cmd_id,from) local thiscmd = GEM_Events.realms[GEM_Realm].commands[ev_id].cmds[cmd_id].cmd; local thisautoack = _GEM_CMD_AutoAckCorrespondance[thiscmd]; -- First, sort cmds by stamp local cmds = {}; for cmdid,cmdtab in GEM_Events.realms[GEM_Realm].commands[ev_id].cmds do if(from == cmdtab.params[5]) -- This cmd is from 'from' too, add it to the list then table.insert(cmds,{ id=cmdid, cmd=cmdtab.cmd, stamp=cmdtab.stamp, acked=cmdtab.acked }); end end table.sort(cmds,_GEM_CMD_PurgeMultipleCommands_Sorting); -- Now check for auto acked cmds for i,cmd in cmds do if(cmd.id == cmd_id) -- Found our cmd, stop parsing then break; end if(thisautoack[cmd.cmd]) -- This older command must be auto-acked then GEM_ChatDebug(GEM_DEBUG_COMMANDS,"_GEM_CMD_PurgeMultipleCommands : Auto acking CmdId "..cmd.id.." because of "..cmd_id); _GEM_CMD_AckCommand(ev_id,cmd.id); end end end local function _GEM_CMD_IsTooSoonCmd(ev_id,cmd_id) if(ev_id == nil or cmd_id == nil) then GEM_ChatWarning("_GEM_CMD_IsTooSoonCmd : ev_id or cmd_id is nil : "..tostring(ev_id).." : "..tostring(cmd_id)); return true; end if(GEM_Events.realms[GEM_Realm].commands[ev_id].cmds[cmd_id].LastSend and GEM_Events.realms[GEM_Realm].commands[ev_id].cmds[cmd_id].LastSend > GEM_COM_LastJoinerTime) -- Sending too soon ? then return true; end return false; end --------------- Exported functions --------------- function GEM_CMD_IsCommandAcked(ev_id,cmd_id) return GEM_Events.realms[GEM_Realm].commands[ev_id].cmds[cmd_id].acked == 1; end function GEM_CMD_CreateCommands(channel,ev_id,leader,ev_date) local s_cmd = {} s_cmd.cmds = {}; s_cmd.channel = channel; s_cmd.leader = leader; s_cmd.ev_date = ev_date; GEM_Events.realms[GEM_Realm].commands[ev_id] = s_cmd; GEM_ChatDebug(GEM_DEBUG_COMMANDS,"GEM_CMD_CreateCommands : Creating cmds for eventID "..ev_id); end function GEM_CMD_CreateCommandId(ev_id,cmd_id,cmd,stamp,params) local s_cmd = {}; s_cmd.cmd = cmd; s_cmd.stamp = stamp; s_cmd.acked = 0; s_cmd.params = params; GEM_Events.realms[GEM_Realm].commands[ev_id].cmds[cmd_id] = s_cmd; GEM_ChatDebug(GEM_DEBUG_COMMANDS,"GEM_CMD_CreateCommandId : Creating a new cmdID "..cmd_id.." for eventID "..ev_id); _GEM_CMD_PurgeMultipleCommands(ev_id,cmd_id,params[5]); end function GEM_CMD_GetCommands(ev_id) return GEM_Events.realms[GEM_Realm].commands[ev_id]; end --[[ GEM_CMD_ReceivedCommand : 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 ]] function GEM_CMD_ReceivedCommand(channel,cmd,from,stamp,ev_id,params) local cmd_id = params[4].."-"..params[5].."-"..stamp.."-"..cmd; local ev_date = tonumber(params[2]); local must_process = false; -- First check if command is not expired if(_GEM_CMD_CheckExpiredCommand(ev_id,ev_date)) then return must_process; end -- Check for unknown event if I'm leader if(GEM_IsMyReroll(params[1]) and GEM_Events.realms[GEM_Realm].events[ev_id] == nil) -- Unknown event then GEM_ChatDebug(GEM_DEBUG_COMMANDS,"GEM_CMD_ReceivedCommand : I'm leader of EventID "..ev_id..", but I don't know it."); 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(channel,ev_id,params[1],ev_date); end -- Then check if commandID exists if(GEM_Events.realms[GEM_Realm].commands[ev_id].cmds[cmd_id] == nil) then GEM_CMD_CreateCommandId(ev_id,cmd_id,cmd,stamp,params); end GEM_QUE_RemoveCommandFromQueue(ev_id,cmd_id); -- Remove from queue. It will be resent if needed if(params[3] == "1") -- A ACK then GEM_ChatDebug(GEM_DEBUG_COMMANDS,"GEM_CMD_ReceivedCommand : Received an ACK from "..from.." for cmdID : "..cmd_id); _GEM_CMD_AckCommand(ev_id,cmd_id); else -- A command (not a ACK) -- Check if I already have a ACK for this if(GEM_CMD_IsCommandAcked(ev_id,cmd_id)) -- I have a ACK then if(not _GEM_CMD_IsTooSoonCmd(ev_id,cmd_id)) then GEM_ChatDebug(GEM_DEBUG_COMMANDS,"GEM_CMD_ReceivedCommand : I already have a ACK for cmdID "..cmd_id..". Broadcasting my ACK"); GEM_COM_SendAckCommand(ev_id,cmd_id); -- Broadcast the ACK end elseif(GEM_IsMyReroll(params[4])) -- This command is for me, ACK it then GEM_ChatDebug(GEM_DEBUG_COMMANDS,"GEM_CMD_ReceivedCommand : Got cmdID "..cmd_id.." for me. Broadcasting ACK"); _GEM_CMD_AckCommand(ev_id,cmd_id); GEM_COM_SendAckCommand(ev_id,cmd_id); -- Broadcast the ACK must_process = _GEM_CMD_CheckCommandForward(channel,cmd,from,stamp,ev_id,params); end end return must_process; end --[[ function GEM_CMD_CheckExpiredCommands Checks all commands, for expired ones ]] function GEM_CMD_CheckExpiredCommands() for ev_id,cmdtab in GEM_Events.realms[GEM_Realm].commands do _GEM_CMD_CheckExpiredCommand(ev_id,cmdtab.ev_date); end end