Quantcast
Download
(71 Kb)
Download
Updated: 01/11/17 01:53 PM
Compatibility:
Homestead (2.7)
One Tamriel (2.6)
Updated:01/11/17 01:53 PM
Created:04/01/16 01:30 PM
Monthly downloads:239
Total downloads:4,082
Favorites:14
MD5:
LibGroupSocket
Version: r2
by: sirinsidiator [More]
For Players
In order to follow ZOS' opt out policy (brought up in regards to Group Damage), LibGroupSocket gives you fine grained control over what data you share with your group. Per default it automatically disables the sending of all data when you leave a group, or quit the game.
You can download and install LibGroupSocket like any other addon, in order to enable saving settings for it.

For Developers
LibGroupSocket offers a standardized way to share data with group members via map pings. It allows the sending of up to 3 byte of data in one ping or 7 bytes in 2 pings at a time.
Because the channel is very limited, there is currently only a maximum of 31 different message types supported.
If you are interested in adding a new message type, please contact me via pm and I will reserve an ID.
It is also encouraged to reuse existing message types and expand on them instead of adding a new one that does the same thing, but slightly different.

This first version of the library is mostly a trial to see how it will work in combination with the many other addons out there and also to see how ZOS will react and how much interest it generates with players.
For future versions I am considering to split message handlers into separate libraries, so they can be updated independently.

Known Issues
  • The library is currently not compatible with FTC's DPS sharing feature and you and all group members will see wrong values in FTC while LibGroupSocket is active
  • User set group pings may cause incorrect data to show up in same rare cases
  • User set group pings are overwritten when data is transmitted
  • The compass may show the automatically set group pings
  • Users without LibGroupSocket will see random group pings pop up in Wrothgar or Coldharbour
  • Settings for LibGroupSocket won't be saved unless you use the stand alone version.
  • Sometimes you may hear a sound when a ping is set

API Reference

ReadBit
Reads a bit from the data stream and increments the index and bit index accordingly.
Code:
boolean isSet, number nextIndex, number nextBitIndex = lib:ReadBit(table data, number index, number bitIndex)
data - an array of integers between 0 and 255
index - the current position to read from
bitIndex - the current bit inside the current byte (starts from 1)
Returns the state of the bit, the next position in the data array and the next bitIndex.

WriteBit
Writes a bit to the data stream and increments the index and bit index accordingly.
Code:
number nextIndex, number nextBitIndex = lib:WriteBit(table data, number index, number bitIndex, boolean value)
data - an array of integers between 0 and 255
index - the current position to write to
bitIndex - the current bit inside the current byte (starts from 1)
value - the new state of the bit
Returns the next position in the data array and the next bitIndex.

ReadChar
Reads a single byte from the data stream, converts it into a string character and increments the index accordingly.
Code:
string character, number nextIndex = lib:ReadChar(table data, number index)
data - an array of integers between 0 and 255
index - the current position to read from
Returns the character and the next position in the data array.

WriteChar
Writes a single character to the data stream and increments the index accordingly.
Code:
number nextIndex = lib:WriteChar(table data, number index, string value[, number charIndex])
data - an array of integers between 0 and 255
index - the current position to write to
value - a single character or a string of characters
charIndex - optional index of the character that should be written to the data stream. Defaults to the first character
Returns the next position in the data array.

ReadUint8
Reads a single byte from the data stream and increments the index accordingly.
Code:
number value, number nextIndex = lib:ReadUint8(table data, number index)
data - an array of integers between 0 and 255
index - the current position to read from
Returns the 8-bit unsigned integer and the next position in the data array.

WriteUint8
Writes an 8-bit unsigned integer to the data stream and increments the index accordingly. The value is clamped and floored to match the data type.
Code:
number nextIndex = lib:WriteUint8(table data, number index, string value)
data - an array of integers between 0 and 255
index - the current position to write to
value - an 8-bit unsigned integer
Returns the next position in the data array.

ReadUint16
Reads two byte from the data stream, converts them to one integer and increments the index accordingly.
Code:
number value, number nextIndex = lib:ReadUint16(table data, number index)
data - an array of integers between 0 and 255
index - the current position to read from
Returns the 16-bit unsigned integer and the next position in the data array.

WriteUint16
Writes a 16-bit unsigned integer to the data stream and increments the index accordingly. The value is clamped and floored to match the data type.
Code:
number nextIndex = lib:WriteUint16(table data, number index, string value)
data - an array of integers between 0 and 255
index - the current position to write to
value - a 16-bit unsigned integer
Returns the next position in the data array.

