diff --git a/TaosGroupTools/TaosGroupTools.lua b/TaosGroupTools/TaosGroupTools.lua index 91347ce..61d27a9 100644 --- a/TaosGroupTools/TaosGroupTools.lua +++ b/TaosGroupTools/TaosGroupTools.lua @@ -60,7 +60,7 @@ function TaosGroupUltimate:initialize() TGU_SettingsHandler.Initialize(logger) -- Initialize communication - TGU_Communicator.Initialize(logger, TGU_SettingsHandler.SavedVariables.IsLgsActive, ISMOCKED) + TGU_Communicator.Initialize(logger, ISMOCKED) -- Initialize logic TGU_GroupHandler.Initialize(logger, ISMOCKED) diff --git a/TaosGroupTools/TaosGroupTools.txt b/TaosGroupTools/TaosGroupTools.txt index b77ae31..1e09518 100644 --- a/TaosGroupTools/TaosGroupTools.txt +++ b/TaosGroupTools/TaosGroupTools.txt @@ -22,7 +22,6 @@ libs/LibAddonMenu-2.0/controls/dropdown.lua libs/LibMapPing/LibMapPing.lua libs/LibGPS/LibGPS.lua -libs/LibGroupSocket/LibGroupSocket.lua i18n/de.lua i18n/$(language).lua diff --git a/TaosGroupTools/communication/Communicator.lua b/TaosGroupTools/communication/Communicator.lua index 3b5a295..e461633 100644 --- a/TaosGroupTools/communication/Communicator.lua +++ b/TaosGroupTools/communication/Communicator.lua @@ -15,7 +15,6 @@ if(not LMP) then end local _logger = nil -local _ultimateHandler = nil local ABILITY_COEFFICIENT = 100 local ULTIMATE_COEFFICIENT = 1000 @@ -31,25 +30,6 @@ TGU_Communicator.__index = TGU_Communicator ]]-- TGU_Communicator.Name = "TGU-Communicator" TGU_Communicator.IsMocked = false -TGU_Communicator.IsLgsActive = false - ---[[ - Called on data from LGS -]]-- -function TGU_Communicator.OnUltimateReceived(unitTag, ultimateCurrent, ultimateCost, ultimateGroupId, isSelf) - if (LOG_ACTIVE) then - _logger:logTrace("TGU_Communicator.OnUltimateReceived") - _logger:logDebug("unitTag; ultimateCurrent; ultimateCost; ultimateGroupId", unitTag, ultimateCurrent, ultimateCost, ultimateGroupId) - end - - local relativeUltimate = math.floor((ultimateCurrent / ultimateCost) * 100) - - if (relativeUltimate > 100) then - relativeUltimate = 100 - end - - CALLBACK_MANAGER:FireCallbacks(TGU_MAP_PING_CHANGED, unitTag, ultimateGroupId, relativeUltimate) -end --[[ Called on map ping from LibMapPing @@ -124,15 +104,6 @@ function TGU_Communicator.SendData(abilityGroup) -- Mocked if (TGU_Communicator.IsMocked) then TGU_Communicator.SendFakePings() - -- LGS communication - elseif (TGU_Communicator.IsLgsActive) then - if (_ultimateHandler ~= nil) then - _ultimateHandler:SetUltimateCost(abilityCost) - _ultimateHandler:SetUltimateGroupId(abilityGroup.GroupAbilityPing) - _ultimateHandler:Refresh() - else - _logger:logError("TGU_Communicator.SendData, _ultimateHandler is nil") - end -- Standard communication else local relativeUltimate = math.floor((current / abilityCost) * 100) @@ -267,52 +238,19 @@ function TGU_Communicator.SendFakePings() end --[[ - Updates communication type -]]-- -function TGU_Communicator.UpdateCommunicationType() - if (LOG_ACTIVE) then - _logger:logTrace("TGU_Communicator.UpdateCommunicationType") - end - - -- Unregister events - LMP:UnregisterCallback("BeforePingAdded", TGU_Communicator.OnMapPing) - LMP:UnregisterCallback("AfterPingRemoved", TGU_Communicator.OnMapPingFinished) - - if (TGU_Communicator.IsLgsActive) then - local LGS = LibStub:GetLibrary("LibGroupSocket") - - if (LGS ~= nil) then - if (_ultimateHandler == nil) then - _ultimateHandler = LGS:GetHandler(LGS.MESSAGE_TYPE_ULTIMATE) - end - - _ultimateHandler:RegisterForUltimateChanges(TGU_Communicator.OnUltimateReceived) - _ultimateHandler:Refresh() - else - _logger:logError("LGS not found. Please install LibGroupSocket. Activate default communication as fallback.") - TGU_Communicator.SetIsLgsActive(false) - end - else - -- Register events - LMP:RegisterCallback("BeforePingAdded", TGU_Communicator.OnMapPing) - LMP:RegisterCallback("AfterPingRemoved", TGU_Communicator.OnMapPingFinished) - end -end - ---[[ Initialize initializes TGU_Communicator ]]-- -function TGU_Communicator.Initialize(logger, isLgsActive, isMocked) +function TGU_Communicator.Initialize(logger, isMocked) if (LOG_ACTIVE) then logger:logTrace("TGU_Communicator.Initialize") - logger:logDebug("isLgsActive", isLgsActive) logger:logDebug("isMocked", isMocked) end _logger = logger TGU_Communicator.IsMocked = isMocked - - TGU_Communicator.IsLgsActive = isLgsActive - TGU_Communicator.UpdateCommunicationType() + + -- Register events + LMP:RegisterCallback("BeforePingAdded", TGU_Communicator.OnMapPing) + LMP:RegisterCallback("AfterPingRemoved", TGU_Communicator.OnMapPingFinished) end \ No newline at end of file diff --git a/TaosGroupTools/communication/UltimateHandler.lua b/TaosGroupTools/communication/UltimateHandler.lua deleted file mode 100644 index 906f376..0000000 --- a/TaosGroupTools/communication/UltimateHandler.lua +++ /dev/null @@ -1,243 +0,0 @@ --- The Ultimate Protocol --- *bitArray* flags, *uint8* ultimate[, *uint8* ultimateCost, *uint8* ultimageGroupId] --- flags: --- 1: isFullUpdate - the user is sending cost in addition to percentages in this packet --- 2: requestsFullUpdate - the user does not have all the necessary data and wants to have a full update from everyone (e.g. after reloading the ui) - -local LGS = LibStub("LibGroupSocket") -LGS.MESSAGE_TYPE_ULTIMATE = 21 -- aka, the code for 'u' -local type, version = LGS.MESSAGE_TYPE_ULTIMATE, 3 -local handler, saveData = LGS:RegisterHandler(type, version) -if(not handler) then return end -local SKIP_CREATE = true -local ON_ULTIMATE_CHANGED = "OnUltimateChanged" -local MIN_SEND_TIMEOUT = 2 -local MIN_COMBAT_SEND_TIMEOUT = 1 -local Log = LGS.Log - -handler.resources = {} -local resources = handler.resources -local sendFullUpdate = true -local needFullUpdate = true -local ultimateCost = 0 -local ultimateGroupId = 0 -local lastSendTime = 0 -local defaultData = { - version = 1, - enabled = true, -} -handler.callbacks = handler.callbacks or 0 - -local function GetCachedUnitResources(unitTag, skipCreate) - local unitName = GetUnitName(unitTag) - local unitResources = resources[unitName] - if(not unitResources and not skipCreate) then - resources[unitName] = { - [POWERTYPE_ULTIMATE] = {current=0, cost=0, groupId=0}, - lastUpdate = 0, - } - unitResources = resources[unitName] - end - return unitResources -end - -function handler:GetLastUpdateTime(unitTag) - local unitResources = GetCachedUnitResources(unitTag, SKIP_CREATE) - if(unitResources) then return unitResources.lastUpdate end - return -1 -end - -function handler:SetUltimateCost(cost) - ultimateCost = cost -end - -function handler:SetUltimateGroupId(groupId) - ultimateGroupId = groupId -end - -local function OnData(unitTag, data, isSelf) - if (handler.callbacks == 0) then return end --dont do anything if nobody is using this handler - - local index, bitIndex = 1, 1 - local isFullUpdate, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - local requestsFullUpdate, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - - -- Log("OnData %s (%d byte): is full: %s, needs full: %s", GetUnitName(unitTag), #data, tostring(isFullUpdate), tostring(requestsFullUpdate)) - index = index + 1 - if(not isSelf and requestsFullUpdate) then - sendFullUpdate = true - end - - --local expectedLength = isFullUpdate and 3 or 2 - --if(#data < expectedLength) then Log("UltimateHandler received only %d of %d byte", #data, expectedLength) return end - - local unitResources = GetCachedUnitResources(unitTag) - local ultimate = unitResources[POWERTYPE_ULTIMATE] - ultimate.current, index = LGS:ReadUint8(data, index) - if(isFullUpdate) then - ultimate.cost, index = LGS:ReadUint8(data, index) - ultimate.groupId, index = LGS:ReadUint8(data, index) - end - - unitResources.lastUpdate = GetTimeStamp() - - -- Log("ultimate: %d, cost: %d", ultimate.current, ultimate.cost) - LGS.cm:FireCallbacks(ON_ULTIMATE_CHANGED, unitTag, ultimate.current, ultimate.cost, ultimate.groupId, isSelf) -end - -local function NumCallbacks() - local registry = LGS.cm.callbackRegistry[ON_ULTIMATE_CHANGED] - handler.callbacks = registry and #registry or 0 -end - -function handler:RegisterForUltimateChanges(callback) - LGS.cm:RegisterCallback(ON_ULTIMATE_CHANGED, callback) - NumCallbacks() -end - -function handler:UnregisterForUltimateChanges(callback) - LGS.cm:UnregisterCallback(ON_ULTIMATE_CHANGED, callback) - NumCallbacks() -end - -local function GetPowerValues(unitResources, powerType) - local data = unitResources[powerType] - local current, maximum = GetUnitPower("player", powerType) - return data, current, data.cost -end - -function handler:Send() - if(not saveData.enabled or not IsUnitGrouped("player") or handler.callbacks == 0) then return end - local now = GetTimeStamp() - local timeout = IsUnitInCombat("player") and MIN_COMBAT_SEND_TIMEOUT or MIN_SEND_TIMEOUT - if(now - lastSendTime < timeout) then return end - - local unitResources = GetCachedUnitResources("player") - local ultimate, ultimateCurrent, ultimateMaximum = GetPowerValues(unitResources, POWERTYPE_ULTIMATE) - ultimateCurrent = zo_min(ultimateCurrent, ultimateMaximum) - - sendFullUpdate = sendFullUpdate or ultimate.cost ~= ultimateCost or ultimate.groupId ~= ultimateGroupId - if(ultimate.current ~= ultimateCurrent or sendFullUpdate) then - - local data = {} - local index, bitIndex = 1, 1 - index, bitIndex = LGS:WriteBit(data, index, bitIndex, sendFullUpdate) - index, bitIndex = LGS:WriteBit(data, index, bitIndex, needFullUpdate) - index = index + 1 - index = LGS:WriteUint8(data, index, ultimateCurrent) - if sendFullUpdate then - index = LGS:WriteUint8(data, index, ultimateCost) - index = LGS:WriteUint8(data, index, ultimateGroupId) - end - - -- Log("Send %d byte: is full: %s, needs full: %s, ultimate: %s, cost: %s", #data, tostring(sendFullUpdate), tostring(needFullUpdate), tostring(ultimateCurrent), tostring(ultimateCost)) - if(LGS:Send(type, data)) then - -- Log("Send Complete") - lastSendTime = now - ultimate.current = ultimateCurrent - if sendFullUpdate then - ultimate.cost = ultimateCost - ultimate.groupId = ultimateGroupId - end - sendFullUpdate = false - needFullUpdate = false - end - end -end - -function handler:Refresh() - sendFullUpdate = true - needFullUpdate = true -end - -local function OnUpdate() - handler:Send() -end - -local isActive = false - -local function StartSending() - if(not isActive and saveData.enabled and IsUnitGrouped("player")) then - EVENT_MANAGER:RegisterForUpdate("LibGroupSocketUltimateHandler", 1000, OnUpdate) - isActive = true - end -end - -local function StopSending() - if(isActive) then - EVENT_MANAGER:UnregisterForUpdate("LibGroupSocketUltimateHandler") - isActive = false - end -end - -local function OnUnitCreated(_, unitTag) - sendFullUpdate = true - StartSending() -end - -local function OnUnitDestroyed(_, unitTag) - resources[GetUnitName(unitTag)] = nil - if(isActive and not IsUnitGrouped("player")) then - StopSending() - end -end - -function handler:InitializeSettings(optionsData, IsSendingDisabled) -- TODO: localization - optionsData[#optionsData + 1] = { - type = "header", - name = "Ultimate Handler", - } -optionsData[#optionsData + 1] = { - type = "checkbox", - name = "Enable sending", - tooltip = "Controls if the handler does send data. It will still receive and process incoming data.", - getFunc = function() return saveData.enabled end, - setFunc = function(value) - saveData.enabled = value - if(value) then StartSending() else StopSending() end - end, - disabled = IsSendingDisabled, - default = defaultData.enabled -} -end - --- savedata becomes available twice in case the standalone lib is loaded -local function InitializeSaveData(data) - saveData = data - - if(not saveData.version) then - ZO_DeepTableCopy(defaultData, saveData) - end - - -- if(saveData.version == 1) then - -- -- update it - -- end -end - -local function Unload() - LGS.cm:UnregisterCallback(type, handler.dataHandler) - LGS.cm:UnregisterCallback("savedata-ready", InitializeSaveData) - EVENT_MANAGER:UnregisterForEvent("LibGroupSocketUltimateHandler", EVENT_UNIT_CREATED) - EVENT_MANAGER:UnregisterForEvent("LibGroupSocketUltimateHandler", EVENT_UNIT_DESTROYED) - StopSending() -end - -local function Load() - InitializeSaveData(saveData) - LGS.cm:RegisterCallback("savedata-ready", function(data) - InitializeSaveData(data.handlers[type]) - end) - - handler.dataHandler = OnData - LGS.cm:RegisterCallback(type, OnData) - EVENT_MANAGER:RegisterForEvent("LibGroupSocketUltimateHandler", EVENT_UNIT_CREATED, OnUnitCreated) - EVENT_MANAGER:AddFilterForEvent("LibGroupSocketUltimateHandler",EVENT_UNIT_CREATED, REGISTER_FILTER_UNIT_TAG_PREFIX, "group") - EVENT_MANAGER:RegisterForEvent("LibGroupSocketUltimateHandler", EVENT_UNIT_DESTROYED, OnUnitDestroyed) - EVENT_MANAGER:AddFilterForEvent("LibGroupSocketUltimateHandler",EVENT_UNIT_DESTROYED, REGISTER_FILTER_UNIT_TAG_PREFIX, "group") - handler.Unload = Unload - - StartSending() -end - -if(handler.Unload) then handler.Unload() end -Load() diff --git a/TaosGroupTools/i18n/de.lua b/TaosGroupTools/i18n/de.lua index d822e3b..2e628fd 100644 --- a/TaosGroupTools/i18n/de.lua +++ b/TaosGroupTools/i18n/de.lua @@ -2,14 +2,11 @@ -- Options local strings = { - TGU_WARNING_LGS_ENABLE = "Warnung: Aktiviere LibGroupSocket um zu senden -> /lgs 1", TGU_OPTIONS_HEADER = "Optionen", TGU_OPTIONS_DRAG_LABEL = "Elemente verschieben", TGU_OPTIONS_DRAG_TOOLTIP = "Wenn die Option aktiviert ist, können alle Elemente verschoben werden.", TGU_OPTIONS_ONLY_AVA_LABEL = "Nur im AvA Gebiet anzeigen", TGU_OPTIONS_ONLY_AVA_TOOLTIP = "Wenn die Option aktiviert ist, sind alle Elemente nur in Cyrodiil (AvA) sichtbar.", - TGU_OPTIONS_USE_LGS_LABEL = "Kommunikation via LibGroupSocket", - TGU_OPTIONS_USE_LGS_TOOLTIP = "Wenn die Option aktiviert ist, wird versucht eine Kommunikation via LibGroupSocket aufzubauen. LibGroupSocket muss dazu separat als eigenes Addon installiert sein.", TGU_OPTIONS_USE_SORTING_LABEL = "Listen nach Ulti-Fortschritt sortieren", TGU_OPTIONS_USE_SORTING_TOOLTIP = "Wenn die Option aktiviert ist, werden alle Listen nach Ulti-Fortschritt sortiert (Volle Ultis oben).", TGU_OPTIONS_STYLE_LABEL = "Style auswählen", diff --git a/TaosGroupTools/i18n/en.lua b/TaosGroupTools/i18n/en.lua index 572062a..501e9ae 100644 --- a/TaosGroupTools/i18n/en.lua +++ b/TaosGroupTools/i18n/en.lua @@ -2,14 +2,11 @@ -- Options local strings = { - TGU_WARNING_LGS_ENABLE = "Warning: Enable LibGroupSocket to send -> /lgs 1", TGU_OPTIONS_HEADER = "Options", TGU_OPTIONS_DRAG_LABEL = "Drag elements", TGU_OPTIONS_DRAG_TOOLTIP = "If activated, you can drag all elements.", TGU_OPTIONS_ONLY_AVA_LABEL = "Show only in AvA", TGU_OPTIONS_ONLY_AVA_TOOLTIP = "If activated, all elements will only be visible in Cyrodiil (AvA).", - TGU_OPTIONS_USE_LGS_LABEL = "Communication via LibGroupSocket", - TGU_OPTIONS_USE_LGS_TOOLTIP = "If activated, the addon will try to activate communication via LibGroupSocket. LibGroupSocket must be installed as own addon.", TGU_OPTIONS_USE_SORTING_LABEL = "Sort lists by ultimate progress", TGU_OPTIONS_USE_SORTING_TOOLTIP = "If activated, all lists will be sorted by ultimate progress (Maximum on top).", TGU_OPTIONS_STYLE_LABEL = "Choose style", diff --git a/TaosGroupTools/i18n/fr.lua b/TaosGroupTools/i18n/fr.lua index cf79590..46eab84 100644 --- a/TaosGroupTools/i18n/fr.lua +++ b/TaosGroupTools/i18n/fr.lua @@ -2,14 +2,11 @@ -- Options local strings = { - TGU_WARNING_LGS_ENABLE = "Warning: Enable LibGroupSocket to send -> /lgs 1", TGU_OPTIONS_HEADER = "Options", TGU_OPTIONS_DRAG_LABEL = "Drag elements", TGU_OPTIONS_DRAG_TOOLTIP = "If activated, you can drag all elements.", TGU_OPTIONS_ONLY_AVA_LABEL = "Show only in AvA", TGU_OPTIONS_ONLY_AVA_TOOLTIP = "If activated, all elements will only be visible in Cyrodiil (AvA).", - TGU_OPTIONS_USE_LGS_LABEL = "Communication via LibGroupSocket", - TGU_OPTIONS_USE_LGS_TOOLTIP = "If activated, the addon will try to activate communication via LibGroupSocket. LibGroupSocket must be installed as own addon.", TGU_OPTIONS_USE_SORTING_LABEL = "Sort lists by ultimate progress", TGU_OPTIONS_USE_SORTING_TOOLTIP = "If activated, all lists will be sorted by ultimate progress (Maximum on top).", TGU_OPTIONS_STYLE_LABEL = "Choose style", diff --git a/TaosGroupTools/libs/LibGroupSocket/LICENSE b/TaosGroupTools/libs/LibGroupSocket/LICENSE deleted file mode 100644 index 12b3fde..0000000 --- a/TaosGroupTools/libs/LibGroupSocket/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - The Artistic License 2.0 - - Copyright (c) 2016 sirinsidiator - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -Preamble - -This license establishes the terms under which a given free software -Package may be copied, modified, distributed, and/or redistributed. -The intent is that the Copyright Holder maintains some artistic -control over the development of that Package while still keeping the -Package available as open source and free software. - -You are always permitted to make arrangements wholly outside of this -license directly with the Copyright Holder of a given Package. If the -terms of this license do not permit the full use that you propose to -make of the Package, you should contact the Copyright Holder and seek -a different licensing arrangement. - -Definitions - - "Copyright Holder" means the individual(s) or organization(s) - named in the copyright notice for the entire Package. - - "Contributor" means any party that has contributed code or other - material to the Package, in accordance with the Copyright Holder's - procedures. - - "You" and "your" means any person who would like to copy, - distribute, or modify the Package. - - "Package" means the collection of files distributed by the - Copyright Holder, and derivatives of that collection and/or of - those files. A given Package may consist of either the Standard - Version, or a Modified Version. - - "Distribute" means providing a copy of the Package or making it - accessible to anyone else, or in the case of a company or - organization, to others outside of your company or organization. - - "Distributor Fee" means any fee that you charge for Distributing - this Package or providing support for this Package to another - party. It does not mean licensing fees. - - "Standard Version" refers to the Package if it has not been - modified, or has been modified only in ways explicitly requested - by the Copyright Holder. - - "Modified Version" means the Package, if it has been changed, and - such changes were not explicitly requested by the Copyright - Holder. - - "Original License" means this Artistic License as Distributed with - the Standard Version of the Package, in its current version or as - it may be modified by The Perl Foundation in the future. - - "Source" form means the source code, documentation source, and - configuration files for the Package. - - "Compiled" form means the compiled bytecode, object code, binary, - or any other form resulting from mechanical transformation or - translation of the Source form. - - -Permission for Use and Modification Without Distribution - -(1) You are permitted to use the Standard Version and create and use -Modified Versions for any purpose without restriction, provided that -you do not Distribute the Modified Version. - - -Permissions for Redistribution of the Standard Version - -(2) You may Distribute verbatim copies of the Source form of the -Standard Version of this Package in any medium without restriction, -either gratis or for a Distributor Fee, provided that you duplicate -all of the original copyright notices and associated disclaimers. At -your discretion, such verbatim copies may or may not include a -Compiled form of the Package. - -(3) You may apply any bug fixes, portability changes, and other -modifications made available from the Copyright Holder. The resulting -Package will still be considered the Standard Version, and as such -will be subject to the Original License. - - -Distribution of Modified Versions of the Package as Source - -(4) You may Distribute your Modified Version as Source (either gratis -or for a Distributor Fee, and with or without a Compiled form of the -Modified Version) provided that you clearly document how it differs -from the Standard Version, including, but not limited to, documenting -any non-standard features, executables, or modules, and provided that -you do at least ONE of the following: - - (a) make the Modified Version available to the Copyright Holder - of the Standard Version, under the Original License, so that the - Copyright Holder may include your modifications in the Standard - Version. - - (b) ensure that installation of your Modified Version does not - prevent the user installing or running the Standard Version. In - addition, the Modified Version must bear a name that is different - from the name of the Standard Version. - - (c) allow anyone who receives a copy of the Modified Version to - make the Source form of the Modified Version available to others - under - - (i) the Original License or - - (ii) a license that permits the licensee to freely copy, - modify and redistribute the Modified Version using the same - licensing terms that apply to the copy that the licensee - received, and requires that the Source form of the Modified - Version, and of any works derived from it, be made freely - available in that license fees are prohibited but Distributor - Fees are allowed. - - -Distribution of Compiled Forms of the Standard Version -or Modified Versions without the Source - -(5) You may Distribute Compiled forms of the Standard Version without -the Source, provided that you include complete instructions on how to -get the Source of the Standard Version. Such instructions must be -valid at the time of your distribution. If these instructions, at any -time while you are carrying out such distribution, become invalid, you -must provide new instructions on demand or cease further distribution. -If you provide valid instructions or cease distribution within thirty -days after you become aware that the instructions are invalid, then -you do not forfeit any of your rights under this license. - -(6) You may Distribute a Modified Version in Compiled form without -the Source, provided that you comply with Section 4 with respect to -the Source of the Modified Version. - - -Aggregating or Linking the Package - -(7) You may aggregate the Package (either the Standard Version or -Modified Version) with other packages and Distribute the resulting -aggregation provided that you do not charge a licensing fee for the -Package. Distributor Fees are permitted, and licensing fees for other -components in the aggregation are permitted. The terms of this license -apply to the use and Distribution of the Standard or Modified Versions -as included in the aggregation. - -(8) You are permitted to link Modified and Standard Versions with -other works, to embed the Package in a larger work of your own, or to -build stand-alone binary or bytecode versions of applications that -include the Package, and Distribute the result without restriction, -provided the result does not expose a direct interface to the Package. - - -Items That are Not Considered Part of a Modified Version - -(9) Works (including, but not limited to, modules and scripts) that -merely extend or make use of the Package, do not, by themselves, cause -the Package to be a Modified Version. In addition, such works are not -considered parts of the Package itself, and are not subject to the -terms of this license. - - -General Provisions - -(10) Any use, modification, and distribution of the Standard or -Modified Versions is governed by this Artistic License. By using, -modifying or distributing the Package, you accept this license. Do not -use, modify, or distribute the Package, if you do not accept this -license. - -(11) If your Modified Version has been derived from a Modified -Version made by someone other than you, you are nevertheless required -to ensure that your Modified Version complies with the requirements of -this license. - -(12) This license does not grant you the right to use any trademark, -service mark, tradename, or logo of the Copyright Holder. - -(13) This license includes the non-exclusive, worldwide, -free-of-charge patent license to make, have made, use, offer to sell, -sell, import and otherwise transfer the Package with respect to any -patent claims licensable by the Copyright Holder that are necessarily -infringed by the Package. If you institute patent litigation -(including a cross-claim or counterclaim) against any party alleging -that the Package constitutes direct or contributory patent -infringement, then this Artistic License to you shall terminate on the -date that such litigation is filed. - -(14) Disclaimer of Warranty: -THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS -IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL -LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/TaosGroupTools/libs/LibGroupSocket/LibGroupSocket.lua b/TaosGroupTools/libs/LibGroupSocket/LibGroupSocket.lua deleted file mode 100644 index 9f486bc..0000000 --- a/TaosGroupTools/libs/LibGroupSocket/LibGroupSocket.lua +++ /dev/null @@ -1,658 +0,0 @@ -local LIB_IDENTIFIER = "LibGroupSocket" -local lib = LibStub:NewLibrary(LIB_IDENTIFIER, 2) - -if not lib then - return -- already loaded and no upgrade necessary -end - -local LMP = LibStub("LibMapPing", true) -if(not LMP) then - error(string.format("[%s] Cannot load without LibMapPing", LIB_IDENTIFIER)) -end - -local LGPS = LibStub("LibGPS2", true) -if(not LGPS) then - error(string.format("[%s] Cannot load without LibGPS2", LIB_IDENTIFIER)) -end - -local function Log(message, ...) - df("[%s] %s", LIB_IDENTIFIER, message:format(...)) -end -lib.Log = Log - ---/script PingMap(89, 1, 1 / 2^16, 1 / 2^16) StartChatInput(table.concat({GetMapPlayerWaypoint()}, ",")) --- smallest step is around 1.428571431461e-005 for Wrothgar, so there should be 70000 steps --- Coldharbour has a similar step size, meaning we can send 4 bytes of data per ping on both -local WROTHGAR_MAP_INDEX = 27 -local COLDHARBOUR_MAP_INDEX = 23 -local MAP_METRICS = { - [WROTHGAR_MAP_INDEX] = { zoneIndex = GetZoneIndex(684), stepSize = 1.428571431461e-005 }, - [COLDHARBOUR_MAP_INDEX] = { zoneIndex = GetZoneIndex(347), stepSize = 1.4285034012573e-005 }, -} -local NO_UPDATE = true - ---lib.debug = true -- TODO -lib.cm = lib.cm or ZO_CallbackObject:New() -lib.outgoing = lib.outgoing or {} -lib.incoming = lib.incoming or {} -lib.handlers = lib.handlers or {} -local handlers = lib.handlers -local suppressedList = {} -local panel, button, entry - -function lib:GetMapIndexForUnit(unitTag) - if(MAP_METRICS[WROTHGAR_MAP_INDEX].zoneIndex == GetUnitZoneIndex(unitTag)) then - return COLDHARBOUR_MAP_INDEX - else - return WROTHGAR_MAP_INDEX - end -end - -function lib:GetStepSizeForUnit(unitTag) - return MAP_METRICS[lib:GetMapIndexForUnit(unitTag)].stepSize -end - -------------------------------------------------------- Settings ------------------------------------------------------ - -local defaultData = { - version = 1, - enabled = false, - autoDisableOnGroupLeft = true, - autoDisableOnSessionStart = true, - handlers = {}, -} - --- saved variables are not ready yet so we just use the defaults, the real saved variables will be loaded later in case the standalone lib is active -local saveData = ZO_DeepTableCopy(defaultData) - -local function RefreshSettingsPanel() - if(not panel) then return end - CALLBACK_MANAGER:FireCallbacks("LAM-RefreshPanel", panel) -end - -local function RefreshGroupMenuKeyboard() - if(not button) then return end - ZO_CheckButton_SetCheckState(button, saveData.enabled) -end - -local function RefreshGroupMenuGamepad(noUpdate) - if(not entry) then return end - entry:SetText(saveData.enabled and "Disable sending" or "Enable sending") - if(not noUpdate) then - GAMEPAD_GROUP_MENU:UpdateMenuList() - end -end - -local function InitializeGroupMenu() - if(not ZO_GroupMenu_Keyboard) then return end - -- keyboard - button = CreateControlFromVirtual("$(parent)_LibGroupSocketToggle", ZO_GroupMenu_Keyboard, "ZO_CheckButton_Text") - ZO_CheckButton_SetLabelText(button, "LibGroupSocket Sending:") - ZO_CheckButton_SetCheckState(button, saveData.enabled) - ZO_CheckButton_SetToggleFunction(button, function(control, checked) - if(checked ~= saveData.enabled) then - saveData.enabled = checked - RefreshSettingsPanel() - RefreshGroupMenuGamepad() - end - end) - button.label:ClearAnchors() - button.label:SetAnchor(TOPLEFT, ZO_GroupMenu_Keyboard, TOPLEFT, 10, 30) - button:SetAnchor(LEFT, button.label, RIGHT, -40, 0) - - -- gamepad - local menu = GAMEPAD_GROUP_MENU - local MENU_ENTRY_TYPE_LGS_TOGGLE = #menu.menuEntries + 1 - entry = ZO_GamepadEntryData:New("") - RefreshGroupMenuGamepad(NO_UPDATE) - entry.type = MENU_ENTRY_TYPE_LGS_TOGGLE - entry:SetHeader("LibGroupSocket") - menu.menuEntries[MENU_ENTRY_TYPE_LGS_TOGGLE] = entry - - local list = GAMEPAD_GROUP_MENU:GetMainList() - local originalCommit = list.Commit - list.Commit = function(self, ...) - list:AddEntryWithHeader("ZO_GamepadMenuEntryTemplate", entry) - originalCommit(self, ...) - end - - local InitializeKeybindDescriptors = menu.InitializeKeybindDescriptors - menu.InitializeKeybindDescriptors = function(self) - InitializeKeybindDescriptors(self) - - local primary = menu.keybindStripDescriptor[1] - local callback = primary.callback - primary.callback = function() - callback() - local type = list:GetTargetData().type - if type == MENU_ENTRY_TYPE_LGS_TOGGLE then - PlaySound(SOUNDS.DEFAULT_CLICK) - saveData.enabled = not saveData.enabled - RefreshSettingsPanel() - RefreshGroupMenuKeyboard() - RefreshGroupMenuGamepad() - end - end - end -end - -local function InitializeSettingsPanel() -- TODO: localization - local LAM = LibStub("LibAddonMenu-2.0", true) - if(LAM) then -- if LAM is not available, it is not the stand alone version of LGS. As we can't save anything in that case, we don't bother enforcing a dependency. - local function IsSendingDisabled() return not saveData.enabled end - - local panelData = { - type = "panel", - name = "LibGroupSocket", - author = "sirinsidiator", - version = "2", - website = "http://www.esoui.com/downloads/info1337-LibGroupSocket.html", - registerForRefresh = true, - registerForDefaults = true - } - panel = LAM:RegisterAddonPanel("LibGroupSocketOptions", panelData) - - local optionsData = {} --- if(not lib.standalone) then -- the stand alone version contains a file that sets standalone = true --- optionsData[#optionsData + 1] = { --- type = "description", --- text = "No stand alone installation detected. Settings won't be saved.", --- reference = "LibGroupSocketStandAloneWarning" --- } --- end - - optionsData[#optionsData + 1] = { - type = "header", - name = "General", - } - optionsData[#optionsData + 1] = { - type = "checkbox", - name = "Enable Sending", - tooltip = "Controls if the library sends any data. It will still receive and process data.", - getFunc = function() return saveData.enabled end, - setFunc = function(value) - saveData.enabled = value - RefreshGroupMenuKeyboard() - RefreshGroupMenuGamepad() - end, - default = defaultData.enabled - } - optionsData[#optionsData + 1] = { - type = "checkbox", - name = "Disable On Group Left", - tooltip = "Automatically disables sending when you leave a group in order to prevent accidentally sending data to a new group.", - getFunc = function() return saveData.autoDisableOnGroupLeft end, - setFunc = function(value) saveData.autoDisableOnGroupLeft = value end, - default = defaultData.enabled - } - optionsData[#optionsData + 1] = { - type = "checkbox", - name = "Disable On Session Start", - tooltip = "Automatically disables sending when you start the game in order to prevent accidentally sending data to an existing group.", - getFunc = function() return saveData.autoDisableOnSessionStart end, - setFunc = function(value) saveData.autoDisableOnSessionStart = value end, - default = defaultData.enabled - } - - for handlerType, handler in pairs(handlers) do - if(handler.InitializeSettings) then - handler:InitializeSettings(optionsData, IsSendingDisabled) - end - end - LAM:RegisterOptionControls("LibGroupSocketOptions", optionsData) - end -end - -------------------------------------------------- OutgoingPacket Class ------------------------------------------------ - -local OutgoingPacket = ZO_Object:Subclass() - -function OutgoingPacket:New(messageType, data) - local object = ZO_Object.New(self) - object.messageType = messageType - object.header = lib:EncodeHeader(messageType, #data) - object.data = data - object.index = 0 - return object -end - -function OutgoingPacket:GetNext() - local next - if(self.index < 1) then - next = self.header - else - next = self.data[self.index] or 0 - end - self.index = self.index + 1 - return next -end - -function OutgoingPacket:GetNextCoordinates() - local stepSize = lib:GetStepSizeForUnit("player") - return lib:EncodeData(self:GetNext(), self:GetNext(), self:GetNext(), self:GetNext(), stepSize) -end - -function OutgoingPacket:HasMore() - return self.index <= #self.data -end - -------------------------------------------------- IncomingPacket Class ------------------------------------------------ - -local IncomingPacket = ZO_Object:Subclass() - -function IncomingPacket:New(unitTag) - local object = ZO_Object.New(self) - object.messageType = -1 - object.data = {} - object.length = 0 - object.stepSize = lib:GetStepSizeForUnit(unitTag) - return object -end - -function IncomingPacket:AddCoordinates(x, y) - local b0, b1, b2, b3 = lib:DecodeData(x, y, self.stepSize) - local data = self.data - if(self.messageType < 0) then - self.messageType, self.length = lib:DecodeHeader(b0) - else - data[#data + 1] = b0 - end - if(#data < self.length) then data[#data + 1] = b1 end - if(#data < self.length) then data[#data + 1] = b2 end - if(#data < self.length) then data[#data + 1] = b3 end -end - -function IncomingPacket:IsComplete() - return self.length > 0 and #self.data >= self.length -end - -local function IsValidMessageType(messageType) - return not (messageType < 0 or messageType > 31) -end - -function IncomingPacket:HasValidHeader() - return IsValidMessageType(self.messageType) and self.length > 0 and self.length < 8 -end - -function IncomingPacket:IsValid() - return self:HasValidHeader() and #self.data == self.length -end - ---------------------------------------------- Byte Manipulation Utilities --------------------------------------------- - ---- Reads a bit from the data stream and increments the index and bit index accordingly ---- 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 -function lib:ReadBit(data, index, bitIndex) - local p = 2 ^ (bitIndex - 1) - local isSet = (data[index] % (p + p) >= p) - local nextIndex = (bitIndex >= 8 and index + 1 or index) - local nextBitIndex = (bitIndex >= 8 and 1 or bitIndex + 1) - return isSet, nextIndex, nextBitIndex -end - ---- Writes a bit to the data stream and increments the index and bit index accordingly ---- 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 -function lib:WriteBit(data, index, bitIndex, value) - local p = 2 ^ (bitIndex - 1) - local oldValue = data[index] or 0 - local isSet = (oldValue % (p + p) >= p) - if(isSet and not value) then - oldValue = oldValue - p - elseif(not isSet and value) then - oldValue = oldValue + p - end - data[index] = oldValue - local nextIndex = (bitIndex >= 8 and index + 1 or index) - local nextBitIndex = (bitIndex >= 8 and 1 or bitIndex + 1) - return nextIndex, nextBitIndex -end - ---- Reads a single byte from the data stream, converts it into a string character and increments the index accordingly ---- 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 -function lib:ReadChar(data, index) - return string.char(data[index]), index + 1 -end - ---- Writes a single character to the data stream and increments the index accordingly ---- 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 -function lib:WriteChar(data, index, value, charIndex) - data[index] = value:byte(charIndex) - return index + 1 -end - ---- Reads a single byte from the data stream and increments the index accordingly ---- 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 -function lib:ReadUint8(data, index) - return data[index], index + 1 -end - ---- 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. ---- 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 -function lib:WriteUint8(data, index, value) - data[index] = math.min(0xff, math.max(0x00, math.floor(value))) - return index + 1 -end - ---- Reads two byte from the data stream, converts them to one integer and increments the index accordingly ---- 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 -function lib:ReadUint16(data, index) - return (data[index] * 0x100 + data[index + 1]), index + 2 -end - ---- 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. ---- 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 -function lib:WriteUint16(data, index, value) - value = math.min(0xffff, math.max(0x0000, math.floor(value))) - data[index] = math.floor(value / 0x100) - data[index + 1] = value % 0x100 - return index + 2 -end - ---- Converts 4 bytes of data into coordinates for a map ping ---- 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 -function lib:EncodeData(b0, b1, b2, b3, stepSize) - b0 = b0 or 0 - b1 = b1 or 0 - b2 = b2 or 0 - b3 = b3 or 0 - return (b0 * 0x100 + b1) * stepSize, (b2 * 0x100 + b3) * stepSize -end - ---- Converts normalized map ping coordinates into 4 bytes of data ---- step size specifies the smallest possible increment for the coordinates on a map ---- returns 4 integers between 0 and 255 -function lib:DecodeData(x, y, stepSize) - x = math.floor(x / stepSize + 0.5) -- round to next integer - y = math.floor(y / stepSize + 0.5) - local b0 = math.floor(x / 0x100) - local b1 = x % 0x100 - local b2 = math.floor(y / 0x100) - local b3 = y % 0x100 - return b0, b1, b2, b3 -end - ---- Packs a 5-bit messageType and a 3-bit length value into one byte of data ---- messageType - integer between 0 and 31 ---- length - integer between 0 and 7 ---- returns encoded header byte -function lib:EncodeHeader(messageType, length) - return messageType * 0x08 + length -end - ---- Unpacks a 5-bit messageType and a 3-bit length value from one byte of data ---- value - integer between 0 and 255 ---- returns messageType and length -function lib:DecodeHeader(value) - local messageType = math.floor(value / 0x08) - local length = value % 0x08 - return messageType, length -end - ---------------------------------------------------- Data Processing --------------------------------------------------- - -local function SetMapPingOnCommonMap(x, y) - local pingType = MAP_PIN_TYPE_PING - if(lib.debug and not IsUnitGrouped("player")) then - pingType = MAP_PIN_TYPE_PLAYER_WAYPOINT - end - LGPS:PushCurrentMap() - SetMapToMapListIndex(lib:GetMapIndexForUnit("player")) - LMP:SetMapPing(pingType, MAP_TYPE_LOCATION_CENTERED, x, y) - LGPS:PopCurrentMap() -end - -local function GetMapPingOnCommonMap(pingType, pingTag) - LGPS:PushCurrentMap() - SetMapToMapListIndex(lib:GetMapIndexForUnit(pingTag)) - local x, y = LMP:GetMapPing(pingType, pingTag) - LGPS:PopCurrentMap() - return x, y -end - -local function DoSend(isFirst) - local packet = lib.outgoing[1] - if(not packet) then Log("Tried to send when no data in queue") return end - lib.isSending = true - - local x, y = packet:GetNextCoordinates() - SetMapPingOnCommonMap(x, y) - - lib.hasMore = packet:HasMore() - if(not lib.hasMore) then - table.remove(lib.outgoing, 1) - lib.hasMore = (#lib.outgoing > 0) - end -end - -local function IsValidData(data) - if(#data > 7) then - Log("Tried to send %d of 7 allowed bytes", #data) - return false - end - for i = 1, #data do - local value = data[i] - if(type(value) ~= "number" or value < 0 or value > 255) then - Log("Invalid value '%s' at position %d in byte data", tostring(value), i) - return false - end - end - return true -end - ---- Queues up to seven byte of data of the selected messageType for broadcasting to all group members ---- 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. -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 - -local function HandleDataPing(pingType, pingTag, x, y, isPingOwner) - x, y = GetMapPingOnCommonMap(pingType, pingTag) - if(not LMP:IsPositionOnMap(x, y)) then return false end - if(not lib.incoming[pingTag]) then - lib.incoming[pingTag] = IncomingPacket:New(pingTag) - end - local packet = lib.incoming[pingTag] - packet:AddCoordinates(x, y) - if(not packet:HasValidHeader()) then -- it might be a user set ping - lib.incoming[pingTag] = nil - return false - end - if(packet:IsComplete()) then - lib.incoming[pingTag] = nil - if(packet:IsValid()) then - lib.cm:FireCallbacks(packet.messageType, pingTag, packet.data, isPingOwner) - else - lib.incoming[pingTag] = nil - Log("received invalid packet from %s", GetUnitName(pingTag)) - return false - end - end - if(isPingOwner) then - if(lib.hasMore) then - DoSend() - else - lib.isSending = false - end - end - return true -end - --------------------------------------------------- Map Ping Handling -------------------------------------------------- -local function GetKey(pingType, pingTag) - return string.format("%d_%s", pingType, pingTag) -end - -local function SuppressPing(pingType, pingTag) - local key = GetKey(pingType, pingTag) - if(not suppressedList[key]) then - LMP:SuppressPing(pingType, pingTag) - suppressedList[key] = true - end -end - -local function UnsuppressPing(pingType, pingTag) - local key = GetKey(pingType, pingTag) - if(suppressedList[key]) then - LMP:UnsuppressPing(pingType, pingTag) - suppressedList[key] = false - end -end - -LMP:RegisterCallback("BeforePingAdded", function(pingType, pingTag, x, y, isPingOwner) - if(pingType == MAP_PIN_TYPE_PING or (lib.debug and not IsUnitGrouped("player") and pingType == MAP_PIN_TYPE_PLAYER_WAYPOINT)) then - if(HandleDataPing(pingType, pingTag, x, y, isPingOwner)) then -- it is a valid data ping - SuppressPing(pingType, pingTag) - else -- ping is set by player - UnsuppressPing(pingType, pingTag) - end - end -end) - -LMP:RegisterCallback("AfterPingRemoved", function(pingType, pingTag, x, y, isPingOwner) - UnsuppressPing(pingType, pingTag) -end) - ----------------------------------------------------- Data Handlers ---------------------------------------------------- - -lib.MESSAGE_TYPE_RESERVED = 0 --- reserved in case we ever have more than 31 message types. can also be used for local tests -lib.MESSAGE_TYPE_RESOURCES = 1 --- for exchanging stamina and magicka values -lib.MESSAGE_TYPE_COMBATSTATS = 2 --- for combat stats like heal, damage and time in combat - ---- 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. ---- 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 -function lib:RegisterHandler(messageType, handlerVersion) - if handlers[messageType] and handlers[messageType].version >= handlerVersion then - return false - else - handlers[messageType] = handlers[messageType] or {} - handlers[messageType].version = handlerVersion - saveData.handlers[messageType] = saveData.handlers[messageType] or {} - return handlers[messageType], saveData.handlers[messageType] - end -end - ---- Gives access to an already registered handler for addons. ---- messageType - The messageType of the handler ---- returns the handler object -function lib:GetHandler(messageType) - return handlers[messageType] -end - ---------------------------------------------------------- Misc -------------------------------------------------------- - ---- Register for unprocessed data of a messageType -function lib:RegisterCallback(messageType, callback) - self.cm:RegisterCallback(messageType, callback) -end - ---- Unregister for unprocessed data of a messageType -function lib:UnregisterCallback(messageType, callback) - self.cm:UnregisterCallback(messageType, callback) -end - ----------------------------------------------------- Initialization --------------------------------------------------- - -local function Unload() - EVENT_MANAGER:UnregisterForEvent(LIB_IDENTIFIER, EVENT_PLAYER_ACTIVATED) - EVENT_MANAGER:UnregisterForEvent(LIB_IDENTIFIER, EVENT_UNIT_DESTROYED) - EVENT_MANAGER:UnregisterForEvent(LIB_IDENTIFIER, EVENT_ADD_ON_LOADED) - SLASH_COMMANDS["/lgs"] = nil -end - -local function Load() - EVENT_MANAGER:RegisterForEvent(LIB_IDENTIFIER, EVENT_UNIT_DESTROYED, function() - if(saveData.autoDisableOnGroupLeft and not IsUnitGrouped("player")) then - saveData.enabled = false - RefreshSettingsPanel() - RefreshGroupMenuKeyboard() - RefreshGroupMenuGamepad() - end - end) - - -- saved variables only become available when EVENT_ADD_ON_LOADED is fired for the library - EVENT_MANAGER:RegisterForEvent(LIB_IDENTIFIER, EVENT_ADD_ON_LOADED, function(_ ,addonName) - if(addonName == LIB_IDENTIFIER) then - LibGroupSocket_Data = LibGroupSocket_Data or {} - saveData = LibGroupSocket_Data[GetDisplayName()] or ZO_DeepTableCopy(defaultData) - LibGroupSocket_Data[GetDisplayName()] = saveData - - --if(saveData.version == 1) then - -- saveData.setting = defaultData.setting - -- saveData.version = 2 - --end - - for messageType in pairs(handlers) do - saveData.handlers[messageType] = saveData.handlers[messageType] or {} - end - - lib.cm:FireCallbacks("savedata-ready", saveData) - end - end) - - -- don't initialize the settings menu before we can be sure that it is the newest version of the lib - EVENT_MANAGER:RegisterForEvent(LIB_IDENTIFIER, EVENT_PLAYER_ACTIVATED, function(_, initial) - EVENT_MANAGER:UnregisterForEvent(LIB_IDENTIFIER, EVENT_PLAYER_ACTIVATED) - if(saveData.autoDisableOnSessionStart and initial) then - saveData.enabled = false -- don't need to refresh the settings or group menu here, because they are not initialized yet - end - - InitializeSettingsPanel() - InitializeGroupMenu() - end) - - SLASH_COMMANDS["/lgs"] = function(value) - saveData.enabled = (value == "1") - Log("Data sending %s", saveData.enabled and "enabled" or "disabled") - RefreshSettingsPanel() - RefreshGroupMenuKeyboard() - RefreshGroupMenuGamepad() - end - - lib.Unload = Unload -end - -if(lib.Unload) then lib.Unload() end -Load() diff --git a/TaosGroupTools/libs/LibGroupSocket/handlers/ResourceHandler.lua b/TaosGroupTools/libs/LibGroupSocket/handlers/ResourceHandler.lua deleted file mode 100644 index c6f6dad..0000000 --- a/TaosGroupTools/libs/LibGroupSocket/handlers/ResourceHandler.lua +++ /dev/null @@ -1,277 +0,0 @@ --- The Group Resource Protocol --- *bitArray* flags, *uint8* magicka percentage, *uint8* stamina percentage[, *uint16* magicka maximum, *uint16* stamina maximum] --- flags: --- 1: isFullUpdate - the user is sending max values in addition to percentages in this packet --- 2: requestsFullUpdate - the user does not have all the necessary data and wants to have a full update from everyone (e.g. after reloading the ui) --- 3: sharesPercentagesOnly - the user does not want to share maximum values --- 4: largeMagickaPool - the user has more than 2^16 magicka, so the value has been divided by 2; around 100k magicka seems to be the most that is possible right now --- 5: largeStaminaPool - the user has more than 2^16 stamina, so the value has been divided by 2 - -local LGS = LibStub("LibGroupSocket") -local type, version = LGS.MESSAGE_TYPE_RESOURCES, 2 -local handler, saveData = LGS:RegisterHandler(type, version) -if(not handler) then return end -local SKIP_CREATE = true -local ON_RESOURCES_CHANGED = "OnResourcesChanged" -local MIN_SEND_TIMEOUT = 2 -local MIN_COMBAT_SEND_TIMEOUT = 1 -local Log = LGS.Log - -handler.resources = {} -local resources = handler.resources -local sendFullUpdate = true -local needFullUpdate = true -local lastSendTime = 0 -local defaultData = { - version = 1, - enabled = true, - percentOnly = true, -} - -local function GetCachedUnitResources(unitTag, skipCreate) - local unitName = GetUnitName(unitTag) - local unitResources = resources[unitName] - if(not unitResources and not skipCreate) then - resources[unitName] = { - [POWERTYPE_MAGICKA] = { current = 1000, maximum = 1000, percent = 255 }, - [POWERTYPE_STAMINA] = { current = 1000, maximum = 1000, percent = 255 }, - percentageOnly = true, - hasFullData = false, - lastUpdate = 0, - } - unitResources = resources[unitName] - end - return unitResources -end - -function handler:GetLastUpdateTime(unitTag) - local unitResources = GetCachedUnitResources(unitTag, SKIP_CREATE) - if(unitResources) then return unitResources.lastUpdate end - return -1 -end - -local function OnData(unitTag, data, isSelf) - local index, bitIndex = 1, 1 - local isFullUpdate, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - local requestsFullUpdate, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - local sharesPercentagesOnly, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - local largeMagickaPool, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - local largeStaminaPool, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - local hasMoreStamina, index, bitIndex = LGS:ReadBit(data, index, bitIndex) - -- Log("OnData %s (%d byte): is full: %s, needs full: %s, percent only: %s", GetUnitName(unitTag), #data, tostring(isFullUpdate), tostring(requestsFullUpdate), tostring(sharesPercentagesOnly)) - index = index + 1 - if(not isSelf and requestsFullUpdate) then - sendFullUpdate = true - end - - local expectedLength = isFullUpdate and 7 or 3 - if(#data < expectedLength) then Log("ResourceHandler received only %d of %d byte", #data, expectedLength) return end - - local unitResources = GetCachedUnitResources(unitTag) - local magicka = unitResources[POWERTYPE_MAGICKA] - local stamina = unitResources[POWERTYPE_STAMINA] - - unitResources.percentageOnly = sharesPercentagesOnly - - magicka.percent, index = LGS:ReadUint8(data, index) - stamina.percent, index = LGS:ReadUint8(data, index) - - if(sharesPercentagesOnly) then - magicka.maximum = 1000 - stamina.maximum = 1000 - if(hasMoreStamina) then - stamina.maximum = stamina.maximum * 2 - else - magicka.maximum = magicka.maximum * 2 - end - unitResources.hasFullData = false - elseif(isFullUpdate) then - magicka.maximum, index = LGS:ReadUint16(data, index) - if(largeMagickaPool) then magicka.maximum = magicka.maximum * 2 end - stamina.maximum, index = LGS:ReadUint16(data, index) - if(largeStaminaPool) then stamina.maximum = stamina.maximum * 2 end - unitResources.hasFullData = true - elseif(not unitResources.hasFullData and not isSelf) then - needFullUpdate = true - end - - magicka.current = math.floor((magicka.percent / 255) * magicka.maximum) - stamina.current = math.floor((stamina.percent / 255) * stamina.maximum) - - unitResources.lastUpdate = GetTimeStamp() - - -- Log("magicka: %d/%d stamina: %d/%d", magicka.current, magicka.maximum, stamina.current, stamina.maximum) - LGS.cm:FireCallbacks(ON_RESOURCES_CHANGED, unitTag, magicka.current, magicka.maximum, stamina.current, stamina.maximum, isSelf) -end - -function handler:RegisterForResourcesChanges(callback) - LGS.cm:RegisterCallback(ON_RESOURCES_CHANGED, callback) -end - -function handler:UnregisterForResourcesChanges(callback) - LGS.cm:UnregisterCallback(ON_RESOURCES_CHANGED, callback) -end - -local function GetPowerValues(unitResources, powerType) - local data = unitResources[powerType] - local current, maximum = GetUnitPower("player", powerType) - local percent = math.floor(current / maximum * 255) - return data, current, maximum, percent -end - -function handler:Send() - if(not saveData.enabled or not IsUnitGrouped("player")) then return end - local now = GetTimeStamp() - local timeout = IsUnitInCombat("player") and MIN_COMBAT_SEND_TIMEOUT or MIN_SEND_TIMEOUT - if(now - lastSendTime < timeout) then return end - - local unitResources = GetCachedUnitResources("player") - local magicka, magickaCurrent, magickaMaximum, magickaPercent = GetPowerValues(unitResources, POWERTYPE_MAGICKA) - local stamina, staminaCurrent, staminaMaximum, staminaPercent = GetPowerValues(unitResources, POWERTYPE_STAMINA) - - local percentOnly = saveData.percentOnly - sendFullUpdate = sendFullUpdate or (not percentOnly and (magicka.maximum ~= magickaMaximum or stamina.maximum ~= staminaMaximum)) - if(magicka.percent ~= magickaPercent or stamina.percent ~= staminaPercent or sendFullUpdate or needFullUpdate) then - local largeMagickaPool = (magickaMaximum >= 2^16) - local largeStaminaPool = (staminaMaximum >= 2^16) - local hasMoreStamina = staminaMaximum > magickaMaximum - - local data = {} - local index, bitIndex = 1, 1 - index, bitIndex = LGS:WriteBit(data, index, bitIndex, (sendFullUpdate and not percentOnly)) - index, bitIndex = LGS:WriteBit(data, index, bitIndex, needFullUpdate) - index, bitIndex = LGS:WriteBit(data, index, bitIndex, percentOnly) - if(sendFullUpdate and not percentOnly) then - index, bitIndex = LGS:WriteBit(data, index, bitIndex, largeMagickaPool) - index, bitIndex = LGS:WriteBit(data, index, bitIndex, largeStaminaPool) - else - index, bitIndex = LGS:WriteBit(data, index, bitIndex, false) - index, bitIndex = LGS:WriteBit(data, index, bitIndex, false) - end - index, bitIndex = LGS:WriteBit(data, index, bitIndex, hasMoreStamina) - index = index + 1 - index = LGS:WriteUint8(data, index, magickaPercent) - index = LGS:WriteUint8(data, index, staminaPercent) - if(sendFullUpdate and not percentOnly) then - if(largeMagickaPool) then magickaMaximum = math.floor(magickaMaximum / 2) end - index = LGS:WriteUint16(data, index, magickaMaximum) - - if(largeStaminaPool) then staminaMaximum = math.floor(staminaMaximum / 2) end - index = LGS:WriteUint16(data, index, staminaMaximum) - end - - -- Log("Send %d byte: is full: %s, needs full: %s, percent only: %s", #data, tostring(sendFullUpdate), tostring(needFullUpdate), tostring(percentOnly)) - if(LGS:Send(type, data)) then - lastSendTime = now - magicka.percent = magickaPercent - stamina.percent = staminaPercent - if(sendFullUpdate and not percentOnly) then - if(largeMagickaPool) then magicka.maximum = magicka.maximum * 2 end - magicka.maximum = magickaMaximum - if(largeStaminaPool) then stamina.maximum = stamina.maximum * 2 end - stamina.maximum = staminaMaximum - end - sendFullUpdate = false - needFullUpdate = false - end - end -end - -local function OnUpdate() - handler:Send() -end - -local isActive = false - -local function StartSending() - if(not isActive and saveData.enabled and IsUnitGrouped("player")) then - EVENT_MANAGER:RegisterForUpdate("LibGroupSocketResourceHandler", 1000, OnUpdate) - isActive = true - end -end - -local function StopSending() - if(isActive) then - EVENT_MANAGER:UnregisterForUpdate("LibGroupSocketResourceHandler") - isActive = false - end -end - -local function OnUnitCreated(_, unitTag) - sendFullUpdate = true - StartSending() -end - -local function OnUnitDestroyed(_, unitTag) - resources[GetUnitName(unitTag)] = nil - if(isActive and not IsUnitGrouped("player")) then - StopSending() - end -end - -function handler:InitializeSettings(optionsData, IsSendingDisabled) -- TODO: localization - optionsData[#optionsData + 1] = { - type = "header", - name = "Resource Handler", - } -optionsData[#optionsData + 1] = { - type = "checkbox", - name = "Enable sending", - tooltip = "Controls if the handler does send data. It will still receive and process incoming data.", - getFunc = function() return saveData.enabled end, - setFunc = function(value) - saveData.enabled = value - if(value) then StartSending() else StopSending() end - end, - disabled = IsSendingDisabled, - default = defaultData.enabled -} -optionsData[#optionsData + 1] = { - type = "checkbox", - name = "Send percentages only", - tooltip = "If this is turned on, your maximum resources won't be shared with your group members", - getFunc = function() return saveData.percentOnly end, - setFunc = function(value) saveData.percentOnly = value end, - disabled = IsSendingDisabled, - default = defaultData.percentOnly -} -end - --- savedata becomes available twice in case the standalone lib is loaded -local function InitializeSaveData(data) - saveData = data - - if(not saveData.version) then - ZO_DeepTableCopy(defaultData, saveData) - end - - -- if(saveData.version == 1) then - -- -- update it - -- end -end - -local function Unload() - LGS.cm:UnregisterCallback(type, handler.dataHandler) - LGS.cm:UnregisterCallback("savedata-ready", InitializeSaveData) - EVENT_MANAGER:UnregisterForEvent("LibGroupSocketResourceHandler", EVENT_UNIT_CREATED) - EVENT_MANAGER:UnregisterForEvent("LibGroupSocketResourceHandler", EVENT_UNIT_DESTROYED) - StopSending() -end - -local function Load() - InitializeSaveData(saveData) - LGS.cm:RegisterCallback("savedata-ready", function(data) - InitializeSaveData(data.handlers[type]) - end) - - handler.dataHandler = OnData - LGS.cm:RegisterCallback(type, OnData) - EVENT_MANAGER:RegisterForEvent("LibGroupSocketResourceHandler", EVENT_UNIT_CREATED, OnUnitCreated) - EVENT_MANAGER:RegisterForEvent("LibGroupSocketResourceHandler", EVENT_UNIT_DESTROYED, OnUnitDestroyed) - handler.Unload = Unload - - StartSending() -end - -if(handler.Unload) then handler.Unload() end -Load() diff --git a/TaosGroupTools/logic/MapPingHandler.lua b/TaosGroupTools/logic/MapPingHandler.lua index b594b11..c331226 100644 --- a/TaosGroupTools/logic/MapPingHandler.lua +++ b/TaosGroupTools/logic/MapPingHandler.lua @@ -25,7 +25,7 @@ TGU_MapPingHandler.Name = "TGU-MapPingHandler" TGU_MapPingHandler.IsMocked = false --[[ - Called on new data from LibGroupSocket + Called on new data from Communication ]]-- function TGU_MapPingHandler.OnData(pingTag, abilityPing, relativeUltimate) if (LOG_ACTIVE) then _logger:logTrace("TGU_MapPingHandler.OnData") end diff --git a/TaosGroupTools/logic/SettingsHandler.lua b/TaosGroupTools/logic/SettingsHandler.lua index 0dc742b..26fe9b2 100644 --- a/TaosGroupTools/logic/SettingsHandler.lua +++ b/TaosGroupTools/logic/SettingsHandler.lua @@ -31,7 +31,6 @@ TGU_SettingsHandler.Default = ["SelectorPosX"] = 0, ["SelectorPosY"] = 0, ["OnlyAva"] = false, - ["IsLgsActive"] = false, ["IsSortingActive"] = false, ["Movable"] = true, ["Style"] = 3, @@ -125,18 +124,6 @@ function TGU_SettingsHandler.SetOnlyAvaSettings(onlyAva) end --[[ - Sets IsLgsActive settings -]]-- -function TGU_SettingsHandler.SetIsLgsActiveSettings(isLgsActive) - if (LOG_ACTIVE) then - _logger:logTrace("TGU_SettingsHandler.SetIsLgsActiveSettings") - _logger:logDebug("isLgsActive", isLgsActive) - end - - TGU_SettingsHandler.SavedVariables.IsLgsActive = isLgsActive -end - ---[[ Sets IsSortingActive settings ]]-- function TGU_SettingsHandler.SetIsSortingActiveSettings(isSortingActive) diff --git a/TaosGroupTools/ui/SettingsWindow.lua b/TaosGroupTools/ui/SettingsWindow.lua index 4fbaf5c..bf8e6f1 100644 --- a/TaosGroupTools/ui/SettingsWindow.lua +++ b/TaosGroupTools/ui/SettingsWindow.lua @@ -79,21 +79,6 @@ function TGU_SettingsWindow.Initialize(logger, major, minor, patch) }, [4] = { type = "checkbox", - name = GetString(TGU_OPTIONS_USE_LGS_LABEL), - tooltip = GetString(TGU_OPTIONS_USE_LGS_TOOLTIP), - requiresReload = true, - getFunc = - function() - return TGU_SettingsHandler.SavedVariables.IsLgsActive - end, - setFunc = - function(value) - TGU_SettingsHandler.SetIsLgsActiveSettings(value) - end, - default = TGU_SettingsHandler.Default.IsLgsActive - }, - [5] = { - type = "checkbox", name = GetString(TGU_OPTIONS_USE_SORTING_LABEL), tooltip = GetString(TGU_OPTIONS_USE_SORTING_TOOLTIP), getFunc = @@ -106,7 +91,7 @@ function TGU_SettingsWindow.Initialize(logger, major, minor, patch) end, default = TGU_SettingsHandler.Default.IsSortingActive }, - [6] = { + [5] = { type = "dropdown", name = GetString(TGU_OPTIONS_STYLE_LABEL), tooltip = GetString(TGU_OPTIONS_STYLE_TOOLTIP),