vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 GUILDADS_VERSION_STORAGE = "20051017";
2  
3 GuildAdsStorage_DebugTableName = {};
4 GUILDADSSTORAGE_DEBUG = false;
5  
6 local HourMin = 60;
7 local DayMin = HourMin * 24;
8 local MonthMin = DayMin * 30;
9 local TimeRef = 18467940; -- Nombre de minutes entre 1/1/1970 et 11/2/2005
10 local AdsTable = nil; -- GuildAds.Data[realmName].Global[channel]
11 local IgnoreTable = nil; -- GuildAds.Data[realmName].Ignore[channel]
12 local MyAdsTable = nil; -- GuildAds.Data[realmName].Mine[playerName]
13 local playerName = nil;
14 local playersOnlineStatus = { };
15 local playersByAccount = { };
16 local itemInfo = { }; -- cache for GetItemInfo (usefull ?)
17  
18 GuildAdsItems = {};
19  
20 GAS_EVENT_ADDGLOBAL = 1;
21 GAS_EVENT_REMOVEGLOBAL = 2;
22 GAS_EVENT_ADDMY = 3;
23 GAS_EVENT_REMOVEMY = 4;
24 GAS_EVENT_UPDATEINVENTORY = 5;
25 GAS_EVENT_ONLINE = 6;
26  
27 local Listeners = {
28 [GAS_EVENT_ADDGLOBAL] = {};
29 [GAS_EVENT_REMOVEGLOBAL] = {};
30 [GAS_EVENT_ADDMY] = {};
31 [GAS_EVENT_REMOVEMY] = {};
32 [GAS_EVENT_UPDATEINVENTORY] = {};
33 [GAS_EVENT_ONLINE] = {};
34 };
35  
36 local function DEBUG_MSG(msg)
37 if (GUILDADSSTORAGE_DEBUG)
38 then
39 ChatFrame1:AddMessage("GAS: "..msg, 1.0, 1.0, 0.5);
40 end
41 end
42  
43 --[[
44 Provide a common time between different players.
45 Return the number of minutes since 11/2/2005 00h00 (date of the WOW release in Europe)
46 Get UTC time, using server time and PC date.
47 do not use UTC ( !*t ) to avoid to much difference between server and PC time.
48 ]]
49 function GAS_currentTime()
50 local hours,minutes = GetGameTime();
51 local t = date("*t");
52 t.wday = nil;
53 t.yday = nil;
54 t.isdst = nil;
55 t.sec = nil;
56  
57 local local_min = t.hour*60+t.min;
58 local server_min = hours*60+minutes;
59  
60 local TimeShift = server_min-local_min;
61 if math.abs(TimeShift)>=12*60 then
62 if local_min<server_min then
63 TimeShift = TimeShift-DayMin;
64 else
65 TimeShift = TimeShift+DayMin;
66 end
67 end
68  
69 t.hour, t.min = hours, minutes;
70 -- local_min+TimeShift : server time not round between 0 and DayMin
71 return math.floor(time(t) / 60)+math.floor((local_min+TimeShift)/DayMin)*DayMin-TimeRef;
72 end
73  
74 function GAS_timeToString(ref, relative)
75 local delta;
76 local prefix = "";
77 if relative then
78 delta = tonumber(ref);
79 else
80 delta = GAS_currentTime()-tonumber(ref);
81 end
82  
83 if delta<0 then
84 prefix = "-";
85 delta = -delta;
86 end
87  
88 month = math.floor(delta / MonthMin);
89 deltamonth = math.mod(delta, MonthMin);
90  
91 day = math.floor(deltamonth / DayMin);
92 deltaday = math.mod(delta, DayMin);
93  
94 hour = math.floor(deltaday / HourMin);
95 minute = math.mod(delta, HourMin);
96  
97 if (month > 0) then
98 return prefix..string.format(GetText("LASTONLINE_MONTHS", nil, month), month);
99 elseif (day > 0) then
100 return prefix..string.format(GetText("LASTONLINE_DAYS", nil, day), day);
101 elseif (hour > 0) then
102 return prefix..string.format(GetText("LASTONLINE_HOURS", nil, hour), hour);
103 else
104 return prefix..string.format(GetText("GENERIC_MIN", nil, minute), minute);
105 end
106 end
107  
108 --------------------------------------------------------------------------------
109 --
110 -- About listeners
111 --
112 --------------------------------------------------------------------------------
113 function GAS_AddListener(ltype, name, listener)
114 if Listeners[ltype] then
115 Listeners[ltype][name] = listener;
116 return true;
117 else
118 return false;
119 end
120 end
121  
122 function GAS_RemoveListener(ltype, name)
123 if Listeners[ltype] and Listeners[ltype][name] then
124 Listeners[ltype][name] = nil;
125 return true;
126 else
127 return false;
128 end
129 end
130  
131 function GAS_NotifyListeners(ltype, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
132 GuildAdsPlugin_OnEvent(ltype, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
133 for listenerName, listenerFunction in Listeners[ltype] do
134 listenerFunction(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
135 end
136 end
137  
138 --------------------------------------------------------------------------------
139 --
140 -- Set online status of a player
141 --
142 --------------------------------------------------------------------------------
143 function GAS_SetOnlineStatus(playername, status)
144 if status then
145 if (not playersOnlineStatus[playername]) then
146 playersOnlineStatus[playername] = true;
147 GAS_NotifyListeners(GAS_EVENT_ONLINE, playername, true);
148 end
149 else
150 if (playersOnlineStatus[playername]) then
151 playersOnlineStatus[playername] = nil;
152 GAS_NotifyListeners(GAS_EVENT_ONLINE, playername, false);
153 end
154 end
155 end
156  
157 --------------------------------------------------------------------------------
158 --
159 -- Get online status of a player
160 --
161 --------------------------------------------------------------------------------
162 function GAS_IsOnline(playername)
163 if (playersOnlineStatus[playername]) then
164 return true;
165 else
166 return false;
167 end
168 end
169  
170 --------------------------------------------------------------------------------
171 --
172 -- Init
173 --
174 --------------------------------------------------------------------------------
175 function GAS_Init(playername, channel)
176 DEBUG_MSG("[GAS_Init] begin");
177  
178 realmName = GetCVar("realmName");
179 playerName = playername;
180  
181 -- Set account id
182 if (GuildAds.AccountId == nil) then
183 GuildAds.AccountId = GAS_CreateAccountId();
184 end
185  
186 -- If this is the first time for this realm
187 if (GuildAds.Data[realmName] == nil) then
188 GuildAds.Data[realmName] = {};
189 GuildAds.Data[realmName].Mine = {};
190 GuildAds.Data[realmName].Global = {};
191 GuildAds.Data[realmName].Profile = {};
192 end
193  
194 -- If this is the first time that this player uses GuildAds
195 if (GuildAds.Data[realmName].Mine[playername] == nil) then
196 GuildAds.Data[realmName].Mine[playername] = {
197 [GUILDADS_MSG_TYPE_REQUEST] = { NextId = 0 };
198 [GUILDADS_MSG_TYPE_AVAILABLE] = { NextId = 0 };
199 [GUILDADS_MSG_TYPE_EVENT] = { NextId = 0 };
200 [GUILDADS_MSG_TYPE_ANNONCE] = {};
201 [GUILDADS_MSG_TYPE_SKILL] = {};
202 }
203 DEBUG_MSG("First time for this player");
204 end
205  
206 -- Init de GuildAds.Global[realmName][g_ChatChannel]
207 if (GuildAds.Data[realmName].Global[channel] == nil) then
208 GuildAds.Data[realmName].Global[channel] = {
209 [GUILDADS_MSG_TYPE_REQUEST] = {};
210 [GUILDADS_MSG_TYPE_AVAILABLE] = {};
211 [GUILDADS_MSG_TYPE_EVENT] = {};
212 [GUILDADS_MSG_TYPE_ANNONCE] = {};
213 [GUILDADS_MSG_TYPE_SKILL] = {};
214 };
215  
216 DEBUG_MSG("First time for this channel");
217 end
218  
219 -- Init de GuildAds.Data[realmName].Ignore[channel]
220 if GuildAds.Data[realmName].Ignore==nil then
221 GuildAds.Data[realmName].Ignore={};
222 end
223 if GuildAds.Data[realmName].Ignore[channel]==nil then
224 GuildAds.Data[realmName].Ignore[channel]={};
225 end
226  
227 -- Init de GuildAds.Data[realmName].Profile[realmName]
228 if (GuildAds.Data[realmName].Profile == nil) then
229 GuildAds.Data[realmName].Profile = {};
230 end
231  
232 -- Init des tables pour ce personnage
233 IgnoreTable = GuildAds.Data[realmName].Ignore[channel]
234 AdsTable = GuildAds.Data[realmName].Global[channel];
235 MyAdsTable = GuildAds.Data[realmName].Mine[playername];
236 ProfileTable = GuildAds.Data[realmName].Profile;
237  
238 -- Init des demandes par items
239 GAS_ScanItems();
240  
241 -- DEBUG
242 GAS_DebugWatchTables();
243  
244 DEBUG_MSG("[GAS_Init] end");
245 end
246  
247 --------------------------------------------------------------------------------
248 --
249 -- After calling this function, an illegal access to AdsTable or MyAdsTable
250 -- will show an error
251 -- Illegal access = undefined key
252 --
253 --------------------------------------------------------------------------------
254 function GAS_DebugWatchTables()
255 local mt = {
256 __index = function (t, n)
257 local msg = "GuildAds: attempt to read undeclared variable "..n;
258 local name = GuildAdsStorage_DebugTableName[t];
259 if (name) then
260 msg = msg .. " in "..name;
261 end
262 ChatFrame1:AddMessage(msg, 1.0, 0.0, 0.0);
263 error(msg, 2)
264 return nil;
265 end,
266 };
267  
268 setmetatable(GuildAdsStorage_DebugTableName, {__mode = "k"})
269  
270 GuildAdsStorage_DebugTableName[AdsTable] = "AdsTable";
271 setmetatable(AdsTable, mt);
272 for k, t in AdsTable do
273 GuildAdsStorage_DebugTableName[AdsTable[k]] = "AdsTable["..k.."]";
274 setmetatable(AdsTable[k], mt);
275 end
276  
277 GuildAdsStorage_DebugTableName[MyAdsTable] = "MyAdsTable";
278 setmetatable(MyAdsTable, mt);
279 for k, t in MyAdsTable do
280 GuildAdsStorage_DebugTableName[MyAdsTable[k]] = "MyAdsTable["..k.."]";
281 setmetatable(MyAdsTable[k], mt);
282 end
283 end
284  
285 function GAS_GetAccountId()
286 return GuildAds.AccountId;
287 end
288  
289 function GAS_CreateAccountId()
290 local str = "";
291 for i=1,4,1 do
292 str = str .. string.char(math.random(65, 90));
293 end
294 str = str..GAS_currentTime();
295 return str;
296 end
297  
298 --------------------------------------------------------------------------------
299 --
300 -- Profile
301 --
302 --------------------------------------------------------------------------------
303 function GAS_ProfileInit(owner)
304 if (ProfileTable[owner] == nil) then
305 ProfileTable[owner] = {};
306 ProfileTable[owner].Inventory = {};
307 end
308 end
309  
310 function GAS_ProfileSetInventorySlot(time, owner, slot, color, ref, name, texture, count)
311 GAS_ProfileInit(owner);
312 ProfileTable[owner].Inventory.creationtime = time;
313 ProfileTable[owner].Inventory[slot] = {
314 color = color,
315 ref = ref,
316 name = name,
317 texture = texture,
318 count = count
319 }
320 GAS_NotifyListeners(GAS_EVENT_UPDATEINVENTORY, owner, slot);
321 end
322  
323 function GAS_ProfileGetInventory(owner)
324 GAS_ProfileInit(owner);
325 return ProfileTable[owner].Inventory;
326 end
327  
328 function GAS_ProfileGet(owner)
329 GAS_ProfileInit(owner);
330 return ProfileTable[owner];
331 end
332  
333 function GAS_ProfileSetGeneral(time, owner, race, class, level, guild)
334 GAS_ProfileInit(owner);
335 ProfileTable[owner].race = race;
336 ProfileTable[owner].class = class;
337 ProfileTable[owner].level = level;
338 ProfileTable[owner].guild = guild;
339 ProfileTable[owner].creationtime = time;
340 end
341  
342 function GAS_ProfileSetAccountId(owner, accountid)
343 GAS_ProfileInit(owner);
344 ProfileTable[owner].accountid = accountid;
345 if accountid and playersByAccount[accountid] then
346 playersByAccount[accountid] = nil;
347 end
348 end
349  
350 function GAS_ProfileSetUpdatedDate(owner, time)
351 GAS_ProfileInit(owner);
352 ProfileTable[owner].updatedDate = time;
353 end
354  
355 function GAS_ProfileGetUpdatedDate(owner)
356 GAS_ProfileInit(owner);
357 return ProfileTable[owner].updatedDate;
358 end
359  
360 function GAS_PlayersByAccount(accountid)
361 if (not playersByAccount[accountid]) then
362 playersByAccount[accountid] = { };
363 for owner, data in ProfileTable do
364 if (data.accountid == accountid) then
365 tinsert(playersByAccount[accountid], owner);
366 end
367 end
368 end
369 return playersByAccount[accountid];
370 end
371  
372 function GAS_ProfileIgnore(owner, status)
373 if status then
374 IgnoreTable[owner] = GAS_currentTime();
375  
376 local account = ProfileTable[owner].accountid;
377 if account then
378 playersByAccount[account] = nil;
379 end
380  
381 ProfileTable[owner] = nil;
382 for adtype, ads in AdsTable do
383 GAS_RemoveByOwner(owner, adtype);
384 end
385  
386 else
387 IgnoreTable[owner] = nil;
388 end
389 end
390  
391 function GAS_ProfileIsIgnored(owner)
392 return IgnoreTable[owner];
393 end
394  
395 function GAS_ProfileIgnoreList()
396 return IgnoreTable;
397 end
398  
399 --------------------------------------------------------------------------------
400 --
401 -- Get my ads table
402 --
403 --------------------------------------------------------------------------------
404 function GAS_GetMyAds()
405 if (MyAdsTable == nil) then
406 error("GuildAdsStorage : MyAdsTable == nil", 2);
407 else
408 return MyAdsTable;
409 end
410 end
411  
412 --------------------------------------------------------------------------------
413 --
414 -- Get global ads table
415 --
416 --------------------------------------------------------------------------------
417 function GAS_GetAds(adType)
418 if (AdsTable == nil) then
419 error("GuildAdsStorage : AdsTable == nil", 2);
420 else
421 if (adType) then
422 if (not AdsTable[adType]) then
423 AdsTable[adType] = {};
424 end
425 return AdsTable[adType];
426 else
427 return AdsTable;
428 end
429 end
430 end
431  
432 ---------------------------------------------------------------------------------
433 --
434 -- Check validity of an ad
435 --
436 ---------------------------------------------------------------------------------
437 function GAS_IsValidAd(adtype, ad)
438 if (adtype == GUILDADS_MSG_TYPE_EVENT) then
439 for k, oneAd in MyAdsTable[adtype] do
440 if type(oneAd)=="table" and oneAd.text == ad.text then
441 return false;
442 end
443 end
444 return true;
445 else
446 return true;
447 end
448 end
449  
450 ---------------------------------------------------------------------------------
451 --
452 -- Add a my ad
453 --
454 ---------------------------------------------------------------------------------
455 function GAS_AddMyAd(adtype, text, color, ref, name, texture, count)
456 -- Create ad
457 local nextId = MyAdsTable[adtype].NextId;
458 local ad = {
459 id = nextId,
460 text = text,
461 itemColor = color,
462 itemRef = ref,
463 itemName = name,
464 texture = texture,
465 count = count,
466 creationtime = GAS_currentTime(),
467 m_Enabled = true,
468 };
469  
470 -- Check validity
471 if (not GAS_IsValidAd(adtype, ad)) then
472 return false
473 end
474  
475 -- Add to the my ad table
476 table.insert(MyAdsTable[adtype], ad);
477  
478 -- Incrememnt the id and wrap around
479 nextId = nextId + 1;
480 if (nextId >= 65535) then
481 nextId = 0;
482 end;
483 MyAdsTable[adtype].NextId = nextId;
484  
485 -- Notify listeners
486 GAS_NotifyListeners(GAS_EVENT_ADDMY, adtype, ad);
487  
488 -- Notify everyone
489 if (GuildAds.Config.PublishMyAds) then
490 GAC_SendingUpdate(nil, 1);
491 GAC_SendAd(nil, adtype, ad);
492 end
493 return id;
494 end
495  
496 ---------------------------------------------------------------------------------
497 --
498 -- Edit one of my ad
499 --
500 ---------------------------------------------------------------------------------
501 function GAS_EditMyAd(adtype, id, text, color, ref, name, texture, count)
502 -- Ad to edit
503 ad = MyAdsTable[adtype][id];
504  
505 -- Add to the my ads table
506 ad.text = text;
507 ad.itemColor = color;
508 ad.itemRef = ref;
509 ad.itemName = name;
510 ad.count = count;
511 ad.texture = texture;
512  
513 -- Notify listeners
514 GAS_NotifyListeners(GAS_EVENT_ADDMY, adtype, ad);
515  
516 -- Notify everyone
517 if (GuildAds.Config.PublishMyAds) then
518 GAC_SendingUpdate(nil, 1);
519 GAC_SendAd(nil, adtype, ad);
520 end
521 return id;
522 end
523  
524  
525 ---------------------------------------------------------------------------------
526 --
527 -- Remove a my ad
528 --
529 ---------------------------------------------------------------------------------
530 function GAS_RemoveMyAd(adtype, id)
531 for key, ad in MyAdsTable[adtype] do
532 if (ad.id == id) then
533 table.remove(MyAdsTable[adtype], key);
534  
535 -- Notify listener
536 GAS_NotifyListeners(GAS_EVENT_REMOVEMY, adtype, id);
537  
538 -- Notify everyone
539 if (GuildAds.Config.PublishMyAds) then
540 GAC_SendRemove(nil, adtype, id);
541 end
542  
543 -- Return
544 return
545 end
546 end
547 end
548  
549 ---------------------------------------------------------------------------------
550 --
551 -- Enable a my ad
552 --
553 ---------------------------------------------------------------------------------
554 function GAS_EnableMyAd(adtype, id)
555 MyAdsTable[adtype][id].m_Enabled = true;
556  
557 -- Notify everyone
558 if (GuildAds.Config.PublishMyAds) then
559 -- ChatFrame1:AddMessage("GAS_EnableMyAd("..NoNil(owner)..","..NoNil(adtype)..","..NoNil(id)..")");
560 GAC_SendingUpdate(nil, 1);
561 GAC_SendAd(nil, adtype, MyAdsTable[adtype][id]);
562 end
563 end
564  
565 ---------------------------------------------------------------------------------
566 --
567 -- Disable a my ad
568 --
569 ---------------------------------------------------------------------------------
570 function GAS_DisableMyAd(adtype, id)
571 MyAdsTable[adtype][id].m_Enabled = false;
572  
573 -- Notify everyone
574 if (GuildAds.Config.PublishMyAds) then
575 -- ChatFrame1:AddMessage("GAS_DisableMyAd("..NoNil(owner)..","..NoNil(adtype)..","..NoNil(id)..")");
576 GAC_SendRemove(nil, adtype, MyAdsTable[adtype][id].id);
577 end
578 end
579  
580 ---------------------------------------------------------------------------------
581 --
582 -- Add a global ad
583 --
584 ---------------------------------------------------------------------------------
585 function GAS_AddAd(owner, adtype, ad)
586 DEBUG_MSG("GAS_AddAd");
587 if (AdsTable[adtype]) then
588 table.insert(AdsTable[adtype], ad);
589 if adtype==GUILDADS_MSG_TYPE_REQUEST or adtype==GUILDADS_MSG_TYPE_AVAILABLE then
590 GAS_ScanItemsLine(adtype, owner, ad.itemName, 1, ad.count);
591 end
592 -- Notify listeners
593 GAS_NotifyListeners(GAS_EVENT_ADDGLOBAL, owner, adtype, ad);
594 end
595 end
596  
597 ---------------------------------------------------------------------------------
598 --
599 -- Remove an add by owner and id
600 --
601 ---------------------------------------------------------------------------------
602 function GAS_RemoveByOwnerAndId(owner, adtype, id)
603 if (AdsTable[adtype]) then
604 local size = table.getn(AdsTable[adtype]);
605 local i = 1;
606 while (i <= size) do
607 local ad = AdsTable[adtype][i];
608 if ((ad.owner == owner) and (ad.id == id)) then
609 table.remove(AdsTable[adtype], i);
610 size = size - 1;
611 if adtype==GUILDADS_MSG_TYPE_REQUEST or adtype==GUILDADS_MSG_TYPE_AVAILABLE then
612 GAS_ScanItemsLine(adtype, owner, ad.itemName, -1, ad.count)
613 end
614 -- Notify listeners
615 GAS_NotifyListeners(GAS_EVENT_REMOVEGLOBAL, owner, adtype, id);
616 else
617 i = i + 1;
618 end
619 end
620 else
621 -- ChatFrame1:AddMessage("Problème avec GAS_RemoveByOwnerAndId("..NoNil(owner)..","..NoNil(adtype)..","..NoNil(id)..")");
622 end
623 end
624  
625 ----------------------------------------------------------------------------------
626 --
627 -- Remove all ads by owner
628 --
629 ---------------------------------------------------------------------------------
630 function GAS_RemoveByOwner(owner, adtype)
631 if (AdsTable[adtype]) then
632 local size = table.getn(AdsTable[adtype]);
633 local i = 1;
634 while (i <= size) do
635 local ad = AdsTable[adtype][i];
636 if (ad.owner == owner) then
637 table.remove(AdsTable[adtype], i);
638 size = size - 1;
639 if adtype==GUILDADS_MSG_TYPE_REQUEST or adtype==GUILDADS_MSG_TYPE_AVAILABLE then
640 GAS_ScanItemsLine(adtype, owner, ad.itemName, -1, ad.count)
641 end
642 -- Notify listeners
643 GAS_NotifyListeners(GAS_EVENT_REMOVEGLOBAL, owner, adtype, id);
644 else
645 i = i + 1;
646 end
647 end
648 else
649 -- ChatFrame1:AddMessage("Problème avec GAS_RemoveByOwner("..NoNil(owner)..","..NoNil(adtype)..","..NoNil(id)..")");
650 end
651 end
652  
653 ---------------------------------------------------------------------------------
654 --
655 -- Get Skill id, name, group
656 --
657 ---------------------------------------------------------------------------------
658 function GAS_GetSkillId(SkillName)
659 for id, name in GUILDADS_SKILLS do
660 if (name == SkillName) then
661 return id;
662 end
663 end
664 return -1;
665 end
666  
667 function GAS_GetSkillText(SkillId)
668 if (GUILDADS_SKILLS[SkillId]) then
669 return GUILDADS_SKILLS[SkillId];
670 else
671 return "";
672 end
673 end
674  
675 ---------------------------------------------------------------------------------
676 --
677 -- Get Class id, name
678 --
679 ---------------------------------------------------------------------------------
680 function GAS_GetClassId(ClassName)
681 for id, name in GUILDADS_CLASSES do
682 if (name == ClassName) then
683 return id;
684 end
685 end
686 return -1;
687 end
688  
689 function GAS_GetClassText(ClassId)
690 if (GUILDADS_CLASSES[ClassId]) then
691 return GUILDADS_CLASSES[ClassId];
692 else
693 return ClassId;
694 end
695 end
696  
697 ---------------------------------------------------------------------------------
698 --
699 -- Get Race id, name
700 --
701 ---------------------------------------------------------------------------------
702 function GAS_GetRaceId(RaceName)
703 for id, name in GUILDADS_RACES do
704 if (name == RaceName) then
705 return id;
706 end
707 end
708 return -1;
709 end
710  
711 function GAS_GetRaceText(RaceId)
712 if (GUILDADS_RACES[RaceId]) then
713 return GUILDADS_RACES[RaceId];
714 else
715 return RaceId;
716 end
717 end
718  
719 ----------------------------------------------------------------------------------
720 --
721 -- GAS_ScanItems
722 --
723 ---------------------------------------------------------------------------------
724 function GAS_ScanItems()
725 GuildAdsItems = {};
726 for k,v in AdsTable[GUILDADS_MSG_TYPE_REQUEST] do
727 if (v.itemName) then
728 GAS_ScanItemsLine(GUILDADS_MSG_TYPE_REQUEST, v.owner, v.itemName, 1, v.count);
729 end
730 end
731 for k,v in AdsTable[GUILDADS_MSG_TYPE_AVAILABLE] do
732 if (v.itemName) then
733 GAS_ScanItemsLine(GUILDADS_MSG_TYPE_AVAILABLE, v.owner, v.itemName, 1, v.count);
734 end
735 end
736 end
737  
738 local function GAS_GetItemIndex(adtype, author, itemName)
739 for index, data in GuildAdsItems[itemName][adtype] do
740 if data.owner==author then
741 return index;
742 end
743 end
744 return nil;
745 end
746  
747 function GAS_ScanItemsLine(adtype, author, itemName, delta, count)
748 if (itemName ~= nil) then
749 if (GuildAdsItems[itemName] == nil) then
750 GuildAdsItems[itemName] = {
751 [GUILDADS_MSG_TYPE_REQUEST] = {};
752 [GUILDADS_MSG_TYPE_AVAILABLE] = {};
753 };
754 end
755 local inf = false;
756 if (count==nil) then
757 count = 0;
758 inf = true;
759 end
760  
761 local index = GAS_GetItemIndex(adtype, author, itemName);
762  
763 if index then
764 local t = GuildAdsItems[itemName][adtype][index];
765 t.count = t.count+delta*count;
766 if inf then
767 if delta>0 then
768 t.inf = true;
769 else
770 t.inf = false;
771 end
772 end
773 if (t.count==0) and (not t.inf) then
774 tremove(GuildAdsItems[itemName][adtype], index);
775 end
776 else
777 if (delta>0) then
778 tinsert(GuildAdsItems[itemName][adtype], {
779 count = count;
780 inf = inf;
781 owner = author;
782 });
783 end
784 end
785 table.sort(GuildAdsItems[itemName][adtype], GAS_PredicateAds);
786 end
787 end
788  
789 function GAS_PredicateAds(a, b)
790 -- nil references are always less than
791 if (a == nil) then
792 if (b == nil) then
793 return false;
794 else
795 return true;
796 end
797 elseif (b == nil) then
798 return false;
799 end
800  
801 -- inf/count
802 if (a.inf) then
803 if (not b.inf) then
804 return true;
805 end
806 else
807 if (b.inf) then
808 return false;
809 else
810 if (a.count < b.count) then
811 return false;
812 elseif (a.count > b.count) then
813 return true;
814 end
815 end
816 end
817  
818 -- owner
819 if (a.owner<b.owner) then
820 return true;
821 elseif (a.owner>b.owner) then
822 return false;
823 end
824  
825 -- same
826 return false;
827 end
828  
829 function GAS_GetItemAdsInfo(itemName)
830 if GuildAdsItems[itemName] then
831 return GuildAdsItems[itemName][GUILDADS_MSG_TYPE_REQUEST], GuildAdsItems[itemName][GUILDADS_MSG_TYPE_AVAILABLE];
832 else
833 return;
834 end
835 end
836  
837 function GAS_UnpackLink(link)
838 local start, _, color, ref, name = string.find(link, "|c([%w]+)|H([^|]+)|h%[([^|]+)%]|h|r");
839 if (start) then
840 return color, ref, name;
841 else
842 local _, _, color, name = string.find(link, "|c([%w]+)%[([^|]+)%]|r");
843 return color, nil, name;
844 end
845 end
846  
847 function GAS_PackLink(color, ref, name)
848 if (ref) then
849 color = color or "ffffffff";
850 name = name or "??";
851 return "|c"..color.."|H"..ref.."|h["..name.."]|h|r";
852 else
853 return "|c"..color.."["..name.."]|r";
854 end
855 end
856  
857 local function GAS_MakeIntFromHexString(str)
858 local remain = str;
859 local amount = 0;
860 while( remain ~= "" ) do
861 amount = amount * 16;
862 local byteVal = string.byte(strupper(strsub(remain, 1, 1)));
863 if( byteVal >= string.byte("0") and byteVal <= string.byte("9") ) then
864 amount = amount + (byteVal - string.byte("0"));
865 elseif( byteVal >= string.byte("A") and byteVal <= string.byte("F") ) then
866 amount = amount + 10 + (byteVal - string.byte("A"));
867 end
868 remain = strsub(remain, 2);
869 end
870 return amount;
871 end
872  
873 function GAS_GetRGBFromHexColor(hexColor)
874 local red = GAS_MakeIntFromHexString(strsub(hexColor, 3, 4)) / 255;
875 local green = GAS_MakeIntFromHexString(strsub(hexColor, 5, 6)) / 255;
876 local blue = GAS_MakeIntFromHexString(strsub(hexColor, 7, 8)) / 255;
877 return red, green, blue;
878 end
879  
880 ---------------------------------------------------------------------------------
881 --
882 -- Get item information (GetItemInfo)
883 --
884 ---------------------------------------------------------------------------------
885 function GAS_GetItemInfo(itemRef)
886 if not(itemInfo[itemRef] and itemInfo[itemRef].type) then
887 -- GetAuctionItemClasses(); GetAuctionItemSubClasses(index)
888 -- itemTexture valid [since|in futur] patch 1.9
889 local _, _, itemLink1, itemLink2, itemLink3, itemLink4 = string.find(itemRef, "item:(%d+):(%d+):(%d+):(%d+)");
890 local itemName, itemLink, itemRarity, itemMinLevel, itemType, itemSubType, itemStackCount, itemSlot, itemTexture;
891 if itemLink1 and itemLink2 == "0" and itemLink3 == "0" and itemLink4 == "0" then
892 itemName, itemLink, itemRarity, itemMinLevel, itemType, itemSubType, itemStackCount, itemSlot, itemTexture = GetItemInfo(itemLink1);
893 else
894 -- GuildAdsInternalTooltip:SetHyperlink(itemRef);
895 -- GuildAdsInternalTooltip:Show();
896 itemName, itemLink, itemRarity, itemMinLevel, itemType, itemSubType, itemStackCount, itemSlot, itemTexture = GetItemInfo(itemRef);
897 if not itemName then
898 _, itemLink, itemRarity, itemMinLevel, itemType, itemSubType, itemStackCount, itemSlot, itemTexture = GetItemInfo(itemLink1);
899 end
900 end
901  
902 if itemSlot and getglobal(itemSlot) then
903 itemSlot = getglobal(itemSlot);
904 end
905 itemInfo[itemRef] = { };
906 itemInfo[itemRef].type = itemType;
907 itemInfo[itemRef].subtype = itemSubType;
908 itemInfo[itemRef].slot = itemSlot;
909 itemInfo[itemRef].rarity = itemRarity;
910 itemInfo[itemRef].stackcount = itemStackCount;
911 itemInfo[itemRef].minlevel = itemMinLevel;
912 itemInfo[itemRef].name = itemName;
913 itemInfo[itemRef].texture = itemTexture;
914 end
915 return itemInfo[itemRef];
916 end