EncodeData
Converts 4 bytes of data into coordinates for a map ping.
Code:
number x, number y = lib:EncodeData(number b0, number b1, number b2, number b3, number stepSize)
b0 to b3 - integers between 0 and 255
Step size specifies the smallest possible increment for the coordinates on a map.
Returns normalized x and y coordinates.

DecodeData
Converts normalized map ping coordinates into 4 bytes of data.
Code:
number b0, number b1, number b2, number b3 = lib:DecodeData(number x, number y, number stepSize)
Step size specifies the smallest possible increment for the coordinates on a map.
Returns 4 integers between 0 and 255.

MessageType
MessageType is an enumeration of implemented message types.
lib.MESSAGE_TYPE_RESERVED: Reserved in case we ever have more than 31 message types. Can also be used for local tests.
lib.MESSAGE_TYPE_RESOURCES: For exchanging stamina and magicka values.

EncodeHeader
Packs a 5-bit messageType and a 3-bit length value into one byte of data.
Code:
number value = lib:EncodeHeader(MessageType messageType, number length)
messageType - integer between 0 and 31
length - integer between 0 and 7
Returns encoded header byte.

DecodeHeader
Unpacks a 5-bit messageType and a 3-bit length value from one byte of data.
Code:
MessageType messageType, number length = lib:DecodeHeader(number value)
value - integer between 0 and 255
Returns messageType and length.

Send
Queues up to seven byte of data of the selected messageType for broadcasting to all group members.
Code:
boolean isValid = lib:Send(MessageType messageType, table data)
messageType - the protocol that is used for encoding the sent data
data - up to 7 byte of custom data. if more than 3 bytes are passed, the data will take 2 map pins to arrive.
Returns true if the data was successfully queued. Data won't be queued when the general sending setting is off or an invalid value was passed.

RegisterHandler
Registers a handler module for a specific data type.
This module will keep everything related to data handling out of any single addon, in order to let multiple addons use the same messageType.
Code:
table handler, table saveData = lib:RegisterHandler(MessageType messageType, table data)
messageType - The messageType the handler will take care of
handlerVersion - The loaded handler version. Works like the minor version in LibStub and prevents older instances from overwriting a newer one
Returns the handler object and saveData for the messageType.

GetHandler
Gives access to an already registered handler for addons.
Code:
table handler = lib:GetHandler(MessageType messageType)
messageType - The messageType of the handler
Returns the handler object.

RegisterCallback
Register for unprocessed data of a messageType.
Code:
lib:RegisterCallback(MessageType messageType, function callback)
UnregisterCallback
Unregister for unprocessed data of a messageType.
Code:
lib:UnregisterCallback(MessageType messageType, function callback)
/lgs
Gives access to the "enabled" setting via a chat command.
Code:
/lgs <1/0>
r2:
- reserved message type for Solinur's dps handler
- fixed settings not getting saved, even when the library is installed as a standalone addon
* NOTE: this required a small change to the way how handlers initialize their settings
- added flag to resource handler to transmit which resource pool is larger
* NOTE: when only the percentage is transmitted by a player, it will set the max value of the larger pool to 2k instead of 1k
Optional Files (0)


Archived Files (1)
File Name
Version
Size
Author
Date
r1
70kB
sirinsidiator
04/01/16 01:30 PM


Post A Reply Comment Options
Unread 02/09/18, 02:56 PM  
marlonbrando
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 34
Uploads: 3
Re: Re: sending seems to stop occasionally

Originally Posted by sirinsidiator
Originally Posted by marlonbrando
I've recently rewritten my addon to use LibGroupSocket rather than LibMapPing at a great decrease in code size and complexity. Thanks. Great library.

I have a problem that is difficult (for me) to debug, though. Every so often one player seemingly stops sending even when LGS:Send() does not return false. I haven't been able to figure out what causes the issue, though. I thought maybe it happened to player a when player b logs out or when player b zones a lot but I can't confirm that. When player seems to stops sending, both player a and player b see player b's pings but neither sees pings from a.

