refactor: move /take and /give to LUA#2423
Conversation
sprunk
left a comment
There was a problem hiding this comment.
Needs a replacement Lua gadget to be put into examples or basecontent.
This was our conversation about a proxy to preserve /take or am I misunderstanding? I believe this comment is resolved. |
|
Removing draft from this PR since I believe it is now ready for testing/review. |
- Add TakeActionExecutor class to handle /take command forwarding - Register /take command in synced_commands.json to forward to Lua - Remove old C++ /take command implementation - Improve modularity by delegating command logic to Lua gadgets This change allows the /take command to be implemented in Lua for better modularity and easier maintenance, while maintaining the same user interface.
Gave C++ its own enum for only the transfer types it is responsible for. LUA handles the rest and C++ simply passes everything through the appropriate hooks
| int LuaSyncedCtrl::TransferUnit(lua_State* L) | ||
| { | ||
| CheckAllowGameChanges(L); | ||
| const int args = lua_gettop(L); |
There was a problem hiding this comment.
This is a breaking change, in general we avoid breaking changes.
We'd instead make a new overload (in the documentation) that accepts the new type, and mark the previous as deprecated.
The old method would still work.
There was a problem hiding this comment.
This function should be 100% untouched.
There was a problem hiding this comment.
So I do think we should eventually deprecate the existing hook. capture is a useless parameter compared with reason.
There was a problem hiding this comment.
It can be deprecated when capture handling is moved to Lua.
| #include "Sim/Units/Scripts/LuaUnitScript.h" | ||
|
|
||
| // for profiler | ||
| #include "System/TimeProfiler.h" |
There was a problem hiding this comment.
No sorry this was a me profiling during testing.
| // capture failed | ||
| if (team == gu->myTeam) { | ||
| LOG_L(L_WARNING, "%s: Capture failed, unit type limit reached", unitDef->humanName.c_str()); | ||
| eventHandler.LastMessagePosition(pos); |
There was a problem hiding this comment.
Is the removal of a callin invocation intended? (the new one does not contain it)
There was a problem hiding this comment.
Removing LastMessagePosition is probably ok, adding UnitTaken isn't. Generally leave the UnitBla callins as they were.
| "description" : "Fast-forwards to a given frame, or stops fast-forwarding" | ||
| }, | ||
| "take" : { | ||
| "spectator" : { |
There was a problem hiding this comment.
these two files are automatically generated, they are only committed within the repository to provide some default data to site (when the user does not perform the task to refresh them).
| class GiveActionExecutor : public ISyncedActionExecutor { | ||
| public: | ||
| GiveActionExecutor() : ISyncedActionExecutor( | ||
| "Give", |
There was a problem hiding this comment.
Mark it as deprecated in the description recommending the alternative instead.
| TakeActionExecutor() : ISyncedActionExecutor( | ||
| "Take", | ||
| "Transfers all units of allied teams without any " | ||
| "active players to the team of the issuing player" |
There was a problem hiding this comment.
Mark it as deprecated in the description recommending the alternative instead.
| // For the full list of reasons, see 'GG.CHANGETEAM_REASON' in luarules/gadgets.lua | ||
| // The two enums should be kept in sync for shared values. | ||
| enum class ChangeTeamReasonCpp { | ||
| RECLAIMED = 0, |
There was a problem hiding this comment.
"Reclaim" is already the term for gathering resources from wrecks.
I don't think this needs to introduce a new value since the engine shouldn't do anything about it anyway.
| ChangeGiven, | ||
| ChangeCaptured | ||
| // C++-side reasons for changing team. | ||
| // For the full list of reasons, see 'GG.CHANGETEAM_REASON' in luarules/gadgets.lua |
There was a problem hiding this comment.
Engine generally shouldn't refer to Lua (even if it provides examples of its own). This is because Lua is 100% replaceable (i.e. there may not be GG.CHANGETEAM_REASON, a GG table, or even gadgets.lua for any particular game). If Lua gets to define something then it's none of engine's business, and if engine has to define it then that is the source of truth and it is Lua who should refer to the engine.
There was a problem hiding this comment.
Hmm, yeah. It is just a pass through, but the engine does refer to this enum a few places and the values match. But your point is taken. What is the best way to expose this to LUA so it is upstream.
There was a problem hiding this comment.
The enum should be kept as-is, AFAICT its only use is to pick which of the two irrelevant stats this affects, "units sent" or "units outcaptured". These stats are a larger topic, see #2041 but the tl;dr is that we can't add a 3rd stat anyway for protocol reasons, and they would ideally be moved to Lua sometime anyway.
RecoilEngine/rts/Sim/Misc/Team.cpp
Lines 440 to 445 in a9bd9de
Lua doesn't need to have the reason passed via the callin, see #2423 (comment)
| { | ||
| ZoneScoped; | ||
|
|
||
| bool allow = true; |
There was a problem hiding this comment.
result.first and result.second are much worse names than allow and drop.
| if (oldTeam == newTeam) | ||
| return true; |
There was a problem hiding this comment.
Is this just for the factory buildee transfer?
There was a problem hiding this comment.
I put it in a state with logging in it where I noticed it was getting called a LOT, so wanted to add a guard clause to save some pointless work.
| * @return false to disallow unit transfer | ||
| */ | ||
| bool CSyncedLuaHandle::AllowUnitTransfer(const CUnit* unit, int newTeam, bool capture) | ||
| bool CSyncedLuaHandle::AllowUnitTransfer(const CUnit* unit, int newTeam, int reason) |
There was a problem hiding this comment.
This function should also be 100% untouched.
There was a problem hiding this comment.
hmm, that was a key reason for this patch. It allows us to have better information in downstream widgets to make decisions about allowing unit transfer.
There was a problem hiding this comment.
How about this? Should work without any engine changes.
-- take_gadget.lua
function HandleTakeRequest()
-- ...
Spring.SetUnitRulesParam(unitID, "transfer_reason", "take")
Spring.TransferUnit(unitID, teamID)
Spring.SetUnitRulesParam(unitID, "transfer_reason", nil)-- another_wupget.lua
function wupget:UnitTaken(unitID, ..., capture) -- or gadget:AllowUnitTransfer
local reason = Spring.GetUnitRulesParam(unitID, "transfer_reason")
if reason == "take" then
-- ...
elseif reason == "betrayal" then
-- ...
elseif reason == nil then
if capture then
-- engine capture mechanic
else
-- transfer request from a player
end
-- alternatively, a very early layer gadget could inject these two as reasons in AllowTransfer if it doesn't find any, so that it's never nil anywhere else
end
endIf you want a master list accessible to both widgets and gadgets, do something like this
-- master_list_gadget.lua
function Initialize()
-- not yet supported, see engine #1057
-- Spring.SetGameRulesParam("transfer_reasons", {"take", "betrayal"})
-- current workaround, manual enumeration
Spring.SetGameRulesParam("transfer_reasons_n", 2)
Spring.SetGameRulesParam("transfer_reasons_1", "take")
Spring.SetGameRulesParam("transfer_reasons_2", "betrayal")
Sorry, what I meant was that something similar to |
This allows building on Apple Silicon Macs by automatically detecting ARM64 and using --platform linux/amd64 for Docker commands.
|
TeamTransferWithReason can be (and should be, because the engine doesn't do anything meaningful with the reason) in Lua, see #2423 (comment). At the moment I don't think there's any engine change needed to add Lua |
I figure we want it to match the actual best-implementation we implement in bar. Should probably include the gadget hander stuff
- Remove prompts/team_transfer/ directory (13,341+ lines of explanatory content) - Remove examples/lua2cpp_example.lua and lua2cpp_output.cpp (auto-generated examples) - Remove cont/base/springcontent/LuaGadgets/Gadgets/team_transfer.lua (example implementation) - Preserve core team transfer deprecation/fallback functionality in C++ files - Keep auto-generated synced_commands.json changes for take/capture commands This creates a clean functional branch with only the intentional team transfer deprecation and fallback changes, removing all explanatory and example content. Co-Authored-By: Keith Harvey <keithdanielharvey@gmail.com>
cleanup: remove noise files and auto-generated content
| @@ -133,6 +133,9 @@ progress.make | |||
| /installer/Springlobby/ | |||
| /installer/*.exe | |||
|
|
|||
| @@ -266,11 +266,12 @@ end | |||
| -------------------------------------------------------------------------------- | |||
| -------------------------------------------------------------------------------- | |||
There was a problem hiding this comment.
revert all of the cont/base/springcontent changes
| @@ -1137,9 +1137,9 @@ function gadgetHandler:AllowUnitCreation(unitDefID, builderID, builderTeam, x, y | |||
| end | |||
|
|
|||
|
|
|||
There was a problem hiding this comment.
I think we just delete this. We don't need it downstream in BAR. SO just keep the deprecated call and delete this reason based one.
|
My hunt for ChangeTeamReason led me to realize all of these code paths were related and that all transfers should be handled by LUA. This simplifies things greatly on the engine side, and doing it piecemeal seemed harder since the test grid was already huge, even for extremely limited engine changes to transfers. Closing this in favor of the new PR, which has the new focus: #2528 |
Work done
reasonpass through for both ChangeTeam and AllowUnitTransfer, with the engine. The engine retains knowledge of only the ChangeTeam actions it initiates with its own enum.This change allows the /take command to be implemented in Lua for better modularity and easier maintenance, while maintaining the same user interface. It also adds a reason to pass through to AllowUnitTransfer.
Testing
Ensured /take still worked in skirmish