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
31 changes: 31 additions & 0 deletions rts/Lua/LuaHandleSynced.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,37 @@ bool CSyncedLuaHandle::AllowResourceTransfer(int oldTeam, int newTeam, const cha
return allow;
}

/*** Called when excess resources are added.
* Accumulates all excesses within a single gameframe.
*

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should document what happens if you generate more excess while inside this event.

* @function SyncedCallins:TeamResourceExcess
* @param teamID integer
* @param amountMetal number
* @param amountEnergy number
* @return boolean whether or not Lua handled the event
*/
bool CSyncedLuaHandle::TeamResourceExcess(int teamID, const SResourcePack& excess)
{
RECOIL_DETAILED_TRACY_ZONE;
LUA_CALL_IN_CHECK(L, true);
luaL_checkstack(L, 3 + excess.MAX_RESOURCES, __func__);

static const LuaHashString cmdStr(__func__);
if (!cmdStr.GetGlobalFunc(L))
return false;

lua_pushnumber(L, teamID);
for (int i = 0; i < excess.MAX_RESOURCES; ++i)
lua_pushnumber(L, excess[i]);

if (!RunCallIn(L, cmdStr, 1 + excess.MAX_RESOURCES, 1))
return false;

const bool handled = luaL_optboolean(L, -1, false);
lua_pop(L, 1);
return handled;
}


/*** Determines if this unit can be controlled directly in FPS view.
*
Expand Down
2 changes: 2 additions & 0 deletions rts/Lua/LuaHandleSynced.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class CSyncedLuaHandle : public CLuaHandle
bool CommandFallback(const CUnit* unit, const Command& cmd) override;
bool AllowCommand(const CUnit* unit, const Command& cmd, int playerNum, bool fromSynced, bool fromLua) override;

bool TeamResourceExcess(int teamID, const SResourcePack& excess) override;

std::pair <bool, bool> AllowUnitCreation(const UnitDef* unitDef, const CUnit* builder, const BuildInfo* buildInfo) override;
bool AllowUnitTransfer(const CUnit* unit, int newTeam, bool capture) override;
bool AllowUnitBuildStep(const CUnit* builder, const CUnit* unit, float part) override;
Expand Down
33 changes: 30 additions & 3 deletions rts/Sim/Misc/Team.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ CR_REG_METADATA(CTeam, (
CR_MEMBER(resPrevExpense),
CR_MEMBER(resShare),
CR_MEMBER(resDelayedShare),
CR_MEMBER(resOverflow),
CR_MEMBER(resSent),
CR_MEMBER(resPrevSent),
CR_MEMBER(resReceived),
Expand Down Expand Up @@ -156,7 +157,7 @@ void CTeam::AddMetal(float amount, bool useIncomeMultiplier)
if (res.metal <= resStorage.metal)
return;

resDelayedShare.metal += (res.metal - resStorage.metal);
resOverflow.metal += (res.metal - resStorage.metal);
res.metal = resStorage.metal;
}

Expand All @@ -170,7 +171,7 @@ void CTeam::AddEnergy(float amount, bool useIncomeMultiplier)
resIncome.energy += amount;

if (res.energy > resStorage.energy) {
resDelayedShare.energy += (res.energy - resStorage.energy);
resOverflow.energy += (res.energy - resStorage.energy);
res.energy = resStorage.energy;
}
}
Expand All @@ -196,7 +197,7 @@ void CTeam::AddResources(SResourcePack amount, bool useIncomeMultiplier)
if (res[i] <= resStorage[i])
continue;

resDelayedShare[i] += (res[i] - resStorage[i]);
resOverflow[i] += (res[i] - resStorage[i]);
res[i] = resStorage[i];
}
}
Expand Down Expand Up @@ -316,6 +317,32 @@ void CTeam::ResetResourceState()
resPrevReceived.energy = resReceived.energy; resReceived.energy = 0.0f;
}

void CTeam::HandleFrameExcess()
{
/* A team having no excess is also useful information that is a bit annoying
* to detect otherwise, but we make a conservative perf overhead guess.
* Perhaps we will have the leeway to remove this optimisation in the future. */
if (resOverflow.empty())
return;

/* Having a metaaccumulator and relegating the "real" native behaviour to
* slowupdate rather than doing it immediately here is mostly for legacy,
* but it's also consistent with how most existing resource mechanics,
* in particular sharing excess to allies aka the red slider, mostly work
* per slowupdate. */
if (!eventHandler.TeamResourceExcess(teamNum, resOverflow))
resDelayedShare += resOverflow;

resOverflow = 0.0f;
}