Any hints on the best way to debug this? I can obviously just start sprinkling debugging d()'s throughout LibGroupSocket but that has a tendency to overload chat and sometimes the issue takes five minutes or more to crop up. Is there a more elegant way to debug a situation where a player apparently isn't sending? I think I've debugged this all the way down to the point where the code is calling LGS:Send so I don't think it's something obviously wrong with my code although typing this could very well lead to an aha! moment once I hit "Submit Reply".
Unfortunately this is one of the problems I mentioned in the LibMapPing comments. I haven't gotten around to test it with LGS2 yet, but it should be fixed since it handles outgoing pings differently in order to provide a global queuing mechanism.
Aha. If I reduce the frequency of my sends would that reduce the possibility of a problem too?

Right now, I'm sending player information every second but I could (and should) only send information if something changes.
Report comment to moderator  
Reply With Quote
Unread 02/09/18, 01:57 PM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1047
File comments: 638
Uploads: 27
Re: sending seems to stop occasionally

Originally Posted by marlonbrando
I've recently rewritten my addon to use LibGroupSocket rather than LibMapPing at a great decrease in code size and complexity. Thanks. Great library.

I have a problem that is difficult (for me) to debug, though. Every so often one player seemingly stops sending even when LGS:Send() does not return false. I haven't been able to figure out what causes the issue, though. I thought maybe it happened to player a when player b logs out or when player b zones a lot but I can't confirm that. When player seems to stops sending, both player a and player b see player b's pings but neither sees pings from a.

Any hints on the best way to debug this? I can obviously just start sprinkling debugging d()'s throughout LibGroupSocket but that has a tendency to overload chat and sometimes the issue takes five minutes or more to crop up. Is there a more elegant way to debug a situation where a player apparently isn't sending? I think I've debugged this all the way down to the point where the code is calling LGS:Send so I don't think it's something obviously wrong with my code although typing this could very well lead to an aha! moment once I hit "Submit Reply".
Unfortunately this is one of the problems I mentioned in the LibMapPing comments. I haven't gotten around to test it with LGS2 yet, but it should be fixed since it handles outgoing pings differently in order to provide a global queuing mechanism.
__________________
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Report comment to moderator  
Reply With Quote
Unread 02/08/18, 11:49 PM  
marlonbrando
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 34
Uploads: 3
sending seems to stop occasionally

I've recently rewritten my addon to use LibGroupSocket rather than LibMapPing at a great decrease in code size and complexity. Thanks. Great library.

I have a problem that is difficult (for me) to debug, though. Every so often one player seemingly stops sending even when LGS:Send() does not return false. I haven't been able to figure out what causes the issue, though. I thought maybe it happened to player a when player b logs out or when player b zones a lot but I can't confirm that. When player seems to stops sending, both player a and player b see player b's pings but neither sees pings from a.

Any hints on the best way to debug this? I can obviously just start sprinkling debugging d()'s throughout LibGroupSocket but that has a tendency to overload chat and sometimes the issue takes five minutes or more to crop up. Is there a more elegant way to debug a situation where a player apparently isn't sending? I think I've debugged this all the way down to the point where the code is calling LGS:Send so I don't think it's something obviously wrong with my code although typing this could very well lead to an aha! moment once I hit "Submit Reply".
Report comment to moderator  
Reply With Quote
Unread 01/14/18, 05:57 PM  
decay2
AddOn Author - Click to view AddOns

Forum posts: 65
File comments: 279
Uploads: 6
Originally Posted by Tactitocalon
I looked through ZOS addon terms and could not find any mention of an opt-out policy.
This was mentioned by ZOS in the discussion about GroupDamage. I think it was in the official forums.
Last edited by decay2 : 01/14/18 at 05:57 PM.
Report comment to moderator  
Reply With Quote
Unread 01/07/18, 02:28 PM  
Tactitocalon
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 10
Uploads: 4
Originally Posted by sirinsidiator
Originally Posted by Tactitocalon
Can LGS be modified so that saveData.enabled is on by default?
It's off by default for a reason:


When LGS is installed as a standalone addon (and starting in the next version I am working on right now in any case) it will remember the settings.
I looked through ZOS addon terms and could not find any mention of an opt-out policy.

Even if there was one, it should be the sole responsibility of the addon utilizing the library to control whether sending is permitted.

Making such a user-unfriendly requirement to utilize this library just incentives people to make their own communication protocols (like FTC and Roll Call, both which can cause interference), which is something I'm thinking of doing myself.
Report comment to moderator  
Reply With Quote
Unread 01/07/18, 07:25 AM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1047
File comments: 638
Uploads: 27
Originally Posted by Tactitocalon
Can LGS be modified so that saveData.enabled is on by default?
It's off by default for a reason:

