Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
local UnitShared = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_shared.lua")

local API = {}

local hoverChangeListeners = {}

---@param listener function
function API.AddHoverChangeListener(listener)
table.insert(hoverChangeListeners, listener)
end

---@param listener function
function API.RemoveHoverChangeListener(listener)
for i, existingListener in ipairs(hoverChangeListeners) do
if existingListener == listener then
table.remove(hoverChangeListeners, i)
break
end
end
end

---Handle hover changes and notify about invalid units for the hovered player
---@param myTeamID number
---@param selectedUnits number[]
---@param newHoverTeamID number | nil
---@param newHoverPlayerID number | nil
function API.HandleHoverChange(myTeamID, selectedUnits, newHoverTeamID, newHoverPlayerID)
API.NotifyHoverChangeListeners(newHoverTeamID, newHoverPlayerID)

if newHoverTeamID and selectedUnits and #selectedUnits > 0 then
local policyResult = UnitShared.GetCachedPolicyResult(myTeamID, newHoverTeamID, Spring)
local validationResult = UnitShared.ValidateUnits(policyResult, selectedUnits, Spring)
if #validationResult.invalidUnitIds > 0 then
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, validationResult.invalidUnitIds)
else
-- empty notify clears any previous invalid state
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, {})
end
else
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, {})
end
end

---@param newHoverTeamID number | nil
---@param newHoverPlayerID number | nil
function API.NotifyHoverChangeListeners(newHoverTeamID, newHoverPlayerID)
for _, listener in ipairs(hoverChangeListeners) do
listener(newHoverTeamID, newHoverPlayerID)
end
end

local hoverInvalidUnitsListeners = {}

---@param listener function
function API.AddHoverInvalidUnitsListener(listener)
table.insert(hoverInvalidUnitsListeners, listener)
end

---@param listener function
function API.RemoveHoverInvalidUnitsListener(listener)
for i, existingListener in ipairs(hoverInvalidUnitsListeners) do
if existingListener == listener then
table.remove(hoverInvalidUnitsListeners, i)
break
end
end
end

---@param newHoverTeamID number | nil
---@param newHoverPlayerID number | nil
---@param invalidUnitIds number[]
function API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, invalidUnitIds)
for _, listener in ipairs(hoverInvalidUnitsListeners) do
listener(newHoverTeamID, newHoverPlayerID, invalidUnitIds)
end
end

return API
18 changes: 18 additions & 0 deletions common/luaUtilities/team_transfer/gui_advplayerlist/helpers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--- Aggregates sub-helper modules so gui_advplayerslist.lua avoids the Lua local cap
local PolicyHelpers = VFS.Include("common/luaUtilities/team_transfer/gui_advplayerlist/policy.lua")
local ResourceHelpersFactory = VFS.Include("common/luaUtilities/team_transfer/gui_advplayerlist/resource.lua")
local UnitValidationHelpers = VFS.Include("common/luaUtilities/team_transfer/gui_advplayerlist/validation.lua")

local Helpers = {}

local function extend(source)
for key, value in pairs(source) do
Helpers[key] = value
end
end

extend(PolicyHelpers)
extend(ResourceHelpersFactory(PolicyHelpers))
extend(UnitValidationHelpers)

return Helpers
163 changes: 163 additions & 0 deletions common/luaUtilities/team_transfer/gui_advplayerlist/policy.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
--- Policy helpers that keep gui_advplayerslist.lua under the Lua local closure cap
local TransferEnums = VFS.Include("common/luaUtilities/team_transfer/transfer_enums.lua")
local UnitShared = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_shared.lua")
local ResourceShared = VFS.Include("common/luaUtilities/team_transfer/resource_transfer_shared.lua")

local METAL_POLICY_PREFIX = "metal_"
local ENERGY_POLICY_PREFIX = "energy_"
local UNIT_POLICY_PREFIX = "unit_"

local metalPlayerScratch = {}
local energyPlayerScratch = {}
local unitPlayerScratch = {}

local PolicyHelpers = {}

---@param player table
---@param resourceType string
---@param senderTeamId number
---@return ResourcePolicyResult policyResult, string pascalResourceType
function PolicyHelpers.GetPlayerResourcePolicy(player, resourceType, senderTeamId)
local transferCategory = resourceType == "metal" and TransferEnums.TransferCategory.MetalTransfer or
TransferEnums.TransferCategory.EnergyTransfer
local policyResult = PolicyHelpers.UnpackPolicyResult(transferCategory, player, senderTeamId, player.team)
local pascalResourceType = resourceType == TransferEnums.ResourceType.METAL and "Metal" or "Energy"
return policyResult, pascalResourceType
end

