sharing 1/4: foundations (modes, economy boundary, transfer library)#7962
Conversation
| @@ -0,0 +1,58 @@ | |||
| local M = {} | |||
|
|
|||
There was a problem hiding this comment.
The specs for this file are in PR#2. Stats updates are deferred a tick.
| isCheatingEnabled = springRepo.IsCheatingEnabled(), | ||
| ext = {}, | ||
| } | ||
|
|
There was a problem hiding this comment.
Enrichers are a mechanism for subsystems (e.g. tech_core) to inject state into a context without downstream policies caring where, for example, tax rate is coming from.
| -- degrades to the base rate when tech_blocking isn't active. | ||
| ---@param springRepo SpringSynced | ||
| ---@param teamId number | ||
| ---@return number |
There was a problem hiding this comment.
A team's current sharing tax rate, resolved live from its tech level. Unlike the policy path, the waterfill solver works per-team with no sender/receiver pair, so it can't read tax off a PolicyContext; this is its context-free accessor. Tech-blocking aware (callers need no knowledge of tech_core) and degrades to the base rate when tech_blocking is inactive. For the context path, see the enrichers registered via context_factory (registerPolicyContextEnricher) — e.g. game_tech_blocking stamps ctx.taxRate.
|
|
||
| --- Determine communication case from policy result | ||
| ---@param policyResult ResourcePolicyResult | ||
| ---@return integer |
There was a problem hiding this comment.
I fregin love the comms files and this classifier pattern in particular. So much complexity moved to a single function. Note that it must remain exhaustive.
| if not SharedConfig.isResourceSharingEnabled(ctx.springRepo) then | ||
| return Shared.CreateDenyPolicy(ctx.senderTeamId, ctx.receiverTeamId, resourceType, ctx.springRepo) | ||
| end | ||
|
|
There was a problem hiding this comment.
This is necessary to preserve existing expectations around cheat mode. I have tested the fallbacks without cheats on.
| end | ||
| return table.concat(names, " + ") | ||
| end | ||
|
|
There was a problem hiding this comment.
This bit allows us to show "unlocked forever" if you have reached the end of unlocks in tech_core.
| -- example usecase: Spring.SendLuaRulesMsg('msg:ui.playersList.chat.needEnergyAmount:amount='..shareAmount) | ||
| -- example usecase: Spring.SendLuaRulesMsg('msg:ui.playersList.chat.needEnergyAmount:amount:'..shareAmount) | ||
|
|
||
| local PACKET_HEADER = "msg" |
There was a problem hiding this comment.
With "msg" (len 3) it matches any message starting with msg: msgFoo, msgsomethingelse, etc. With "msg:" (len 4) it only matches when the : delimiter is actually present, so it can't accidentally swallow some other gadget's msg-prefixed packet.
With len 3 it strips msg and leaves the payload as :ui.playersList... , a stray leading colon.
| local ModeTestHelpers = VFS.Include("spec/builders/mode_test_helpers.lua") | ||
|
|
||
| ---@class Builders | ||
| ---@field Team TeamBuilder |
There was a problem hiding this comment.
Whoops I thought I completed this rename before this branch.
64f3fb5 to
8c607b5
Compare
| vars = vars or {} | ||
| str = escapeDoublePercent(str) | ||
| str = interpolateVariables(str, vars) | ||
| str = interpolateFormattedVariables(str, vars) |
There was a problem hiding this comment.
This is also fixed in a separate PR, but left here because it does allow the branch to work.
495e115 to
af8b189
Compare
f5a94ae to
8942707
Compare
| local taxRate = ctx.taxRate or SharedConfig.getTaxConfig(ctx.springRepo) | ||
| return (taxRate < 1) and taxRate or 1 | ||
| end | ||
|
|
There was a problem hiding this comment.
The core idea of this PR: a pure function from an enriched per-(sender,receiver) context to the single answer object every downstream consumer (UI, transfer actions, chat) needs -- canShare, sendable/receivable, tax, tech gating. Variability lives in the context + enrichers, not here.
Because it's pure, policy can become data: lift the deny cascade into named, composable nodes that declare what they read/write on ctx, giving an analyzable, mode-diffable rule tree with surgical (dependency-based) cache invalidation. The load-bearing seam is a pure decision separated from imperative effect -- keep the rules pure, composable and extensible (spec kept separate from runtime state) and the math monomorphic.
This shape isn't specific to sharing: the same decision/effect split could underpin the Mission API and game behavior broadly. "Data-driven" alone isn't the win -- purity, composition and extensibility are.
20801f9 to
4c65388
Compare
4c65388 to
fc1c4e1
Compare
📚 Stacked split of #5704 — review bottom-up
Each PR merges into the one below it; all four squash-equal the
sharing_tabbranch (verified byte-identical).Stack 1 of 4 splitting #5704 into reviewable layers.
Pure modules + their specs, no runtime wiring yet:
modes/sharing/*presets,sharing_mode_enums/helpers, modoptions entrieseconomy/*— waterfill solver, manual share ledger, shared_configteam_transfer/*core — enums, comms, shared/synced logic, context_factory, serialization, unit_sharing_categories, tech_blockingTargets the
sharing_tab_mergeableintegration base. Reviews bottom-up.