In order to follow ZOS' opt out policy (brought up in regards to Group Damage), LibGroupSocket gives you fine grained control over what data you share with your group. Per default it automatically disables the sending of all data when you leave a group, or quit the game.
When LGS is installed as a standalone addon (and starting in the next version I am working on right now in any case) it will remember the settings.
__________________
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Last edited by sirinsidiator : 01/07/18 at 07:26 AM.
Report comment to moderator  
Reply With Quote
Unread 01/06/18, 09:24 PM  
Tactitocalon
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 10
Uploads: 4
Can LGS be modified so that saveData.enabled is on by default?
Report comment to moderator  
Reply With Quote
Unread 01/06/18, 09:47 AM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1047
File comments: 638
Uploads: 27
Originally Posted by Tactitocalon
Originally Posted by decay2
Originally Posted by Tactitocalon
Can the sending permissions be changed to:
- have a different enabled flag for each MessageType
- be controllable by dependent addons (expose access to the enabled flag) rather than being only controlled by the library

Currently this library is not very usable because it requires the user to jump through a lot of hoops in order to enable sending, but there is no granularity for controlling which message types are and are not allowed to be sent.
This is not true. If an author follows the design, there should be an option for each message type. But if an author rather decides to keep the settings in his own addon instead there is not much that can be done.
Are you sure about that?

It seems that if "saveData.enabled" is set to false, message sending is disabled regardless of what the message type is.

