Quantcast
Download
(115 Kb)
Download
Updated: 10/31/20 05:32 AM
Pictures
File Info
Compatibility:
Markarth (6.2.5)
Stonethorn (6.1.5)
Updated:10/31/20 05:32 AM
Created:10/25/20 04:32 PM
Monthly downloads:18,852
Total downloads:19,279
Favorites:48
MD5:
Categories:Libraries, Data Mods
6.2.5
LibHistoire - Guild History  Popular! (More than 5000 hits)
Version: 1.0.2
by: sirinsidiator [More]
What is this library for?
Up until now, addons had to send guild history requests to the server individually, which in the past has lead to huge performance problems as more and more players started using these addons and ultimately forced ZOS to throttle how fast they are allowed to send automated requests for the guild history. In order to alleviate this problem and take a lot of the complexity away from individual addons, this library was born. Instead of having each addon send requests, it will all be taken care of by LibHistoire and they will simply become passive listeners.

The library will take care of loading missing history from the server in the background and store everything locally so it never has to request the same time range more than once.

Right now the game provides the history in an inverse order (future to past) of what addons actually try to use (past to future), so before the library passes any events to addons, it will attempt to load the full time range since you last played the game. During this time, it will keep them in a temporary "unlinked" state and only when it encounters the last stored event, it will save them and start sending events to listening addons. If you quit the game before that happens, all progress will be lost and it will have to start over from the beginning the next time you log in.

You can speed this process up by manually requesting missing history via the guild history menu, as this action won't be subject to the cooldown any addon has to deal with. Another option is to tell the library to force a link with what data it has got and create a hole in your history. You can always manually request more history events and trigger a rescan which will find any missing entries later.

Unlike other addons, the library won't request the full range of history provided by the server when you first use it. Instead it will immediately force a link and start collecting data from there. If you want to collect older history in that situation, you will need to manually request it and then hit the rescan button for that guild and category.

Dependencies
The following dependencies are required by LibHistoire:
  • LibAsync - to minimize fps loss while processing history events
  • LibCustomMenu - for the options menu of the status window
  • LibDebugLogger - for logging useful debug information in case something goes wrong

Some observations on what the server does
  • Requesting older history events via an addon starts a cooldown
  • The cooldown is separate for each guild and category, meaning an addon can send up to 20 requests at once
  • Simply put the interval between requests depends on how many players are currently online and is dynamically controlled by the server
  • Interval can be anything from a few seconds (on PTS) to several minutes during primetime EU. I've often seen values between 3 and 4 minutes while developing the library
  • New events are pushed automatically by the server with no way for addons to influence that process
  • The time between new events varies greatly and seems to depend on the how many players are online and how many events a guild produces
  • Sometimes the updates arrive almost instantly, sometimes they don't arrive for several hours - I've had to wait 2-3 hours quite often before any new guild history arrived
  • Ocassionally the updates never arrive (even after waiting for 5 hours) and restarting the game is the only way to force an update in that situation

User Interface

The status icon on the bottom right of the guild history symbolizes the link status of the currently viewed category in the selected guild. On hover it will show a tooltip that gives information about the stored history and unlinked events.


The new guild history status panel will provide an overview of what LibHistoire has stored and what is missing.

On the left side it will show each guild and the overall progress, on the right side it will show the categories for the currently selected guild.
Clicking on a guild or category will update the selection in both the status window and the guild history menu accordingly.
When you hover over any of the entries, a tooltip will show you the same information as the tooltip in the guild history menu.
The category entries also house the force link button (while the category is unlinked) and the rescan button (after it has linked up with stored events).
On the bottom of the panel you can see an icon which symbolizes the overall state and gives some general information about what is happening when you hover over it.
The cog button on the top right will open a context menu with an option to unlock the window so it can be moved and an option to hide it (same as the button on the bottom left of the guild history)

Special Thanks
FooWasHere who helped me test how the history behaves on rank and permission changes
ZOSDanBatson for answering my many questions about the history API
Everyone else who helped me test this and gave me feedback