---@param playerData table
---@param myTeamID number
---@param playerTeamID number
function PolicyHelpers.PackAllPoliciesForPlayer(playerData, myTeamID, playerTeamID)
PolicyHelpers.PackMetalPolicyResult(playerTeamID, myTeamID, playerData)
PolicyHelpers.PackEnergyPolicyResult(playerTeamID, myTeamID, playerData)
PolicyHelpers.PackUnitPolicyResult(playerTeamID, myTeamID, playerData)
end

---@param playerData table
---@param myTeamID number
---@param team number
---@return table, table, table
function PolicyHelpers.UnpackAllPolicies(playerData, myTeamID, team)
local metalPolicy = PolicyHelpers.UnpackPolicyResult(TransferEnums.TransferCategory.MetalTransfer, playerData, myTeamID,
team)
local energyPolicy = PolicyHelpers.UnpackPolicyResult(TransferEnums.TransferCategory.EnergyTransfer, playerData, myTeamID,
team)
local unitPolicy = PolicyHelpers.UnpackUnitPolicyResult(playerData, myTeamID, team)
return metalPolicy, energyPolicy, unitPolicy
end

---@param transferCategory string TransferEnums.TransferCategory
---@param playerData table
---@param senderTeamId number
---@param receiverTeamId number
---@return table
function PolicyHelpers.UnpackPolicyResult(transferCategory, playerData, senderTeamId, receiverTeamId)
local fields, prefix, scratch
if transferCategory == TransferEnums.TransferCategory.MetalTransfer then
fields = ResourceShared.ResourcePolicyFields
prefix = METAL_POLICY_PREFIX
scratch = metalPlayerScratch
elseif transferCategory == TransferEnums.TransferCategory.EnergyTransfer then
fields = ResourceShared.ResourcePolicyFields
prefix = ENERGY_POLICY_PREFIX
scratch = energyPlayerScratch
elseif transferCategory == TransferEnums.TransferCategory.UnitTransfer then
fields = UnitShared.UnitPolicyFields
prefix = UNIT_POLICY_PREFIX
scratch = unitPlayerScratch
else
error("Invalid transfer category: " .. transferCategory)
end

scratch.senderTeamId = senderTeamId
scratch.receiverTeamId = receiverTeamId

for field, _ in pairs(fields) do
scratch[field] = playerData[prefix .. field]
end
return scratch
end

---@param playerData table
---@param senderTeamId number
---@param receiverTeamId number
---@return UnitPolicyResult
function PolicyHelpers.UnpackUnitPolicyResult(playerData, senderTeamId, receiverTeamId)
return PolicyHelpers.UnpackPolicyResult(TransferEnums.TransferCategory.UnitTransfer, playerData, senderTeamId,
receiverTeamId)
end

---@param transferCategory string TransferEnums.TransferCategory
---@param policy table
---@param playerData table
function PolicyHelpers.PackPolicyResult(transferCategory, policy, playerData)
local fields, prefix
if transferCategory == TransferEnums.TransferCategory.MetalTransfer then
fields = ResourceShared.ResourcePolicyFields
prefix = METAL_POLICY_PREFIX
elseif transferCategory == TransferEnums.TransferCategory.EnergyTransfer then
fields = ResourceShared.ResourcePolicyFields
prefix = ENERGY_POLICY_PREFIX
elseif transferCategory == TransferEnums.TransferCategory.UnitTransfer then
fields = UnitShared.UnitPolicyFields
prefix = UNIT_POLICY_PREFIX
else
error("Invalid transfer category: " .. transferCategory)
end
for field, _ in pairs(fields) do
playerData[prefix .. field] = policy[field]
end
end

---@param team number
---@param myTeamID number
---@param player table
function PolicyHelpers.PackMetalPolicyResult(team, myTeamID, player)
local policyResult = ResourceShared.GetCachedPolicyResult(myTeamID, team, TransferEnums.ResourceType.METAL)
PolicyHelpers.PackPolicyResult(TransferEnums.TransferCategory.MetalTransfer, policyResult, player)
end

---@param team number
---@param myTeamID number
---@param player table
function PolicyHelpers.PackEnergyPolicyResult(team, myTeamID, player)
local policyResult = ResourceShared.GetCachedPolicyResult(myTeamID, team, TransferEnums.ResourceType.ENERGY)
PolicyHelpers.PackPolicyResult(TransferEnums.TransferCategory.EnergyTransfer, policyResult, player)
end

