Skip to content

Commit 41cb9cf

Browse files
committed
Sharing 4/4: Sharing Tab UI
1 parent 0ac6d63 commit 41cb9cf

22 files changed

Lines changed: 1262 additions & 677 deletions
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
local UnitShared = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_shared.lua")
2+
3+
local API = {}
4+
5+
local hoverChangeListeners = {}
6+
7+
---@param listener function
8+
function API.AddHoverChangeListener(listener)
9+
table.insert(hoverChangeListeners, listener)
10+
end
11+
12+
---@param listener function
13+
function API.RemoveHoverChangeListener(listener)
14+
for i, existingListener in ipairs(hoverChangeListeners) do
15+
if existingListener == listener then
16+
table.remove(hoverChangeListeners, i)
17+
break
18+
end
19+
end
20+
end
21+
22+
---Handle hover changes and notify about invalid units for the hovered player
23+
---@param myTeamID number
24+
---@param selectedUnits number[]
25+
---@param newHoverTeamID number | nil
26+
---@param newHoverPlayerID number | nil
27+
function API.HandleHoverChange(myTeamID, selectedUnits, newHoverTeamID, newHoverPlayerID)
28+
API.NotifyHoverChangeListeners(newHoverTeamID, newHoverPlayerID)
29+
30+
if newHoverTeamID and selectedUnits and #selectedUnits > 0 then
31+
local policyResult = UnitShared.GetCachedPolicyResult(myTeamID, newHoverTeamID, Spring)
32+
local validationResult = UnitShared.ValidateUnits(policyResult, selectedUnits, Spring)
33+
local invalidUnitIds = validationResult.invalidUnitIds
34+
if not policyResult.canShare and Spring.AreTeamsAllied(myTeamID, newHoverTeamID) then
35+
-- Sharing is fully disabled for this ally under the current mode (e.g. Tech
36+
-- Core at a tier whose unit_sharing_mode is "none"), so every selected unit is
37+
-- un-shareable. ValidateUnits short-circuits to an empty list when canShare is
38+
-- false, so flag them all here for the hover highlight.
39+
invalidUnitIds = selectedUnits
40+
end
41+
if #invalidUnitIds > 0 then
42+
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, invalidUnitIds)
43+
else
44+
-- empty notify clears any previous invalid state
45+
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, {})
46+
end
47+
else
48+
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, {})
49+
end
50+
end
51+
52+
---@param newHoverTeamID number | nil
53+
---@param newHoverPlayerID number | nil
54+
function API.NotifyHoverChangeListeners(newHoverTeamID, newHoverPlayerID)
55+
for _, listener in ipairs(hoverChangeListeners) do
56+
listener(newHoverTeamID, newHoverPlayerID)
57+
end
58+
end
59+
60+
local hoverInvalidUnitsListeners = {}
61+
62+
---@param listener function
63+
function API.AddHoverInvalidUnitsListener(listener)
64+
table.insert(hoverInvalidUnitsListeners, listener)
65+
end
66+
67+
---@param listener function
68+
function API.RemoveHoverInvalidUnitsListener(listener)
69+
for i, existingListener in ipairs(hoverInvalidUnitsListeners) do
70+
if existingListener == listener then
71+
table.remove(hoverInvalidUnitsListeners, i)
72+
break
73+
end
74+
end
75+
end
76+
77+
---@param newHoverTeamID number | nil
78+
---@param newHoverPlayerID number | nil
79+
---@param invalidUnitIds number[]
80+
function API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, invalidUnitIds)
81+
for _, listener in ipairs(hoverInvalidUnitsListeners) do
82+
listener(newHoverTeamID, newHoverPlayerID, invalidUnitIds)
83+
end
84+
end
85+
86+
return API
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--- Aggregates sub-helper modules so gui_advplayerslist.lua avoids the Lua local cap
2+
local PolicyHelpers = VFS.Include("common/luaUtilities/team_transfer/gui_advplayerlist/policy.lua")
3+
local ResourceHelpersFactory = VFS.Include("common/luaUtilities/team_transfer/gui_advplayerlist/resource.lua")
4+
local UnitValidationHelpers = VFS.Include("common/luaUtilities/team_transfer/gui_advplayerlist/validation.lua")
5+
6+
local Helpers = {}
7+
8+
local function extend(source)
9+
for key, value in pairs(source) do
10+
Helpers[key] = value
11+
end
12+
end
13+
14+
extend(PolicyHelpers)
15+
extend(ResourceHelpersFactory(PolicyHelpers))
16+
extend(UnitValidationHelpers)
17+
18+
return Helpers
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
--- Policy helpers that keep gui_advplayerslist.lua under the Lua local closure cap
2+
local TransferEnums = VFS.Include("common/luaUtilities/team_transfer/transfer_enums.lua")
3+
local UnitShared = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_shared.lua")
4+
local ResourceShared = VFS.Include("common/luaUtilities/team_transfer/resource_transfer_shared.lua")
5+
6+
local METAL_POLICY_PREFIX = "metal_"
7+
local ENERGY_POLICY_PREFIX = "energy_"
8+
local UNIT_POLICY_PREFIX = "unit_"
9+
10+
local metalPlayerScratch = {}
11+
local energyPlayerScratch = {}
12+
local unitPlayerScratch = {}
13+
14+
local PolicyHelpers = {}
15+
16+
---@param player table
17+
---@param resourceType string
18+
---@param senderTeamId number
19+
---@return ResourcePolicyResult policyResult, string pascalResourceType
20+
function PolicyHelpers.GetPlayerResourcePolicy(player, resourceType, senderTeamId)
21+
local transferCategory = resourceType == "metal" and TransferEnums.TransferCategory.MetalTransfer or
22+
TransferEnums.TransferCategory.EnergyTransfer
23+
local policyResult = PolicyHelpers.UnpackPolicyResult(transferCategory, player, senderTeamId, player.team)
24+
local pascalResourceType = resourceType == TransferEnums.ResourceType.METAL and "Metal" or "Energy"
25+
return policyResult, pascalResourceType
26+
end
27+
28+
---@param playerData table
29+
---@param myTeamID number
30+
---@param playerTeamID number
31+
function PolicyHelpers.PackAllPoliciesForPlayer(playerData, myTeamID, playerTeamID)
32+
PolicyHelpers.PackMetalPolicyResult(playerTeamID, myTeamID, playerData)
33+
PolicyHelpers.PackEnergyPolicyResult(playerTeamID, myTeamID, playerData)
34+
PolicyHelpers.PackUnitPolicyResult(playerTeamID, myTeamID, playerData)
35+
end
36+
37+
---@param playerData table
38+
---@param myTeamID number
39+
---@param team number
40+
---@return table, table, table
41+
function PolicyHelpers.UnpackAllPolicies(playerData, myTeamID, team)
42+
local metalPolicy = PolicyHelpers.UnpackPolicyResult(TransferEnums.TransferCategory.MetalTransfer, playerData, myTeamID,
43+
team)
44+
local energyPolicy = PolicyHelpers.UnpackPolicyResult(TransferEnums.TransferCategory.EnergyTransfer, playerData, myTeamID,
45+
team)
46+
local unitPolicy = PolicyHelpers.UnpackUnitPolicyResult(playerData, myTeamID, team)
47+
return metalPolicy, energyPolicy, unitPolicy
48+
end
49+
50+
---@param transferCategory string TransferEnums.TransferCategory
51+
---@param playerData table
52+
---@param senderTeamId number
53+
---@param receiverTeamId number
54+
---@return table
55+
function PolicyHelpers.UnpackPolicyResult(transferCategory, playerData, senderTeamId, receiverTeamId)
56+
local fields, prefix, scratch
57+
if transferCategory == TransferEnums.TransferCategory.MetalTransfer then
58+
fields = ResourceShared.ResourcePolicyFields
59+
prefix = METAL_POLICY_PREFIX
60+
scratch = metalPlayerScratch
61+
elseif transferCategory == TransferEnums.TransferCategory.EnergyTransfer then
62+
fields = ResourceShared.ResourcePolicyFields
63+
prefix = ENERGY_POLICY_PREFIX
64+
scratch = energyPlayerScratch
65+
elseif transferCategory == TransferEnums.TransferCategory.UnitTransfer then
66+
fields = UnitShared.UnitPolicyFields
67+
prefix = UNIT_POLICY_PREFIX
68+
scratch = unitPlayerScratch
69+
else
70+
error("Invalid transfer category: " .. transferCategory)
71+
end
72+
73+
scratch.senderTeamId = senderTeamId
74+
scratch.receiverTeamId = receiverTeamId
75+
76+
for field, _ in pairs(fields) do
77+
scratch[field] = playerData[prefix .. field]
78+
end
79+
return scratch
80+
end
81+
82+
---@param playerData table
83+
---@param senderTeamId number
84+
---@param receiverTeamId number
85+
---@return UnitPolicyResult
86+
function PolicyHelpers.UnpackUnitPolicyResult(playerData, senderTeamId, receiverTeamId)
87+
return PolicyHelpers.UnpackPolicyResult(TransferEnums.TransferCategory.UnitTransfer, playerData, senderTeamId,
88+
receiverTeamId)
89+
end
90+
91+
---@param transferCategory string TransferEnums.TransferCategory
92+
---@param policy table
93+
---@param playerData table
94+
function PolicyHelpers.PackPolicyResult(transferCategory, policy, playerData)
95+
local fields, prefix
96+
if transferCategory == TransferEnums.TransferCategory.MetalTransfer then
97+
fields = ResourceShared.ResourcePolicyFields
98+
prefix = METAL_POLICY_PREFIX
99+
elseif transferCategory == TransferEnums.TransferCategory.EnergyTransfer then
100+
fields = ResourceShared.ResourcePolicyFields
101+
prefix = ENERGY_POLICY_PREFIX
102+
elseif transferCategory == TransferEnums.TransferCategory.UnitTransfer then
103+
fields = UnitShared.UnitPolicyFields
104+
prefix = UNIT_POLICY_PREFIX
105+
else
106+
error("Invalid transfer category: " .. transferCategory)
107+
end
108+
for field, _ in pairs(fields) do
109+
playerData[prefix .. field] = policy[field]
110+
end
111+
end
112+
113+
---@param team number
114+
---@param myTeamID number
115+
---@param player table
116+
function PolicyHelpers.PackMetalPolicyResult(team, myTeamID, player)
117+
local policyResult = ResourceShared.GetCachedPolicyResult(myTeamID, team, TransferEnums.ResourceType.METAL)
118+
PolicyHelpers.PackPolicyResult(TransferEnums.TransferCategory.MetalTransfer, policyResult, player)
119+
end
120+
121+
---@param team number
122+
---@param myTeamID number
123+
---@param player table
124+
function PolicyHelpers.PackEnergyPolicyResult(team, myTeamID, player)
125+
local policyResult = ResourceShared.GetCachedPolicyResult(myTeamID, team, TransferEnums.ResourceType.ENERGY)
126+
PolicyHelpers.PackPolicyResult(TransferEnums.TransferCategory.EnergyTransfer, policyResult, player)
127+
end
128+
129+
---@param team number
130+
---@param myTeamID number
131+
---@param player table
132+
function PolicyHelpers.PackUnitPolicyResult(team, myTeamID, player)
133+
local policyResult = UnitShared.GetCachedPolicyResult(myTeamID, team, Spring)
134+
PolicyHelpers.PackPolicyResult(TransferEnums.TransferCategory.UnitTransfer, policyResult, player)
135+
end
136+
137+
local packByDomain = {
138+
unit = PolicyHelpers.PackUnitPolicyResult,
139+
metal = PolicyHelpers.PackMetalPolicyResult,
140+
energy = PolicyHelpers.PackEnergyPolicyResult,
141+
}
142+
143+
---Re-pack policy for rows affected by a SharePolicyChanged event: all rows when our own
144+
---team (the sender) changed, otherwise just the changed team's row.
145+
---@param player table all player rows
146+
---@param myTeamID number
147+
---@param changedTeamID number team whose policy changed
148+
---@param domain string "unit" | "metal" | "energy"
149+
function PolicyHelpers.RepackPolicy(player, myTeamID, changedTeamID, domain)
150+
local packFn = packByDomain[domain]
151+
if not packFn then return end
152+
153+
for _, playerData in pairs(player) do
154+
if playerData.team and playerData.team ~= myTeamID then
155+
if changedTeamID == myTeamID or playerData.team == changedTeamID then
156+
packFn(playerData.team, myTeamID, playerData)
157+
end
158+
end
159+
end
160+
end
161+
162+
return PolicyHelpers
163+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--- Resource transfer helpers kept separate to reduce gui_advplayerslist.lua locals
2+
local TransferEnums = VFS.Include("common/luaUtilities/team_transfer/transfer_enums.lua")
3+
local ResourceShared = VFS.Include("common/luaUtilities/team_transfer/resource_transfer_shared.lua")
4+
local LuaRulesMsg = VFS.Include("common/luaUtilities/lua_rules_msg.lua")
5+
6+
---@param policyHelpers table
7+
---@return table
8+
return function(policyHelpers)
9+
local ResourceHelpers = {}
10+
11+
---Handle resource transfer logic for a players list entry
12+
---@param targetPlayer table
13+
---@param resourceType string
14+
---@param shareAmount number
15+
---@param senderTeamId number
16+
function ResourceHelpers.HandleResourceTransfer(targetPlayer, resourceType, shareAmount, senderTeamId)
17+
local policyResult, pascalResourceType = policyHelpers.GetPlayerResourcePolicy(targetPlayer, resourceType, senderTeamId)
18+
19+
local case = ResourceShared.DecideCommunicationCase(policyResult)
20+
21+
if case == TransferEnums.ResourceCommunicationCase.OnSelf then
22+
if shareAmount > 0 then
23+
Spring.SendLuaRulesMsg('msg:ui.playersList.chat.need' .. pascalResourceType .. 'Amount:amount:' .. shareAmount)
24+
elseif policyResult.amountReceivable > 0 then
25+
Spring.SendLuaRulesMsg('msg:ui.playersList.chat.need' .. pascalResourceType)
26+
end
27+
elseif shareAmount and shareAmount > 0 then
28+
local msg = LuaRulesMsg.SerializeResourceShare(senderTeamId, targetPlayer.team, resourceType, shareAmount)
29+
Spring.SendLuaRulesMsg(msg)
30+
end
31+
end
32+
33+
return ResourceHelpers
34+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
local ResourceShared = VFS.Include("common/luaUtilities/team_transfer/resource_transfer_shared.lua")
2+
local UnitShared = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_shared.lua")
3+
local UnitUnsynced = VFS.Include("common/luaUtilities/team_transfer/unit_transfer_unsynced.lua")
4+
5+
local TeamTransfer = {}
6+
7+
TeamTransfer.Resources = ResourceShared
8+
TeamTransfer.Units = UnitShared
9+
TeamTransfer.Units.ShareUnits = UnitUnsynced.ShareUnits
10+
11+
return TeamTransfer
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
local LuaRulesMsg = VFS.Include("common/luaUtilities/lua_rules_msg.lua")
2+
3+
local Unsynced = {}
4+
5+
---Share currently selected units to target team (mirrors Spring.ShareResources behavior)
6+
---@param targetTeamID number
7+
function Unsynced.ShareUnits(targetTeamID)
8+
local unitIDs = Spring.GetSelectedUnits()
9+
if #unitIDs == 0 then
10+
return
11+
end
12+
local msg = LuaRulesMsg.SerializeUnitTransfer(targetTeamID, unitIDs)
13+
Spring.SendLuaRulesMsg(msg)
14+
end
15+
16+
return Unsynced
17+

0 commit comments

Comments
 (0)