For Developers
Why should you use it?
  • It minimizes the amount of requests sent by addons to the absolute minimum and if every addon starts using it, it will likely lower the cooldown the server chooses, so everyone gets their data faster.
  • It takes care of all the complexity that comes with requesting the history. There are many special cases you probably didn't even think about. The lib will handle them all for you.
  • It stores the history locally, so an addon can access time ranges that would be impossible via the game api
  • The data format minimizes impact on load time and disk space usage (compared to other addons like MM or ATT)

How does it work
The library listens to all incoming data and determines for each individual event if it has already been stored locally. It also takes care of sorting the events in the correct historic order and waits until the hole since the last login has been filled before saving them to disk and passing them to listeners.
When a listener starts, it will first iterate over available stored events, then wait for "unlinked" events to link before it iterates over those and finally start passing along newer events whenever they arrive. This is all done via LibAsync, so you will only get as many events per frame as you can safely process without affecting performance.
To avoid having to deserialize all stored events, it offers ways to select a starting point either by specifying an eventId or a timestamp*. It will do a binary search for the closest event and start from there instead of the beginning of the stored history.

*timestamps may not be 100% accurate as event times are returned from the game api as seconds since an event and manually converted to an absolute timestamp. This brings a certain inaccuracy with it and can lead to events being stored with timestamps that do not reflect their actual order. If precision is required it may be best to specify a timestamp a few seconds before the actual target time and use eventIds to identify an actual border for a time range.

API Reference
Callbacks
Can be accessed via the LibHistoire.callback table.

Code:
INITIALIZED()
Fired when Histy has finished initializing and is ready. Any call to the api (aside of RegisterCallback) should be done after it has fired.

Code:
HISTORY_RESCAN_STARTED(integer guildId, integer category)
Fired when the user or library triggered a rescan of the history.

Code:
HISTORY_RESCAN_ENDED(integer guildId, integer category, integer numEventsBefore, integer numEventsInside, integer numEventsAfter, boolean foundInvalidEvents)
Fired after a category rescan has finished. Invalid events are product of a bug where the game won't set the correct event time for a few seconds and the library will ignore them.

Library API
Code:
RegisterCallback(LibHistoire.callback type, function callback)
Register to a callback fired by the library. Usage is the same as with CALLBACK_MANAGER:RegisterCallback.

Code:
UnregisterCallback(LibHistoire.callback type, function callback)
Unregister from a callback. Usage is the same as with CALLBACK_MANAGER:UnregisterCallback.

Code:
LibHistoire.GuildHistoryEventListener listener = CreateGuildHistoryListener(integer guildId, integer category)
Creates a GuildHistoryEventListener object which can be configured before it starts listening to history events, or nil if guildId or category are not valid.
WARNING: Make sure you only call it after the INITIALIZED callback has fired, otherwise it may return nil.

GuildHistoryEventListener
Code:
boolean success = SetAfterEventId(id64 eventId)
Accepts an eventId (id64). The nextEventCallback will only return events which have a higher eventId when it is set. Will return true if it was called while the listener is not running, or false otherwise.

Code:
boolean success = SetAfterEventTime(integer eventTime)
If no afterEventId has been specified, the nextEventCallback will only receive events after the specified timestamp. Will return true if it was called while the listener is not running, or false otherwise.

Code:
boolean success = SetNextEventCallback(function callback)
Sets a callback which is passed stored and received events in the correct historic order (sorted by eventId). Will return true if it was called while the listener is not running, or false otherwise.
The callback has the following signature:
Code:
function(GuildEventType eventType, id64 eventId, integer eventTime, variable param1, variable param2, variable param3, variable param4, variable param5, variable param6)
More details about param1-6 can be found in guildhistory_shared.lua in the UI source code.

Code:
boolean success = SetMissedEventCallback(function callback)
Sets a callback which is passed missed events that are discovered during a rescan, ignoring any afterEventId or afterEventTime values. See SetNextEventCallback for details on the callback. Will return true if it was called while the listener is not running, or false otherwise.