---@param team number
---@param myTeamID number
---@param player table
function PolicyHelpers.PackUnitPolicyResult(team, myTeamID, player)
local policyResult = UnitShared.GetCachedPolicyResult(myTeamID, team, Spring)
PolicyHelpers.PackPolicyResult(TransferEnums.TransferCategory.UnitTransfer, policyResult, player)
end

local packByDomain = {
unit = PolicyHelpers.PackUnitPolicyResult,
metal = PolicyHelpers.PackMetalPolicyResult,
energy = PolicyHelpers.PackEnergyPolicyResult,
}

---Re-pack policy for rows affected by a SharePolicyChanged event: all rows when our own
---team (the sender) changed, otherwise just the changed team's row.
---@param player table all player rows
---@param myTeamID number
---@param changedTeamID number team whose policy changed
---@param domain string "unit" | "metal" | "energy"
function PolicyHelpers.RepackPolicy(player, myTeamID, changedTeamID, domain)
local packFn = packByDomain[domain]
if not packFn then return end

for _, playerData in pairs(player) do
if playerData.team and playerData.team ~= myTeamID then
if changedTeamID == myTeamID or playerData.team == changedTeamID then
packFn(playerData.team, myTeamID, playerData)
end
end
end
end

return PolicyHelpers

34 changes: 34 additions & 0 deletions common/luaUtilities/team_transfer/gui_advplayerlist/resource.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
--- Resource transfer helpers kept separate to reduce gui_advplayerslist.lua locals
local TransferEnums = VFS.Include("common/luaUtilities/team_transfer/transfer_enums.lua")
local ResourceShared = VFS.Include("common/luaUtilities/team_transfer/resource_transfer_shared.lua")
local LuaRulesMsg = VFS.Include("common/luaUtilities/lua_rules_msg.lua")

---@param policyHelpers table
---@return table
return function(policyHelpers)
local ResourceHelpers = {}

---Handle resource transfer logic for a players list entry
---@param targetPlayer table
---@param resourceType string
---@param shareAmount number
---@param senderTeamId number
function ResourceHelpers.HandleResourceTransfer(targetPlayer, resourceType, shareAmount, senderTeamId)
local policyResult, pascalResourceType = policyHelpers.GetPlayerResourcePolicy(targetPlayer, resourceType, senderTeamId)

local case = ResourceShared.DecideCommunicationCase(policyResult)

if case == TransferEnums.ResourceCommunicationCase.OnSelf then
if shareAmount > 0 then
Spring.SendLuaRulesMsg('msg:ui.playersList.chat.need' .. pascalResourceType .. 'Amount:amount:' .. shareAmount)
elseif policyResult.amountReceivable > 0 then
Spring.SendLuaRulesMsg('msg:ui.playersList.chat.need' .. pascalResourceType)
end
elseif shareAmount and shareAmount > 0 then
local msg = LuaRulesMsg.SerializeResourceShare(senderTeamId, targetPlayer.team, resourceType, shareAmount)
Spring.SendLuaRulesMsg(msg)
end
end

return ResourceHelpers
end
11 changes: 11 additions & 0 deletions common/luaUtilities/team_transfer/team_transfer_unsynced.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
local ResourceShared = VFS.Include("common/luaUtilities/team_transfer/resource_transfer_shared.lua")
local UnitShared = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_shared.lua")
local UnitUnsynced = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_unsynced.lua")

local TeamTransfer = {}

TeamTransfer.Resources = ResourceShared
TeamTransfer.Units = UnitShared
TeamTransfer.Units.ShareUnits = UnitUnsynced.ShareUnits

return TeamTransfer
17 changes: 17 additions & 0 deletions common/luaUtilities/team_transfer/unit_transfer_unsynced.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
local LuaRulesMsg = VFS.Include("common/luaUtilities/lua_rules_msg.lua")

local Unsynced = {}

---Share currently selected units to target team (mirrors Spring.ShareResources behavior)
---@param targetTeamID number
function Unsynced.ShareUnits(targetTeamID)
local unitIDs = Spring.GetSelectedUnits()
if #unitIDs == 0 then
return
end
local msg = LuaRulesMsg.SerializeUnitTransfer(targetTeamID, unitIDs)
Spring.SendLuaRulesMsg(msg)
end

return Unsynced

Loading
Loading