Code:
function lib:Send(messageType, data)
	if(not saveData.enabled) then return false end
	if(not IsValidMessageType(messageType)) then Log("tried to send invalid messageType %s", tostring(messageType)) return false end
	if(not IsValidData(data)) then return false end
	--  TODO like all other api functions, this one also has a message rate limit. We need to avoid sending too much or we risk getting kicked
	lib.outgoing[#lib.outgoing + 1] = OutgoingPacket:New(messageType, data)
	if(not lib.isSending) then
		DoSend()
	else
		lib.hasMore = true
	end
	return true
end
@sirinsidiator can you please clarify?
There are two levels of "enabled". The global enable in the code you posted is for quickly switching it completely off, e.g. when you are in a group that doesn't use these addons (pugs etc).
The handlers implement their own enabled switch and settings:

Lua Code:
  1. function handler:Send()
  2.     if(not saveData.enabled or not IsUnitGrouped("player")) then return end
Lua Code:
  1. function handler:InitializeSettings(optionsData, IsSendingDisabled) -- TODO: localization
  2.     optionsData[#optionsData + 1] = {
  3.         type = "header",
  4.         name = "Resource Handler",
  5.     }
  6. optionsData[#optionsData + 1] = {
  7.     type = "checkbox",
  8.     name = "Enable sending",
  9.     tooltip = "Controls if the handler does send data. It will still receive and process incoming data.",
  10.     getFunc = function() return saveData.enabled end,
  11.     setFunc = function(value)
  12.         saveData.enabled = value
  13.         if(value) then StartSending() else StopSending() end
  14.     end,
  15.     disabled = IsSendingDisabled,
  16.     default = defaultData.enabled
  17. }
__________________
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Report comment to moderator  
Reply With Quote
Unread 01/05/18, 06:28 PM  
Tactitocalon
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 10
Uploads: 4
Originally Posted by decay2
Originally Posted by Tactitocalon
Can the sending permissions be changed to:
- have a different enabled flag for each MessageType
- be controllable by dependent addons (expose access to the enabled flag) rather than being only controlled by the library

Currently this library is not very usable because it requires the user to jump through a lot of hoops in order to enable sending, but there is no granularity for controlling which message types are and are not allowed to be sent.
This is not true. If an author follows the design, there should be an option for each message type. But if an author rather decides to keep the settings in his own addon instead there is not much that can be done.
Are you sure about that?

It seems that if "saveData.enabled" is set to false, message sending is disabled regardless of what the message type is.

Code:
function lib:Send(messageType, data)
	if(not saveData.enabled) then return false end
	if(not IsValidMessageType(messageType)) then Log("tried to send invalid messageType %s", tostring(messageType)) return false end
	if(not IsValidData(data)) then return false end
	--  TODO like all other api functions, this one also has a message rate limit. We need to avoid sending too much or we risk getting kicked
	lib.outgoing[#lib.outgoing + 1] = OutgoingPacket:New(messageType, data)
	if(not lib.isSending) then
		DoSend()
	else
		lib.hasMore = true
	end
	return true
end
@sirinsidiator can you please clarify?
Last edited by Tactitocalon : 01/05/18 at 06:28 PM.
Report comment to moderator  
Reply With Quote
Unread 01/05/18, 08:35 AM  
decay2
AddOn Author - Click to view AddOns

Forum posts: 65
File comments: 279
Uploads: 6
Originally Posted by Tactitocalon
Can the sending permissions be changed to:
- have a different enabled flag for each MessageType
- be controllable by dependent addons (expose access to the enabled flag) rather than being only controlled by the library

Currently this library is not very usable because it requires the user to jump through a lot of hoops in order to enable sending, but there is no granularity for controlling which message types are and are not allowed to be sent.
This is not true. If an author follows the design, there should be an option for each message type. But if an author rather decides to keep the settings in his own addon instead there is not much that can be done.
Report comment to moderator  
Reply With Quote
Unread 01/02/18, 04:06 PM  
Tactitocalon
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 10
Uploads: 4
Can the sending permissions be changed to:
- have a different enabled flag for each MessageType
- be controllable by dependent addons (expose access to the enabled flag) rather than being only controlled by the library

Currently this library is not very usable because it requires the user to jump through a lot of hoops in order to enable sending, but there is no granularity for controlling which message types are and are not allowed to be sent.
Report comment to moderator  
Reply With Quote
Unread 09/06/17, 01:23 AM  
Taonnor
AddOn Author - Click to view AddOns

Forum posts: 6
File comments: 37
Uploads: 1
Will this lib be updated and supported?
Report comment to moderator  
Reply With Quote
Unread 05/17/16, 11:42 AM  
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view AddOns

Forum posts: 1047
File comments: 638
Uploads: 27
Originally Posted by Scootworks
which addons are supported atm?
Only GroupResources as far as I am aware.
__________________
>siri.exe MyAddon
Does your addon work? [y/n] n
There is a typo in there.
Report comment to moderator  
Reply With Quote
Unread 05/17/16, 10:37 AM  
Scootworks
 
Scootworks's Avatar
AddOn Author - Click to view AddOns

Forum posts: 187
File comments: 242
Uploads: 18
which addons are supported atm?
Report comment to moderator  
Reply With Quote
Unread 04/30/16, 02:15 PM  
Kyoma
AddOn Author - Click to view AddOns

Forum posts: 39
File comments: 73
Uploads: 6
Originally Posted by sirinsidiator
Originally Posted by Kyoma
Hey, I had a question and possibly a request. What I'm looking for is a way to send/transmit your unitId to other users in your group using this library.

I am looking for this so I can do some cool things in RaidNotifier. Many (if not all) effects & actions from bosses/mobs still supply the unitId in EVENT_EFFECT_CHANGED and EVENT_COMBAT_EVENT. So instead of trying to send an event/warning/ping for whatever mechanic I want to share between group mates I can just send my unitId (to everybody that also has the lib/addon) and let each person's addon handle all the actual checks.

Obtaining your unitId is somewhat easy, I just monitor for the player blocking like this:
Code:
local myUnitId = 0
local function OnEffectChanged(_, change, _, _, _, _, _, _, _, _, _, _, _, _, unitId, abilityId)
	if change == EFFECT_RESULT_GAINED then
		if myUnitId ~= unitId then
			d("I'm blocking! My unitId is "..unitId)
		end
		myUnitId = unitId
	end
end
EVENT_MANAGER:RegisterForEvent("TMP42", EVENT_EFFECT_CHANGED, OnEffectChanged)
EVENT_MANAGER:AddFilterForEvent("TMP42", EVENT_EFFECT_CHANGED, REGISTER_FILTER_ABILITY_ID, 14890, REGISTER_FILTER_UNIT_TAG, "player")
Then I'd need to send this whenever the group changes or is formed.

So here comes the actual question, how do I transmit/send a number between like 20000 and 90000 using LibGroupSocket? I'm guessing I gotta split it up but how would that work exactly?

P.S. This still won't magically enable something like GroupDamage because everything that comes FROM a player will just have a unitId of 0.
You are correct. For values that don't fit into the provided data types you would need to write your own method for serializing and deserializing them.
That said, I am not sure if what you suggest will work. As far as I am aware these ids are local to each client, so different players can have different ids for the same unit.
Hmmm yes, that might actually be the case, damn. :/

Edit: Omg I'm such an idiot, the unitTag can just be used to see who the unitId belongs to, I could've sworn I tested that and that they were left blank/empty.
Last edited by Kyoma : 04/30/16 at 02:38 PM.
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.