Code:
boolean success = SetEventCallback(function callback)
A convenience function which will set both callback types in one go. See SetNextEventCallback for details on the callback. Will return true if it was called while the listener is not running, or false otherwise.

Code:
boolean success = Start()
Signals that the listener can start sending data to the addon. Will return true if it was called while the listener is not running, or false otherwise.

Code:
boolean success = Stop()
Signals that the listener to stop sending data to the addon. Will return true if it was called while the listener is running and has been stopped, or false otherwise.

Code:
boolean success = IsRunning()
Returns the current state of the listener.

Examples
Iterate over all stored events
Lua Code:
  1. LibHistoire:RegisterCallback(LibHistoire.callback.INITIALIZED, function()
  2.     local listener = LibHistoire:CreateGuildHistoryListener(guildId, category)
  3.     listener:SetEventCallback(function(eventType, eventId, eventTime, param1, param2, param3, param4, param5, param6)
  4.         -- do something with the event data
  5.     end)
  6.     listener:Start()
  7. end)
This will simply iterate over all stored events and then listen to any newly received data, including anything that will be found on a rescan.

Retrieve a time range
Lua Code:
  1. LibHistoire:RegisterCallback(LibHistoire.callback.INITIALIZED, function()
  2.     local listener = LibHistoire:CreateGuildHistoryListener(guildId, category)
  3.     listener:SetAfterEventTime(startTime)
  4.     listener:SetNextEventCallback(function(eventType, eventId, eventTime, param1, param2, param3, param4, param5, param6)
  5.         if eventTime > endTime then
  6.             listener:Stop()
  7.             return
  8.         end
  9.         -- do something with the event data
  10.     end)
  11.     listener:Start()
  12. end)
This example shows how to iterate over a specific time frame and then stop. SetAfterEventTime is preferable over just checking the eventTime in the callback, as it will be faster than just iterating everything.

Retrieve sales for different guilds and continue from last event
Lua Code:
  1. LibHistoire:RegisterCallback(LibHistoire.callback.INITIALIZED, function()
  2.     local function SetUpListener(guildId, category)
  3.         local listener = LibHistoire:CreateGuildHistoryListener(guildId, category)
  4.         local key = string.format("%d/%d", guildId, category)
  5.         listener:SetAfterEventId(StringToId64(saveData.lastEventId[key]))
  6.  
  7.         listener:SetNextEventCallback(function(eventType, eventId, eventTime, param1, param2, param3, param4, param5, param6)
  8.             -- the events received by this callback are in the correct historic order
  9.             saveData.lastEventId[key] = Id64ToString(eventId)
  10.         end)
  11.  
  12.         listener:SetMissedEventCallback(function(eventType, eventId, eventTime, param1, param2, param3, param4, param5, param6)
  13.             -- events in this callback are out of order compared to what has been received by the next event callback and can even have an eventId smaller than what has been specified via SetAfterEventId.
  14.         end)
  15.         listener:Start()
  16.     end
  17.  
  18.     for i = 1, GetNumGuilds() do
  19.         SetUpListener(GetGuildId(i), category)
  20.     end
  21. end)
This example will register listeners for all guilds and keep track of the last event id that has been processed by the addon. That way the library will pass every event to the listener only once. It will also handle events that have been found later during a manual rescan.
v1.0.1
- added new callback for when Histy is ready

v1.0.1 - initial release
Optional Files (0)


Archived Files (1)
File Name
Version
Size
Uploader
Date
1.0.1
115kB
sirinsidiator
10/25/20 04:32 PM


Post A Reply Comment Options
Unread 11/17/20, 03:38 AM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1446
File comments: 991
Uploads: 37
Originally Posted by gamingneeds
Which addons use this?

A buddy has it and was wondering what addon required it?

Thanks!
It's currently used by Master Merchant v3 and in the future other addons which require access to the guild history should use it too.
__________________
https://www.imperialtradingcompany.eu/ - My Addons - The Vault (Early updates and experimental projects) - My patreon - My blog
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Report comment to moderator  
Reply With Quote
Unread 11/17/20, 02:40 AM  
gamingneeds

