Skip to content
Closed
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
4 changes: 3 additions & 1 deletion .luarc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
},
"workspace": {
"library": [
"recoil-lua-library"
"recoil-lua-library",
"types",
"common/luaUtilities"
],
"ignoreDir": [
".vscode",
Expand Down
144 changes: 144 additions & 0 deletions common/luaUtilities/team_transfer/context_factory.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
local SharedEnums = VFS.Include("common/luaUtilities/team_transfer/shared_enums.lua")

---@class ContextFactory
---@field create fun(springRepo: ISpring): ContextFactory
---@field policy fun(senderTeamID: number, receiverTeamID: number): PolicyContext
---@field action fun(senderTeamId: number, receiverTeamId: number, transferCategory: string): PolicyActionContext
---@field resourceTransfer fun(senderTeamId: number, receiverTeamId: number, resourceType: ResourceType, desiredAmount: number, policyResult: ResourcePolicyResult): ResourceTransferContext
---@field unitTransfer fun(senderTeamId: number, receiverTeamId: number, unitIds: number[], given: boolean, policyResult: UnitPolicyResult, unitValidationResult: UnitValidationResult): UnitTransferContext
local ContextFactory = {}

---@param springRepo ISpring
---@param teamID number
---@param resourceType string
---@return ResourceData Complete resource data for the team
local function getTeamResourcesUnpacked(springRepo, teamID, resourceType)
local current, storage, pull, income, expense, share, sent, received = springRepo.GetTeamResources(teamID,
resourceType)

return {
current = current,
storage = storage,
pull = pull,
income = income,
expense = expense,
shareSlider = share,
sent = sent,
received = received
}
end

Comment thread
keithharvey marked this conversation as resolved.
---@param springRepo ISpring
---@return table Context factory with closures
function ContextFactory.create(springRepo)
---Create context with optional extensions
---@param senderTeamID number
---@param receiverTeamID number
---@param extensions? table Additional fields to merge
---@return table Context
local function buildContext(senderTeamID, receiverTeamID, extensions)
local senderMetal = getTeamResourcesUnpacked(springRepo, senderTeamID, SharedEnums.ResourceType.METAL)
local senderEnergy = getTeamResourcesUnpacked(springRepo, senderTeamID, SharedEnums.ResourceType.ENERGY)
local receiverMetal = getTeamResourcesUnpacked(springRepo, receiverTeamID, SharedEnums.ResourceType.METAL)
local receiverEnergy = getTeamResourcesUnpacked(springRepo, receiverTeamID, SharedEnums.ResourceType.ENERGY)

---@type TeamResources
local senderResources = {
metal = senderMetal,
energy = senderEnergy
}

---@type TeamResources
local receiverResources = {
metal = receiverMetal,
energy = receiverEnergy
}

---@type PolicyContext
local ctx = {
senderTeamId = senderTeamID,
receiverTeamId = receiverTeamID,
resultSoFar = {},
sender = senderResources,
receiver = receiverResources,
springRepo = springRepo,
areAlliedTeams = springRepo.AreTeamsAllied(senderTeamID, receiverTeamID),
isCheatingEnabled = springRepo.IsCheatingEnabled()
}

if extensions then
for k, v in pairs(extensions) do
ctx[k] = v
end
end

return ctx
end

---Create policy context
---@param senderTeamID number
---@param receiverTeamID number
---@param commandType? string
---@return PolicyContext
local function policy(senderTeamID, receiverTeamID, commandType)
return buildContext(senderTeamID, receiverTeamID, {
commandType = commandType
})
end

---Create action context
---@param transferCategory string
---@param senderTeamId number
---@param receiverTeamId number
---@return PolicyActionContext
local function policyAction(senderTeamId, receiverTeamId, transferCategory)
return buildContext(senderTeamId, receiverTeamId, {
transferCategory = transferCategory
})
end

---Create resource transfer context for transfer actions
---@param senderTeamId number
---@param receiverTeamId number
---@param resourceType ResourceType
---@param desiredAmount number
---@param policyResult ResourcePolicyResult
---@return ResourceTransferContext
local function resourceTransfer(senderTeamId, receiverTeamId, resourceType, desiredAmount, policyResult)
local transferCategory = resourceType == SharedEnums.ResourceType.METAL and resourceType or
SharedEnums.TransferCategory.EnergyTransfer
return buildContext(senderTeamId, receiverTeamId, {
transferCategory = transferCategory,
resourceType = resourceType,
desiredAmount = desiredAmount,
policyResult = policyResult
})
end

---Create unit transfer context for transfer actions
---@param senderTeamId number
---@param receiverTeamId number
---@param unitIds number[]
---@param given boolean?
---@param policyResult UnitPolicyResult\
---@param validationResult UnitValidationResult
---@return UnitTransferContext
local function unitTransfer(senderTeamId, receiverTeamId, unitIds, given, policyResult, validationResult)
return buildContext(senderTeamId, receiverTeamId, {
transferCategory = SharedEnums.TransferCategory.UnitTransfer,
unitIds = unitIds,
given = given,
policyResult = policyResult,
validationResult = validationResult
})
end

return {
policy = policy,
action = policyAction,
resourceTransfer = resourceTransfer,
unitTransfer = unitTransfer,
}
end

return ContextFactory
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
local SharedEnums = VFS.Include("common/luaUtilities/team_transfer/shared_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 API = {}

-- Hover listener management
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)
-- Notify hover change listeners
API.NotifyHoverChangeListeners(newHoverTeamID, newHoverPlayerID)

-- Notify about invalid units (or clear them if not hovering)
if newHoverTeamID and selectedUnits and #selectedUnits > 0 then
local policyResult = UnitShared.GetCachedPolicyResult(myTeamID, newHoverTeamID)
local validationResult = UnitShared.ValidateUnits(policyResult, selectedUnits)
if #validationResult.invalidUnitIds > 0 then
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, validationResult.invalidUnitIds)
else
-- No invalid units, but still notify to clear any previous invalid state
API.NotifyHoverSelectedUnitsInvalid(newHoverTeamID, newHoverPlayerID, {})
end
else
-- Not hovering or no selected units, clear invalid state
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

-- Hover invalid units listeners
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
Loading