void CTeam::GameFramePost(int frameNum)
{
/* Excess being accumulated across a frame (rather than called for every resource income
* instance) is for perf, as you can have e.g. tens of thousands of windgens or whatnot. */
HandleFrameExcess();
}

void CTeam::SlowUpdate()
{
RECOIL_DETAILED_TRACY_ZONE;
Expand Down
5 changes: 5 additions & 0 deletions rts/Sim/Misc/Team.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class CTeam : public TeamBase

void ResetResourceState();
void SlowUpdate();
void GameFramePost(int frameNum);

bool HaveResources(const SResourcePack& amount) const;
void AddResources(SResourcePack res, bool useIncomeMultiplier = true);
Expand Down Expand Up @@ -73,6 +74,9 @@ class CTeam : public TeamBase
void AddUnit(CUnit* unit, AddType type);
void RemoveUnit(CUnit* unit, RemoveType type);

private:
void HandleFrameExcess();

public:
int teamNum;
unsigned int numUnits; // number of units this team controls
Expand All @@ -89,6 +93,7 @@ class CTeam : public TeamBase
SResourcePack resExpense, resPrevExpense;
SResourcePack resShare;
SResourcePack resDelayedShare; //< excess that might be shared next SlowUpdate
SResourcePack resOverflow; //< accumulates overflow over a gameframe
SResourcePack resSent, resPrevSent;
SResourcePack resReceived, resPrevReceived;
SResourcePack resPrevExcess;
Expand Down
6 changes: 6 additions & 0 deletions rts/Sim/Misc/TeamHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ void CTeamHandler::SetDefaultStartPositions(const CGameSetup* setup)
void CTeamHandler::GameFrame(int frameNum)
{
RECOIL_DETAILED_TRACY_ZONE;

for (int a = 0; a < ActiveTeams(); ++a) {
// a bit of a callin mismatch but teamHandler runs ~last within a GameFrame anyway
teams[a].GameFramePost(frameNum);
Comment thread
sprunk marked this conversation as resolved.
}

if ((frameNum % TEAM_SLOWUPDATE_RATE) != 0)
return;

Expand Down
3 changes: 3 additions & 0 deletions rts/System/EventClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct BuildInfo;
struct FeatureDef;
class LuaMaterial;
struct WeaponDef;
struct SResourcePack;

#ifndef zipFile
// might be defined through zip.h already
Expand Down Expand Up @@ -122,6 +123,8 @@ class CEventClient

virtual void TeamDied(int teamID) {}
virtual void TeamChanged(int teamID) {}
virtual bool TeamResourceExcess(int teamID, const SResourcePack& excess) { return false; }

virtual void PlayerChanged(int playerID) {}
virtual void PlayerAdded(int playerID) {}
virtual void PlayerRemoved(int playerID, int reason) {}
Expand Down
6 changes: 6 additions & 0 deletions rts/System/EventHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,12 @@ void CEventHandler::TeamDied(int teamID)
ITERATE_EVENTCLIENTLIST(TeamDied, teamID);
}

bool CEventHandler::TeamResourceExcess(int teamID, const SResourcePack &excess)
{
ZoneScoped;
return ControlIterateDefFalse(listTeamResourceExcess, &CEventClient::TeamResourceExcess, teamID, excess);
}

void CEventHandler::TeamChanged(int teamID)
{
ZoneScoped;
Expand Down
3 changes: 3 additions & 0 deletions rts/System/EventHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct Command;
struct BuildInfo;
class LuaMaterial;
struct WeaponDef;
struct SResourcePack;

class CEventHandler
{
Expand Down Expand Up @@ -60,6 +61,8 @@ class CEventHandler

void TeamDied(int teamID);
void TeamChanged(int teamID);
bool TeamResourceExcess(int teamID, const SResourcePack& excess);

void PlayerChanged(int playerID);
void PlayerAdded(int playerID);
void PlayerRemoved(int playerID, int reason);
Expand Down
3 changes: 3 additions & 0 deletions rts/System/Events.def
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@
SETUP_EVENT(GamePaused, MANAGED_BIT)
SETUP_EVENT(GameFrame, MANAGED_BIT)
SETUP_EVENT(GameFramePost, MANAGED_BIT)

SETUP_EVENT(TeamDied, MANAGED_BIT)
SETUP_EVENT(TeamChanged, MANAGED_BIT)
SETUP_EVENT(TeamResourceExcess, MANAGED_BIT | CONTROL_BIT)

SETUP_EVENT(PlayerChanged, MANAGED_BIT | UNSYNCED_BIT)
SETUP_EVENT(PlayerAdded, MANAGED_BIT | UNSYNCED_BIT)
SETUP_EVENT(PlayerRemoved, MANAGED_BIT | UNSYNCED_BIT)
Expand Down