Forum posts: 0
File comments: 5
Uploads: 0
Which addons use this?

A buddy has it and was wondering what addon required it?

Thanks!
Report comment to moderator  
Reply With Quote
Unread 11/10/20, 11:10 AM  
Verbalinkontinenz
 
Verbalinkontinenz's Avatar
AddOn Author - Click to view AddOns

Forum posts: 11
File comments: 241
Uploads: 2
Originally Posted by sirinsidiator
Originally Posted by Verbalinkontinenz
hmm did u think of a "press e" cooldown which collects the ampount of e pressed and makes sure, noone gets autokicked for spamming e?
That's not as easy as you may think. Addons cannot interfere with the keybind, otherwise it would follow the same cooldown that addons have.
hmm it was just an idea, never tried and thought into it deeper.
i just do remember things like shissus guild mail had such a cool down as example, but sure, worked otherwise.

i also wish i had a note-change-cooldown in the past to rush through guild rosters with my gm work as example instead of sitting there for an hour beeing artificially slowed down by zos or risking getting one kick after another (i got my acc 30min cooldown once after 3 or 4 kicks :])

i am sure there are also a lot of users for this type of activity, who would spam e without minding this might get them kicked from server.

edit: hmmm maybe this would make a good standalone addon. a cooldown-compendium for multiple activities :O
__________________
resigned GM
Just Traders (EU Belkarth)
Tamriel Stock Exchange (EU Rawl'Kha)
Bait Trading House (EU Wayrest)
Last edited by Verbalinkontinenz : 11/10/20 at 11:15 AM.
Report comment to moderator  
Reply With Quote
Unread 11/04/20, 01:48 PM  
Kwoung

Forum posts: 0
File comments: 38
Uploads: 0
Originally Posted by sirinsidiator
That's to be expected with the new update bringing in lots of new and returning players.
From the description of LibHistoire:


Once more addons start using LibHistoire, it should get better, because the server is less busy with sending out pointless requests for older history and can start sending the new events instead.
Ahh okay thanks for the quick response! The new system sucks for now apparently then, as I have gone 7+ hours with my guild history not updating until after I rebooted. Which when you are running raffles, a guild crown exchange, etc... becomes a serious problem.
Report comment to moderator  
Reply With Quote
Unread 11/04/20, 01:16 PM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1446
File comments: 991
Uploads: 37
Originally Posted by Kwoung
Anyone else having issues with the guild history not updating? IDK if it is this addon or the Markarth update, but my guild history is no longer updating until after I reboot my computer (which makes no sense unless there are locked files maybe?)? LibHistoire is clearly showing it has scanned all the events, but I look on my wifes screen and she has many guild events my game is missing.
That's to be expected with the new update bringing in lots of new and returning players.
From the description of LibHistoire:
  • New events are pushed automatically by the server with no way for addons to influence that process
  • The time between new events varies greatly and seems to depend on the how many players are online and how many events a guild produces
  • Sometimes the updates arrive almost instantly, sometimes they don't arrive for several hours - I've had to wait 2-3 hours quite often before any new guild history arrived
  • Ocassionally the updates never arrive (even after waiting for 5 hours) and restarting the game is the only way to force an update in that situation
Once more addons start using LibHistoire, it should get better, because the server is less busy with sending out pointless requests for older history and can start sending the new events instead.
__________________
https://www.imperialtradingcompany.eu/ - My Addons - The Vault (Early updates and experimental projects) - My patreon - My blog
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Last edited by sirinsidiator : 11/04/20 at 01:18 PM.
Report comment to moderator  
Reply With Quote
Unread 11/04/20, 11:23 AM  
Kwoung

Forum posts: 0
File comments: 38
Uploads: 0
Anyone else having issues with the guild history not updating? IDK if it is this addon or the Markarth update, but my guild history is no longer updating until after I reboot my computer (which makes no sense unless there are locked files maybe?)? LibHistoire is clearly showing it has scanned all the events, but I look on my wifes screen and she has many guild events my game is missing.
Report comment to moderator  
Reply With Quote
Unread 11/04/20, 08:50 AM  
Sharlikran
 
Sharlikran's Avatar
AddOn Author - Click to view AddOns

Forum posts: 166
File comments: 869
Uploads: 9
Originally Posted by Verbalinkontinenz
hmm did u think of a "press e" cooldown which collects the ampount of e pressed and makes sure, noone gets autokicked for spamming e?
I had added a pre hook for testing and when I did then as Siri mentioned then E had the same cooldown as mods do. So effectively what happened was it made it such that pressing E does nothing, literally. I thought ZOS had nerfed the key bind for me because other users said they could still press the key and get guild history which I could not. I even put in a ticket. Come to find out it was simply because I touched the keybind. You don't want to do that.
__________________
Admin for TES5Edit, occasional LOOT masterlist contributor, and Wrye Bash contributor. I also maintain special Fallout 3 and Fallout NV versions of Wrye Flash.
Last edited by Sharlikran : 11/04/20 at 08:50 AM.
Report comment to moderator  
Reply With Quote
Unread 11/03/20, 07:32 AM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1446
File comments: 991
Uploads: 37
Originally Posted by Verbalinkontinenz
hmm did u think of a "press e" cooldown which collects the ampount of e pressed and makes sure, noone gets autokicked for spamming e?
That's not as easy as you may think. Addons cannot interfere with the keybind, otherwise it would follow the same cooldown that addons have.
__________________
https://www.imperialtradingcompany.eu/ - My Addons - The Vault (Early updates and experimental projects) - My patreon - My blog
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Report comment to moderator  
Reply With Quote
Unread 11/02/20, 03:45 PM  
Verbalinkontinenz
 
Verbalinkontinenz's Avatar
AddOn Author - Click to view AddOns

Forum posts: 11
File comments: 241
Uploads: 2
hmm did u think of a "press e" cooldown which collects the ampount of e pressed and makes sure, noone gets autokicked for spamming e?
__________________
resigned GM
Just Traders (EU Belkarth)
Tamriel Stock Exchange (EU Rawl'Kha)
Bait Trading House (EU Wayrest)
Report comment to moderator  
Reply With Quote
Unread 10/31/20, 01:38 PM  
Wastelcat

Forum posts: 0
File comments: 54
Uploads: 0
Found, ty

Perfect,

ty for the qick help

Wastelcat
Report comment to moderator  
Reply With Quote
Unread 10/31/20, 12:19 PM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1446
File comments: 991
Uploads: 37
Re: How do i get the I please ?

Originally Posted by Wastelcat
Hi Mate,

thanks for your nice work.

I cant find a way to get the UI shown, please enlight me.

TiA

Wastelcat
Just open the guild history menu (press G and select the correct tab). It should show itself there when you have everything installed correctly.
__________________
https://www.imperialtradingcompany.eu/ - My Addons - The Vault (Early updates and experimental projects) - My patreon - My blog
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Last edited by sirinsidiator : 10/31/20 at 12:20 PM.
Report comment to moderator  
Reply With Quote
Unread 10/31/20, 11:01 AM  
Wastelcat

Forum posts: 0
File comments: 54
Uploads: 0
How do i get the I please ?

Hi Mate,

thanks for your nice work.

I cant find a way to get the UI shown, please enlight me.

TiA

Wastelcat
Last edited by Wastelcat : 10/31/20 at 11:52 AM.
Report comment to moderator  
Reply With Quote
Unread 10/29/20, 04:30 AM  
maximoz

Forum posts: 0
File comments: 13
Uploads: 0
I'm liking this visual way of getting the sales to be updated!
Report comment to moderator  
Reply With Quote
Unread 10/25/20, 11:45 PM  
spinality

Forum posts: 7
File comments: 71
Uploads: 0
Just wow

This is such a great effort, badly needed and much appreciated.
Report comment to moderator  
Reply With Quote
Post A Reply



Category Jump:

Support AddOn Development!

You have just downloaded by the author . If you like this AddOn why not consider supporting the author? This author has set up a donation account. Donations ensure that authors can continue to develop useful tools for everyone.