vanilla-wow-addons – Rev 1
?pathlinks?
GUILDADSCOMM_DEBUG = false; -- Is debug printf enabled?
GUILDADS_MSG_TYPE_ANNONCE = 0;
GUILDADS_MSG_TYPE_REQUEST = 1;
GUILDADS_MSG_TYPE_AVAILABLE = 2;
GUILDADS_MSG_TYPE_SKILL = 3;
GUILDADS_MSG_TYPE_EVENT = 4;
GUILDADS_MSG_TYPE_INVENTORY = 5;
GUILDADS_MSG_TYPE_NOTE = 6;
GUILDADS_MSG_TYPE_EVENT_SUBSCRIPTION = 7;
GUILDADS_MSG_TYPE_IGNORE = "i";
GUILDADS_VERSION_PROTOCOL = "26";
GUILDADS_MSG_PREFIX = "<GA"..GUILDADS_VERSION_PROTOCOL..">";
GUILDADS_MSG_PREFIX_NOVERSION = "<GA";
GUILDADS_MSG_PREFIX_TOKEN = '\29';
GUILDADS_MSG_PREFIX_CHATCOMM = '\29'.."AD"..'\29'..GUILDADS_VERSION_PROTOCOL..'>';
GUILDADS_MSG_ADD = "a";
GUILDADS_MSG_REMOVE = "r";
GUILDADS_MSG_REMOVE_ALL = "R";
GUILDADS_MSG_REQUEST_ADS = "?";
GUILDADS_MSG_REQUEST_INSPECT = "?i";
GUILDADS_MSG_REQUEST_OFFLINES = "?o";
GUILDADS_MSG_SENDING_UPDATE = "U";
GUILDADS_MSG_SENDING_ALL = "S";
GUILDADS_MSG_SENDING_ALL_END = "E";
GUILDADS_MSG_LASTSEEN = "l";
GUILDADS_MSG_LASTSEEN_END = "le";
GUILDADS_MSG_META = "m";
GUILDADS_MSG_CHATFLAG = "chatFlag";
GUILDADS_STATE_UNKNOW = "unknow";
GUILDADS_STATE_SYNC_ONLINE = "s_online";
GUILDADS_STATE_SYNC_OFFLINE = "s_offline";
GUILDADS_STATE_OK = "ok";
local playerName = "";
local MonitorAds = {}; -- record updated ads (GUILDADS_MSG_SENDING_ALL)
local MetaPlayers = {}; -- state, onlineSince, version
local MyState = GUILDADS_STATE_UNKNOW;
local LastSeens = {}; -- Players we are listen to give theirs offline players.
local WaitingOfflinesAds = { }; -- Players are we waiting for offlines ads to be GUILDADS_STATE_OK
local StartTime;
local OnMessageCommand = { };
local OnMessageAd = {};
local WatingForUpdate = { };
local function DEBUG_MSG(msg)
if (GUILDADSCOMM_DEBUG)
then
ChatFrame1:AddMessage("GAC: "..msg, 1.0, 1.0, 0.5);
end
end
local function GAC_GetGuildChatFrame()
for i=1,NUM_CHAT_WINDOWS,1 do
local DefaultMessages = { GetChatWindowMessages(i) };
for k, channel in DefaultMessages do
if channel == "GUILD" then
return getglobal("ChatFrame"..i);
end
end
end
return DEFAULT_CHAT_FRAME;
end
function GAC_GetMeta(player)
return MetaPlayers[player];
end
function GAC_GetMetas()
return MetaPlayers;
end
GAC_GetFlag = SimpleComm_GetFlag;
function GAC_AddChatMessage(msg)
local info = ChatTypeInfo["CHANNEL"..GetChannelName( SimpleComm_Channel )];
SimpleComm_ChatFrame:AddMessage(msg, info.r, info.g, info.b);
end
function GAC_InitVariablesLoaded()
SimpleComm_PreInit(GuildAds_FilterText);
end
function GAC_Init(playername, channel, password)
DEBUG_MSG("GAC_Init("..playername..","..channel..")");
playerName = playername;
if (not StartTime) then
StartTime = GAS_currentTime();
end
SimpleComm_Init(
channel,
password,
GAC_GetGuildChatFrame(),
GAC_Synchronize,
GAC_OnChannelLeave,
GAC_OnMessage,
GuildAds_Serialize,
GuildAds_Unserialize,
GuildAds_FilterText
);
local command, alias = GuildAdsConfig_GetChannelAlias()
SimpleComm_InitAlias(command, alias);
SimpleComm_SetFlagListener(GAC_OnChatFlagChange);
-- Init after the channel is joined (GAC_Synchronize called by SimpleComm)
end
function GAC_Reinit(channel, password)
-- Reset internal variables
MonitorAds = {};
LastSeens = {};
WaitingOfflinesAds = { };
WatingForUpdate = { };
MyState = GUILDADS_STATE_UNKNOW;
GuildAdsSystem.SynchronizeOfflinesTimer = nil;
GuildAdsSystem.SynchronizeOfflinesTimerEnd = nil;
-- Reinit GuildAdsComm
SimpleComm_SetChannel(channel, password);
-- Init after the channel is joined (GAC_Synchronize called by SimpleComm)
end
function GAC_OnChannelLeave()
GuildAdsPlugin_OnChannelLeave();
end
function GAC_Synchronize()
DEBUG_MSG("GAC_Synchronize");
-- call plugin init
GuildAdsPlugin_OnChannelJoin();
-- reset local variables
MonitorAds = {};
MetaPlayers = {};
LastSeens = {};
WaitingOfflinesAds = {};
WatingForUpdate = { };
-- Send status
MyState = GUILDADS_STATE_SYNC_ONLINE;
GAC_SendMeta(nil);
-- Send chat status : detected by SimpleComm
GAC_SendChatFlag(playerName);
-- Now, send to all my ads
GAC_SendAllAdsType(nil, nil, nil);
-- Ask everyone to send me their ads
GAC_SendRequestAds(nil);
-- Wait 30 seconds and synchronize offlines
GuildAdsSystem.SynchronizeOfflinesCount = 0;
GuildAdsSystem.SynchronizeOfflinesTimer = 30;
GuildAdsSystem.SynchronizeOfflinesTimerEnd = false;
end
function GAC_SynchronizeOfflines(numberOfTries)
DEBUG_MSG("GAC_SynchronizeOfflines("..numberOfTries..")");
--[[
moi à player> envois de GUILDADS_MSG_REQUEST_OFFLINES
player à moi> envois de GUILDADS_MSG_LASTSEEN pour chacun de ses offlines
moi> pour chaque GUILDADS_MSG_LASTSEEN reçu :
si plus ancien -> envois de mes annonces
si plus récent -> demande les annonces à player
player à moi> envois de GUILDADS_MSG_LASTSEEN_END
envois de ses offlines non mis à jour
]]
-- Ask offlines to someone who is online
local oneOnlinePlayer, canTryLater = GAC_GetRandomOnline();
if (oneOnlinePlayer) then
-- Il y au moins un autre joueur
if (canTryLater) and (numberOfTries<=20) then
--[[ aucun joueur connecté n'est synchronisé
attends à nouveau 30 secondes
sauf s'il y a plus de 20 essais (donc 10 minutes)
nombre d'essais limité pour éviter le deadlock si
deux joueurs se connectent au même moment
onelinePlayer = true
]]
GuildAdsSystem.SynchronizeOfflinesTimerEnd = false;
GuildAdsSystem.SynchronizeOfflinesCount = numberOfTries+1;
GuildAdsSystem.SynchronizeOfflinesTimer = 30;
else
-- Changement d'état
MyState = GUILDADS_STATE_SYNC_OFFLINE;
GAC_SendMeta(nil);
-- Il y a au moins un autre joueur connecté
GAC_SendRequestOfflines(oneOnlinePlayer);
-- 10 minutes avant d'être déclaré synchronisé
GuildAdsSystem.SynchronizeOfflinesTimer = 60*10;
GuildAdsSystem.SynchronizeOfflinesCount = 0;
GuildAdsSystem.SynchronizeOfflinesTimerEnd = true;
end
else
-- Aucun online
-- Synchronisation terminée
MyState = GUILDADS_STATE_OK;
GAC_SendMeta(nil);
end
end
function GAC_SynchronizeOfflinesEnd()
MyState = GUILDADS_STATE_OK;
GAC_SendMeta(nil);
end
function GAC_OnChatFlagChange(flag, message)
SimpleComm_SendMessage(
nil,
{
command = GUILDADS_MSG_CHATFLAG;
flag = flag;
text = message;
}
);
end
--[[
Retourne le nom d'un joueur connecté et synchronisé.
Si aucun joueur connecté n'est synchronisé, retourne true
Si aucun joueur n'est connecté, retourne nil
]]
function GAC_GetRandomOnline()
local canTryLater = false;
local ready = {};
for name, metainfo in MetaPlayers do
if (name ~= playerName) then
if (metainfo.state == GUILDADS_STATE_OK) then
tinsert(ready, name);
elseif (metainfo.state == GUILDADS_STATE_SYNC_OFFLINE) or (metainfo.state == GUILDADS_STATE_SYNC_ONLINE) then
canTryLater = true;
end
end
end
local s = table.getn(ready);
if (s > 0) then
return ready[math.random(s)], false;
else
if (canTryLater) then
return nil, true;
else
return nil, false;
end
end
end
function GAC_SendAd(who, ad_type ,ad, delay)
if (ad.m_Enabled == false) then
return;
end
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_ADD;
adtype = ad_type;
id = ad.id;
text = ad.text;
texture = ad.texture;
count = ad.count;
itemRef = ad.itemRef;
itemName = ad.itemName;
itemColor = ad.itemColor;
skillRank = ad.skillRank;
skillMaxRank = ad.skillMaxRank;
creationtime = ad.creationtime;
owner = ad.owner
},
delay
);
end
function GAC_SendSkill(who, id, skillRank, skillMaxRank, delay)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_ADD;
adtype = GUILDADS_MSG_TYPE_SKILL;
id = id;
skillRank = skillRank;
skillMaxRank = skillMaxRank;
creationtime = GAS_currentTime()
},
delay
);
end
function GAC_SendSkills(who, delay)
local grp = "";
for i = 1, GetNumSkillLines(), 1 do
local skillName, header, isExpanded, skillRank, numTempPoints, skillModifier, skillMaxRank, isAbandonable, stepCost, rankCost, minLevel, skillCostType = GetSkillLineInfo(i);
if (header == 1) then
grp = skillName;
else
local id = GAS_GetSkillId(skillName);
if (id > 0) then
GAC_SendSkill(who, id, skillRank, skillMaxRank, delay)
end
end
end
end
function GAC_SendInventory(who, slot, texture, color, ref, name, count)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_ADD;
adtype = GUILDADS_MSG_TYPE_INVENTORY;
id = slot;
itemRef = ref;
itemName = name;
itemColor = color;
count = count;
texture = texture;
creationtime = GAS_currentTime()
}
);
end
function GAC_SendInspect(who)
local buffer = {};
for slot=1, 19, 1 do
local link = GetInventoryItemLink("player", slot);
if (link) then
-- local title = TEXT(getglobal(strupper(SlotIdText[slot])));
local texture = GetInventoryItemTexture("player", slot);
local count = GetInventoryItemCount("player", slot);
local color, ref, name = GAS_UnpackLink(link);
tinsert(buffer, {
slot = slot,
texture = texture,
color = color,
ref = ref,
name = name,
count = count
}
);
end
end
GAC_SendingUpdate(who, table.getn(buffer));
local index = 1;
while buffer[index] do
GAC_SendInventory(who, buffer[index].slot, buffer[index].texture, buffer[index].color, buffer[index].ref, buffer[index].name, buffer[index].count);
index = index + 1;
end
end
function GAC_SendRequestInspect(who)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_REQUEST_INSPECT
}
);
end
function GAC_SendRequestOfflines(who)
DEBUG_MSG("GAC_SendRequestOfflines("..NoNil(who)..")");
LastSeens[who] = {};
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_REQUEST_OFFLINES
}
);
end
function GAC_SendRequestAds(who, owner)
DEBUG_MSG("GAC_SendRequestAds("..NoNil(who)..")");
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_REQUEST_ADS;
owner = owner
}
);
end
function GAC_SendAnnonce(who, owner)
local powner, level, race, class, name, guildName, guildRankName, guildRankIndex, creationtime;
if (owner) then
powner = GAS_ProfileGet(owner);
level = powner.level;
race = powner.race;
class = powner.class;
name = owner;
guildName = powner.guild;
creationtime = powner.creationtime;
accountid = powner.accountid;
else
level = UnitLevel("player");
race = GAS_GetRaceId(UnitRace("player"));
class = GAS_GetClassId(UnitClass("player"));
name = playerName;
guildName, guildRankName, guildRankIndex = GetGuildInfo("player");
creationtime = GAS_currentTime();
accountid = GAS_GetAccountId();
end
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_ADD;
adtype = GUILDADS_MSG_TYPE_ANNONCE;
accountId = accountid;
class = class;
race = race;
level = level;
guild = guildName;
creationtime = creationtime;
owner = owner
}
);
end
function GAC_SendRemove(who, adtype, id)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_REMOVE;
adtype = adtype;
id = id
}
);
end
function GAC_SendRemoveAll(who)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_REMOVE_ALL;
}
);
end
function GAC_SendingUpdate(who, count, owner, delay)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_SENDING_UPDATE,
owner = owner,
count = count
},
delay
);
end
function GAC_SendingAll(who, owner)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_SENDING_ALL;
owner = owner
}
);
end
function GAC_SendingAllEnd(who, owner, delay)
local creationtime = 0;
if (owner) then
creationtime = GAS_ProfileGetUpdatedDate(owner);
else
creationtime = GAS_ProfileGetUpdatedDate(playerName);
end
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_SENDING_ALL_END;
creationtime = creationtime;
owner = owner;
},
delay
);
end
function GAC_SendLastSeen(who, owner, time)
DEBUG_MSG("GAC_SendLastSeen("..NoNil(who)..")");
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_LASTSEEN;
creationtime = time;
owner = owner
}
);
end
function GAC_SendLastSeenEnd(who)
DEBUG_MSG("GAC_SendLastSeenEnd("..NoNil(who)..")");
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_LASTSEEN_END;
}
);
end
function GAC_SendAllAds(who, owner, adTable, ad_type, delay)
local size = table.getn(adTable);
if owner then
for i = 1, size, 1 do
if adTable[i].owner == owner then
GAC_SendAd(who, ad_type, adTable[i], delay);
end
end
else
for i = 1, size, 1 do
GAC_SendAd(who, ad_type, adTable[i], delay);
end
end
end
function GAC_SendAllAdsType(who, owner, delay)
DEBUG_MSG("GAC_SendAllAdsType("..NoNil(who)..","..NoNil(owner)..")");
-- On n'envois pas à who ses annonces
-- sauf si c'est nous même, ou si c'est à tout le monde
if (who == owner) and (who ~= playerName) and (who ~= nil) then
return;
end
-- Ads->Start
GAC_SendingAll(who, owner);
-- Ads : Guild
GAC_SendAnnonce(who, owner);
-- Ads : Ask/Have/Event
local adTables = {};
if (owner) then
adTables = GAS_GetAds();
else
adTables = GAS_GetMyAds();
end
GAC_SendAllAds(who, owner, adTables[GUILDADS_MSG_TYPE_REQUEST], GUILDADS_MSG_TYPE_REQUEST, delay);
GAC_SendAllAds(who, owner, adTables[GUILDADS_MSG_TYPE_AVAILABLE], GUILDADS_MSG_TYPE_AVAILABLE, delay);
GAC_SendAllAds(who, owner, adTables[GUILDADS_MSG_TYPE_EVENT], GUILDADS_MSG_TYPE_EVENT, delay);
-- Ads : Skills
if owner then
GAC_SendAllAds(who, owner, adTables[GUILDADS_MSG_TYPE_SKILL], GUILDADS_MSG_TYPE_SKILL, delay);
else
GAC_SendSkills(who, delay);
end
-- Ads->End
GAC_SendingAllEnd(who, owner, delay);
end
function GAC_SendMeta(who)
SimpleComm_SendMessage(
who,
{
command = GUILDADS_MSG_META;
text = GUILDADS_VERSION;
creationtime = StartTime;
id = MyState;
}
);
end
function GAC_SendChatFlag(who)
local flag, message = SimpleComm_GetFlag(playerName);
SimpleComm_SendMessage(
nil,
{
command = GUILDADS_MSG_CHATFLAG;
flag = flag;
text = message;
}
);
end
--------------------------------------------------------------------------------
--
-- OnMessage
--
---------------------------------------------------------------------------------
function GAC_OnMessage(author, message)
if (GUILDADSCOMM_DEBUG) then
DEBUG_MSG("[OnMessage,"..author.."]: "..GuildAds_Serialize(message));
end
-- Ignore this author ?
if GAS_ProfileIsIgnored(author) then
return;
end
-- Set online
GAS_SetOnlineStatus(author, true);
-- A propos de quelle personne : l'auteur du message (author) ou une autre (message.owner)
local owner = author;
if (message.owner) then
owner = message.owner;
end
-- Mise à jour du dernier message de author
if (owner==author) and ((message.command == GUILDADS_MSG_ADD) or (message.command == GUILDADS_MSG_REMOVE)) then
GAS_ProfileSetUpdatedDate(author, message.creationtime);
end
--
-- Process all the messages we know about
--
if (message.command == GUILDADS_MSG_ADD) then
-- Accept only if :
-- this owner isn't ignored
-- AND ( this owner has sent GUILDADS_MSG_SENDING_ALL which was accepted.
-- OR this owner has sent a GUILDADS_MSG_SENDING_UPDATE )
if not GAS_ProfileIsIgnored(owner) and (MonitorAds[owner] or WatingForUpdate[owner]) then
--
local adtype = message.adtype;
-- Use this update
if WatingForUpdate[owner] then
WatingForUpdate[owner] = WatingForUpdate[owner] - 1;
if WatingForUpdate[owner]==0 then
WatingForUpdate[owner] = nil;
end
DEBUG_MSG("Count"..NoNil(WatingForUpdate[owner]));
end
-- Call onMessageAd
if OnMessageAd[adtype] then
if not OnMessageAd[adtype](author, message) then
return;
end
end
-- Inventory
if (adtype == GUILDADS_MSG_TYPE_INVENTORY) then
GAS_ProfileSetInventorySlot(message.creationtime, owner, message.id, message.itemColor, message.itemRef, message.itemName, message.texture, message.count);
return false;
end
-- Mise à jour du profile
if (adtype == GUILDADS_MSG_TYPE_ANNONCE) then
GAS_ProfileSetGeneral(message.creationtime, owner, message.race, message.class, message.level, message.guild);
GAS_ProfileSetAccountId(owner, message.accountId);
message.guild = nil;
message.level = nil;
message.class = nil;
message.race = nil;
message.accountId = nil;
message.id = owner;
end
-- Monitor : l'annonce a été mise à jour
-- cf GUILDADS_MSG_SENDING_ALL et GUILDADS_MSG_SENDING_ALL_END
if adtype and owner and MonitorAds[owner] then
if (MonitorAds[owner][adtype] == nil) then
MonitorAds[owner][adtype] = {};
end
MonitorAds[owner][adtype][message.id] = true;
end
-- Scan for dupes
if ((adtype == GUILDADS_MSG_TYPE_REQUEST) or (adtype == GUILDADS_MSG_TYPE_AVAILABLE) or (adtype == GUILDADS_MSG_TYPE_EVENT)) then
local ads = GAS_GetAds();
for k,v in ads[adtype] do
if ( v.owner == owner and v.id == message.id and v.text == message.text and v.itemName == message.itemName and v.count == message.count ) then
-- DONT ADD IT AGAIN
DEBUG_MSG("GuildAds_OnMessage: Already in DB");
return false;
end
end
end
-- Effacer le précédent Id
GAS_RemoveByOwnerAndId(owner, adtype, message.id);
-- Efface les donnees inutiles
message.adtype = nil;
message.command = nil;
message.owner = owner;
message.currenttime = nil;
-- Traduction du nom si necessaire
if message.itemName and message.itemRef then
local info = GAS_GetItemInfo(message.itemRef);
if (info.name) then
message.itemName = info.name;
end
end
-- Ajout de l'annonce
GAS_AddAd(owner, adtype, message);
end
elseif (message.command == GUILDADS_MSG_REMOVE) then
-- Ignore this owner ?
if not GAS_ProfileIsIgnored(owner) then
-- A previously placed add is being removed
GAS_RemoveByOwnerAndId(owner, message.adtype, message.id);
end
elseif (message.command == GUILDADS_MSG_REQUEST_INSPECT) then
if not GAS_ProfileIsIgnored(owner) then
-- Send inspect to the author
-- Always my inventory
GAC_SendInspect(author);
end
elseif (message.command == GUILDADS_MSG_REQUEST_OFFLINES) then
if not GAS_ProfileIsIgnored(owner) then
-- Pour chaque personne offline
-- -> envois la date du dernier message
local ads = GAS_GetAds();
for i, ad in ads[GUILDADS_MSG_TYPE_ANNONCE] do
if (not GAS_IsOnline(ad.owner)) and (not GAS_ProfileIsIgnored(ad.owner)) then
GAC_SendLastSeen(author, ad.owner, GAS_ProfileGetUpdatedDate(ad.owner));
end
end
GAC_SendLastSeenEnd(author);
end
elseif (message.command == GUILDADS_MSG_LASTSEEN) then
if (owner ~= playerName) and (LastSeens[author]) and (not GAS_ProfileIsIgnored(owner)) then
LastSeens[author][owner] = true;
local myUpdate = GAS_ProfileGetUpdatedDate(owner);
if (message.creationtime ~= myUpdate) then
if (myUpdate) then
if (message.creationtime==nil or message.creationtime < myUpdate) then
DEBUG_MSG("LastSeen("..owner..")="..NoNil(message.creationtime).."<"..NoNil(myUpdate));
-- on doit faire la mise à jour pour tout le monde
GAC_SendAllAdsType(nil, owner);
elseif (message.creationtime > myUpdate) then
DEBUG_MSG("LastSeen("..owner..")="..NoNil(message.creationtime)..">"..NoNil(myUpdate));
-- on doit récupérer la mise à jour
tinsert(WaitingOfflinesAds, owner);
end
else
DEBUG_MSG("LastSeen("..owner..")="..NoNil(message.creationtime).."/"..NoNil(myUpdate));
-- on doit récupérer la mise à jour
tinsert(WaitingOfflinesAds, owner);
end
end
end
elseif (message.command == GUILDADS_MSG_LASTSEEN_END) then
if LastSeens[author] and not GAS_ProfileIsIgnored(author) then
-- envois les annonces des joueurs non connus.
local ads = GAS_GetAds();
for i, ad in ads[GUILDADS_MSG_TYPE_ANNONCE] do
-- si ad.owner est offline et non connu par author
-- alors on envois ses informations à propos de ad.owner
if (not GAS_IsOnline(ad.owner) and LastSeens[author][ad.owner]==nil) then
GAC_SendAllAdsType(nil, ad.owner);
end
end
-- Dernier message de author à propos des offlines
-- Donc on n'écoute plus les message de author
LastSeens[author] = nil;
--
if (table.getn(WaitingOfflinesAds) > 0) then
-- demande de mise à jour pour soi.
for _, owner in WaitingOfflinesAds do
GAC_SendRequestAds(author, owner);
end
else
-- aucune demande de offlines
-- on est donc synchro : passage a l'etat OK
GuildAdsSystem.SynchronizeOfflinesTimer = nil;
MyState = GUILDADS_STATE_OK;
GAC_SendMeta(nil);
end
end
elseif (message.command == GUILDADS_MSG_REQUEST_ADS) then
-- Someone is requesting ads, probably just arrived in the channel
-- if message.owner is set : owner's ads
-- if message.owner is nil : my ads (send my ads in few seconds)
-- owner is meaningless
if GuildAds.Config.PublishMyAds and not GAS_ProfileIsIgnored(owner) then
if (author ~= playerName) then
if message.owner then
GAC_SendAllAdsType(author, message.owner);
else
GAC_SendMeta(author);
GAC_SendChatFlag(author);
GAC_SendAllAdsType(author, nil, math.random(20));
end
end
end
elseif (message.command == GUILDADS_MSG_SENDING_UPDATE) then
WatingForUpdate[owner] = (WatingForUpdate[owner] or 0) + message.count;
elseif (message.command == GUILDADS_MSG_SENDING_ALL) then
if not GAS_ProfileIsIgnored(owner) then
-- Start recording each update ads
if message.owner then
-- Accept offline ads from owner we need. (see GUILDADS_MSG_LASTSEEN)
i = 1;
while WaitingOfflinesAds[i] and WaitingOfflinesAds[i]~=owner do
i = i+1;
end
if WaitingOfflinesAds[i] and WaitingOfflinesAds[i]==owner then
MonitorAds[owner] = {};
end
-- accept new ads from author who are in GUILDADS_STATE_SYNC_OFFLINE state.
if MetaPlayers[author] and MetaPlayers[author].state==GUILDADS_STATE_SYNC_OFFLINE then
MonitorAds[owner] = {};
end
else
-- online synchronization : ok
MonitorAds[owner] = {};
end
end
elseif (message.command == GUILDADS_MSG_SENDING_ALL_END) then
if MonitorAds[owner] and not GAS_ProfileIsIgnored(owner) then
-- Update profile date
if owner then
GAS_ProfileSetUpdatedDate(owner, message.creationtime);
end
-- for each owner's ads
-- if not updated (ie in MonitorAds), we delete it
local ads = GAS_GetAds();
for adtype, tads in ads do
if (MonitorAds[owner][adtype] == nil) then
GAS_RemoveByOwner(owner, adtype);
else
for i, ad in tads do
if (owner==ad.owner and MonitorAds[owner][adtype][ad.id] == nil) then
GAS_RemoveByOwnerAndId(owner, adtype, ad.id);
end
end
end
end
-- stop monitoring
MonitorAds[owner] = nil;
-- Unstack owner in WatingOfflineAds
-- if this is the last, we are sync
-- so set state to GUILDADS_STATE_OK
i = 1;
while WaitingOfflinesAds[i] and WaitingOfflinesAds[i]~=owner do
i = i+1;
end
if WaitingOfflinesAds[i] and WaitingOfflinesAds[i]==owner then
table.remove(WaitingOfflinesAds, i);
if (table.getn(WaitingOfflinesAds)==0) then
GuildAdsSystem.SynchronizeOfflinesTimer = nil;
MyState = GUILDADS_STATE_OK;
GAC_SendMeta(nil);
end
end
end
elseif (message.command == GUILDADS_MSG_REMOVE_ALL) then
if not GAS_ProfileIsIgnored(owner) then
-- Remove all the ads from the owner
GAS_RemoveByOwner(owner, GUILDADS_MSG_TYPE_ANNONCE);
GAS_RemoveByOwner(owner, GUILDADS_MSG_TYPE_REQUEST);
GAS_RemoveByOwner(owner, GUILDADS_MSG_TYPE_AVAILABLE);
GAS_RemoveByOwner(owner, GUILDADS_MSG_TYPE_SKILL);
GAS_RemoveByOwner(owner, GUILDADS_MSG_TYPE_EVENT);
end
elseif (message.command == GUILDADS_MSG_META) then
if not GAS_ProfileIsIgnored(author) then
MetaPlayers[author] = {
state = message.id;
onlineSince = message.creationtime;
version = message.text;
};
end
elseif (message.command == GUILDADS_MSG_CHATFLAG) then
if author~=playerName then
SimpleComm_SetFlag(author, message.flag, message.text);
end
elseif OnMessageCommand[message.command] then
OnMessageCommand[message.command](author, message);
else
-- This message was unknown
end
end
--------------------------------------------------------------------------------
--
-- Serialize/Unserialize
--
---------------------------------------------------------------------------------
function SerializeId(obj)
if (type(obj) == "nil" ) then
return "";
else
return obj
end
end
function UnserializeId(str)
return str;
end
function SerializeString(obj)
if (type(obj) == "nil" ) then
return "";
else
return obj
end
end
function UnserializeString(str)
if (str == "") then
return nil;
else
return str
end
end
function SerializeTexture(obj)
if (type(obj) == "nil" ) then
return "";
else
return string.gsub(obj, "Interface\\Icons\\", "\@");
end
end
function UnserializeTexture(str)
if (str == "") then
return nil;
else
return string.gsub(str, "\@", "Interface\\Icons\\");
end
end
function SerializeItemRef(obj)
if (type(obj) == "nil" ) then
return "";
else
return string.gsub(string.gsub(obj, "item\:", "\@"), ":0:0:0", "\*");
end
end
function UnserializeItemRef(str)
if (str == "") then
return nil;
else
return string.gsub(string.gsub(str, "\@", "item\:"), "\*", ":0:0:0");
end
end
function SerializeColor(obj)
if obj==nil then
return "";
elseif obj=="ffa335ee" then
return "E"; -- epic
elseif obj=="ff0070dd" then
return "R"; -- rare
elseif obj=="ff1eff00" then
return "U" -- uncommun
elseif obj=="ffffffff" then
return "C" -- common
elseif obj=="ff9d9d9d" then
return "P" -- poor
else
return obj;
end
end
function UnserializeColor(str)
if str==nil then
return nil
elseif str=="E" then
return "ffa335ee";
elseif str=="R" then
return "ff0070dd";
elseif str=="U" then
return "ff1eff00";
elseif str=="C" then
return "ffffffff";
elseif str=="P" then
return "ff9d9d9d";
else
return str;
end
end
function SerializeInteger(obj)
if (type(obj) == "nil" ) then
return "";
else
return obj;
end
end
function UnserializeInteger(str)
return tonumber(str);
end
function SerializeTime(obj)
if (type(obj) == "nil" ) then
return "";
else
-- convertion en base 52
value = "";
while (obj ~= 0) do
i = floor(obj / 52);
j = obj - i*52;
if (j>=26) then
value = string.char(65+j-26)..value;
else
value = string.char(96+j)..value;
end
obj = i;
end
return value;
end
end
function UnserializeTime(str)
if (str == "") then
return nil;
else
number = 0;
for i=1, string.len(str),1 do
o = string.byte(str, i);
if (o> 95) then
j = o-96;
else
j = o-65+26;
end
number = number*52 + j;
end
return number;
end
end
function SerializeObj(obj)
if (type(obj) == "nil" ) then
return "";
elseif ( type(obj) == "string" ) then
return "s"..string.gsub(string.gsub(string.gsub(obj, ">", ">"), "|([cHhr])", "&%1;"), "|", "&p;");
elseif ( type(obj) == "number" ) then
return "n"..obj;
elseif ( type(obj) == "boolean" ) then
if (value) then
return "1";
else
return "0";
end
elseif ( type(obj) == "function" ) then
return ""; -- nil
elseif ( type(obj) == "table" ) then
return ""; -- nil
end
return "";
end
function UnserializeObj(str)
if (str == "") then
return nil;
else
typeString = string.sub(str, 0, 1);
valueString = string.sub(str, 2);
if (typeString == "s") then
return string.gsub(string.gsub(string.gsub(valueString, ">", ">"), "&(%w);", "|%1"), "&p;", "|");
elseif (typeString == "n") then
return tonumber(valueString);
elseif (typeString == "1") then
return true;
elseif (typeString == "0") then
return false;
else
DEBUG_MSG("GuildAds_Unserialize: Type non reconnu:"..str);
return nil;
end
end
end
local SerializeMeta = {
[1] = { ["key"] ="command", ["fout"]=SerializeId, ["fin"]=UnserializeId }
};
local SerializeCommand = {
[GUILDADS_MSG_ADD] = {
[1] = { ["key"]="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[2] = { ["key"]="adtype", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[3] = { ["key"]="id", ["fout"]=SerializeObj, ["fin"]=UnserializeObj },
[4] = { ["key"]="currenttime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime},
[5] = { ["key"]="creationtime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime},
},
[GUILDADS_MSG_REMOVE] = {
[1] = { ["key"] ="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[2] = { ["key"] ="adtype", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[3] = { ["key"] ="id", ["fout"]=SerializeObj, ["fin"]=UnserializeObj },
},
[GUILDADS_MSG_REMOVE_ALL] = {
[1] = { ["key"] ="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
},
[GUILDADS_MSG_REQUEST_ADS] = {
[1] = { ["key"] ="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
},
[GUILDADS_MSG_REQUEST_OFFLINES] = {},
[GUILDADS_MSG_REQUEST_INSPECT] = {},
[GUILDADS_MSG_SENDING_UPDATE] = {
[1] = { ["key"] ="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[2] = { ["key"] ="count", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
},
[GUILDADS_MSG_SENDING_ALL] = {
[1] = { ["key"] ="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
},
[GUILDADS_MSG_SENDING_ALL_END] = { -- currenttime, profiletime
[1] = { ["key"] ="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[2] = { ["key"] ="currenttime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime},
[3] = { ["key"] ="creationtime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime },
},
[GUILDADS_MSG_LASTSEEN] = { -- currenttime, profiletime
[1] = { ["key"] ="owner", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[2] = { ["key"] ="currenttime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime},
[3] = { ["key"] ="creationtime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime },
},
[GUILDADS_MSG_LASTSEEN_END] = {},
[GUILDADS_MSG_META] = { -- currenttime, version, starttime, id
[1] = { ["key"] ="currenttime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime},
[2] = { ["key"] ="text", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[3] = { ["key"] ="creationtime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime },
[4] = { ["key"] ="id", ["fout"]=SerializeId, ["fin"]=UnserializeId },
},
[GUILDADS_MSG_CHATFLAG] = { -- flag, text
[1] = { ["key"] ="flag", ["fout"]=SerializeString, ["fin"]=UnserializeString},
[2] = { ["key"] ="text", ["fout"]=SerializeString, ["fin"]=UnserializeString },
},
};
local SerializeAd = {
[GUILDADS_MSG_TYPE_ANNONCE] = { -- accountId, class, race, level, guild
[1] = { ["key"] ="accountId", ["fout"]=SerializeObj, ["fin"]=UnserializeObj },
[2] = { ["key"] ="class", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[3] = { ["key"] ="race", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[4] = { ["key"] ="level", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[5] = { ["key"] ="guild", ["fout"]=SerializeString, ["fin"]=UnserializeString },
},
[GUILDADS_MSG_TYPE_INVENTORY] = { -- itemRef, itemName, itemColor, count, texture
[1] = { ["key"] ="itemColor", ["fout"]=SerializeColor, ["fin"]=UnserializeColor },
[2] = { ["key"] ="itemRef", ["fout"]=SerializeItemRef, ["fin"]=UnserializeItemRef },
[3] = { ["key"] ="itemName", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[4] = { ["key"] ="count", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[5] = { ["key"] ="texture", ["fout"]=SerializeTexture, ["fin"]=UnserializeTexture },
},
[GUILDADS_MSG_TYPE_SKILL] = { -- skillRank , skillMaxRank
[1] = { ["key"] ="skillRank", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[2] = { ["key"] ="skillMaxRank", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
},
[GUILDADS_MSG_TYPE_REQUEST] = { -- text, itemRef, itemName, itemColor, count, texture
[1] = { ["key"] ="text", ["fout"]=SerializeObj, ["fin"]=UnserializeObj },
[2] = { ["key"] ="itemColor", ["fout"]=SerializeColor, ["fin"]=UnserializeColor },
[3] = { ["key"] ="itemRef", ["fout"]=SerializeItemRef, ["fin"]=UnserializeItemRef },
[4] = { ["key"] ="itemName", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[5] = { ["key"] ="count", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[6] = { ["key"] ="texture", ["fout"]=SerializeTexture, ["fin"]=UnserializeTexture },
},
[GUILDADS_MSG_TYPE_AVAILABLE] ={ -- text, itemRef, itemName, itemColor, count, texture
[1] = { ["key"] ="text", ["fout"]=SerializeObj, ["fin"]=UnserializeObj },
[2] = { ["key"] ="itemColor", ["fout"]=SerializeColor, ["fin"]=UnserializeColor },
[3] = { ["key"] ="itemRef", ["fout"]=SerializeItemRef, ["fin"]=UnserializeItemRef },
[4] = { ["key"] ="itemName", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[5] = { ["key"] ="count", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[6] = { ["key"] ="texture", ["fout"]=SerializeTexture, ["fin"]=UnserializeTexture },
},
[GUILDADS_MSG_TYPE_EVENT] = { -- text
[1] = { ["key"] ="text", ["fout"]=SerializeObj, ["fin"]=UnserializeObj },
[2] = { ["key"] ="eventtime", ["fout"]=SerializeTime, ["fin"]=UnserializeTime },
[3] = { ["key"] ="note", ["fout"]=SerializeString, ["fin"]=UnserializeString },
[4] = { ["key"] ="count", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[5] = { ["key"] ="minlevel", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
[6] = { ["key"] ="maxlevel", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
},
[GUILDADS_MSG_TYPE_EVENT_SUBSCRIPTION] = {
[1] = { ["key"] ="eventid", ["fout"]=SerializeInteger, ["fin"]=UnserializeInteger },
}
};
function SerializeTable(spec, obj)
local tmp = "";
local index = table.getn(spec);
while (index > 0) do
local info = spec[index];
local result = info.fout(obj[info.key]);
if (tmp ~= "") or (result ~= "") then
tmp = result..">"..tmp;
end;
index = index -1;
end
return tmp;
end
function GuildAds_SerializeCommand(obj)
local result = SerializeTable(SerializeMeta, obj)
if SerializeCommand[obj.command] then
result = result .. SerializeTable(SerializeCommand[obj.command], obj);
if obj.command == GUILDADS_MSG_ADD then
result = result .. SerializeTable(SerializeAd[obj.adtype], obj);
end
end
return result;
end
function GuildAds_UnserializeCommand(text)
local obj= { };
local spec=SerializeMeta;
local index=1;
local size= table.getn(spec);
local step=1;
for str in string.gfind(text, "([^\>]*)>") do
info = spec[index];
obj[info.key] = info.fin(str);
index = index + 1;
if index>size then
step=step+1;
if step==2 then
if obj.command and SerializeCommand[obj.command] then
spec=SerializeCommand[obj.command];
else
spec=nil;
end
elseif step==3 then
if obj.adtype and SerializeAd[obj.adtype] then
spec=SerializeAd[obj.adtype];
else
spec=nil;
end
else
return obj;
end
if spec then
index=1;
size=table.getn(spec);
else
return obj
end
end
end
return obj;
end
function GuildAds_Serialize(obj)
obj["currenttime"] = GAS_currentTime();
return GUILDADS_MSG_PREFIX..GuildAds_SerializeCommand(obj);
end
function GuildAds_Unserialize(str)
local iStart, iEnd, msg, params;
iStart, iEnd, params = string.find(str, GUILDADS_MSG_PREFIX.."(.*)");
if (iStart) then
return GuildAds_UnserializeCommand(params);
else
iStart, iEnd, params = string.find(str, GUILDADS_MSG_PREFIX_CHATCOMM.."(.*)");
if (iStart) then
return GuildAds_UnserializeCommand(params);
else
return nil
end
end
end
function GuildAds_FilterText(text)
return string.sub(text, 1, string.len(GUILDADS_MSG_PREFIX_NOVERSION)) == GUILDADS_MSG_PREFIX_NOVERSION
or string.sub(text, 1, string.len(GUILDADS_MSG_PREFIX_TOKEN)) == GUILDADS_MSG_PREFIX_TOKEN;
end
--------------------------------------------------------------------------------
--
-- Register/Unregister new command
--
---------------------------------------------------------------------------------
function GAC_RegisterCommand(command, serializeInfo, onMessage)
if SerializeCommand[command] then
return false, "command("..command..") already registered";
else
if type(onMessage) == "function" then
if type(serializeInfo) == "table" then
for _, spec in serializeInfo do
if type(spec.key)~="string" or type(spec.fin)~="function" or type(spec.fout)~="function" then
if type(spec.key)=="string" then
return false, "serializeInfo["..spec.key.."]="..type(spec.fin)..","..type(spec.fout);
else
return false, "serializeInfo[??]="..type(spec.fin)..","..type(spec.fout);
end
end
end
SerializeCommand[command] = serializeInfo;
OnMessageCommand[command] = onMessage;
return true;
else
return false, "type(serializeInfo)="..type(serializeInfo);
end
else
return false, "type(onMessage)="..type(onMessage);
end
end
end
function GAC_UnregisterCommand(command)
SerializeCommand[command] = nil;
OnMessageCommand[command] = nil;
end
function GAC_IsRegisteredCommand(command)
if SerializeCommand[command] then
return true, SerializeCommand[command], OnMessageCommand[command];
else
return false;
end
end
--------------------------------------------------------------------------------
--
-- Register/Unregister new ad type
--
---------------------------------------------------------------------------------
function GAC_RegisterAdtype(adtype, serializeInfo, onMessage)
if SerializeAd[adtype] then
return false, "adtype("..command..") already registered";
else
if type(onMessage) == "function" then
if type(serializeInfo) == "table" then
for _, spec in serializeInfo do
if type(spec.key)~="string" or type(spec.fin)~="function" or type(spec.fout)~="function" then
return false, "serializeInfo["..spec.key.."]="..type(spec.fin)..","..type(spec.fout);
end
end
SerializeAd[adtype] = serializeInfo;
OnMessageAd[adtype] = onMessage;
return true;
else
return false, "type(serializeInfo)="..type(serializeInfo);
end
else
return false, "type(onMessage)="..type(onMessage);
end
end
end
function GAC_UnregisterAdtype(adtype)
SerializeAd[adtype] = nil;
OnMessageAd[adtype] = nil;
end
function GAC_IsRegisteredAdtype(adtype)
if SerializeCommand[adtype] then
return true, SerializeAd[adtype], OnMessageAd[adtype];
else
return false;
end
end
-- export
GAC_SerializeObj = SerializeObj;
GAC_UnserializeObj = UnserializeObj;
GAC_SerializeString = SerializeString;
GAC_UnserializeString = UnserializeString;
GAC_SerializeInteger = SerializeInteger;
GAC_UnserializeInteger = UnserializeInteger;
GAC_SerializeColor = SerializeColor;
GAC_UnserializeColor = UnserializeColor;
Generated by GNU Enscript 1.6.5.90.