Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a test task with some other debug stuff
Browse files Browse the repository at this point in the history
lL1l1 committed Dec 21, 2024
1 parent 26f48f1 commit b5509fa
Showing 3 changed files with 206 additions and 3 deletions.
105 changes: 105 additions & 0 deletions lua/sim/tasks/TestTask.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@

local ScriptTask = import("/lua/sim/scripttask.lua").ScriptTask
local TASKSTATUS = import("/lua/sim/scripttask.lua").TASKSTATUS
local AIRESULT = import("/lua/sim/scripttask.lua").AIRESULT

-- You can issue this task by using:
-- IssueCommand("UNITCOMMAND_Script", { TaskName = "TestTask", Wait = Random(4)*7 }, false)
-- IssueUnitCommand(GetSelectedUnits(), "UNITCOMMAND_Script", { TaskName = "TestTask", Wait = Random(4)*7 }, false)
-- import('/lua/ui/game/commandmode.lua').StartCommandMode('order', { name = "RULEUCC_Script", TaskName = "TestTask" }) -- Note: `UserScriptCommand` overwrites the LuaParams table, so Wait can't be used.
-- or Sim-Side:
-- IssueScript(SelectedUnit(), { TaskName = "TestTask", Wait = Random(4)*7 })

---@class TestTask : ScriptTask
---@field CommandData { TaskName: "TestTask", Wait: number, tailCall?: true } # LuaParams table from the user side. This table is shared by all units ordered the task from one command.
---@field Wait number\
---@field tailCall? true
---@field unitId EntityId # self:GetUnit():GetEntityId()
TestTask = Class(ScriptTask) {

--- Called immediately when task is created
--- Initialize lua param wait times
---@param self TestTask
---@param commandData { TaskName: TestTask, Wait: number } # LuaParams table from the user side. This table is shared by all units ordered the task from one command.
OnCreate = function (self, commandData)
ScriptTask.OnCreate(self, commandData)
LOG(('task %s for unit %s started at tick %d, waiting for %d ticks (until tick %d)'):format(
tostring(self)
, tostring(self.unitId)
, GetGameTick()
, (commandData.Wait or 5)
, GetGameTick() + (commandData.Wait or 5)
))
self.Wait = commandData.Wait or 5
self.unitId = self:GetUnit():GetEntityId()
LOG(repr(commandData))
-- LOG(repr(self, {meta = true}))

-- self:GetUnit():SetBusy(true)
-- self:GetUnit():SetBlockCommandQueue(true)

-- if self.Wait >= 2 then
-- IssueScript({self:GetUnit()}, { TaskName = 'TestTask', Wait = self.Wait - 1 })
-- end

end,

--- Called by the engine every tick. Function must return a value in TaskStatus
---@param self TestTask
---@return ScriptTaskStatus
TaskTick = function(self)
-- "tail call" example: this isn't a true tail call because the queue isn't guaranteed to be empty,
-- so execution may not go to the next issued command unless the command queue is cleared first

-- if not self.CommandData.tailCall then
-- -- IssueScript({ self:GetUnit() }, { TaskName = "TestTask", Wait = self.Wait, tailCall = true })
-- self.CommandData.tailCall = true

-- LOG(repr(self, {meta = true}))

-- -- ForkThread(function(u)
-- -- while not IsDestroyed(u) do
-- -- u:DebugPrintCurrentStates()
-- -- WaitTicks(1)
-- -- end
-- -- end, self:GetUnit())

-- return TASKSTATUS.Done
-- end

local wait = self.Wait

if wait == TASKSTATUS.Done then
self:GetUnit():DebugToggleTrackingStateChanges()

-- if GetGameTick() > self.delaytick then
-- LOG(('task %s for unit %s ended at tick %d with an actual delay'):format(tostring(self), tostring(self.unitId), GetGameTick()))
-- end

LOG(('task %s for unit %s ended at tick %d'):format(tostring(self), tostring(self.unitId), GetGameTick()))

return wait
elseif wait == TASKSTATUS.Delay then
self.Wait = TASKSTATUS.Done
self.delaytick = GetGameTick()
-- LOG(('task %s delayed at tick %d'):format(tostring(self), GetGameTick()))

return wait
else
self.Wait = TASKSTATUS.Done
-- LOG(('task %s waited at tick %d until %d'):format(tostring(self), GetGameTick(), GetGameTick() + wait - 1))
return wait
end
end,

--- Called by the engine when the task is destroyed. This could be it naturally going away after completion or because it was cancelled by another task.
---@param self TestTask
OnDestroy = function(self)
LOG(('task %s destroyed at tick %d'):format(tostring(self), GetGameTick()))

-- self:GetUnit():SetBusy(false)
-- self:GetUnit():SetBlockCommandQueue(false)

self:SetAIResult(AIRESULT.Success)
end,
}
89 changes: 89 additions & 0 deletions lua/sim/units/components/DebugUnitComponent.lua
Original file line number Diff line number Diff line change
@@ -22,6 +22,67 @@

local DebugComponent = import("/lua/shared/components/DebugComponent.lua").DebugComponent

---@type UnitState[]
local possibleUnitStates = {
"Immobile",
"Moving",
"Attacking",
"Guarding",
"Building",
"Upgrading",
"WaitingForTransport",
"TransportLoading",
"TransportUnloading",
"MovingDown",
"MovingUp",
"Patrolling",
"Busy",
"Attached",
"BeingReclaimed",
"Repairing",
"Diving",
"Surfacing",
"Teleporting",
"Ferrying",
"WaitForFerry",
"AssistMoving",
"PathFinding",
"ProblemGettingToGoal",
"NeedToTerminateTask",
"Capturing",
"BeingCaptured",
"Reclaiming",
"AssistingCommander",
"Refueling",
"GuardBusy",
"ForceSpeedThrough",
"UnSelectable",
"DoNotTarget",
"LandingOnPlatform",
"CannotFindPlaceToLand",
"BeingUpgraded",
"Enhancing",
"BeingBuilt",
"NoReclaim",
"NoCost",
"BlockCommandQueue",
"MakingAttackRun",
"HoldingPattern",
"SiloBuildingAmmo",
}

---@param unit Unit
---@return UnitState[] currentStates # Can be empty
local function GetStatesOfUnit(unit)
local currentStates = {}
for _, possibleState in possibleUnitStates do
if unit:IsUnitState(possibleState) then
table.insert(currentStates, possibleState)
end
end
return currentStates
end

---@class DebugUnitComponent : DebugComponent
DebugUnitComponent = Class(DebugComponent) {

@@ -118,4 +179,32 @@ DebugUnitComponent = Class(DebugComponent) {
local blueprint = self.Blueprint
DrawCircle(self:GetPosition(), math.max(blueprint.SizeX, blueprint.SizeY, blueprint.SizeZ), color)
end,

---@param self DebugUnitComponent | Unit
DebugPrintCurrentStates = function(self)
self:DebugLog(string.format("States at tick %d: %s", GetGameTick(), table.concat(GetStatesOfUnit(self), ', ')))
end,

---@param self DebugUnitComponent | Unit
DebugToggleTrackingStateChanges = function(self)
if not self.StateChangeTracker then
self.StateChangeTracker = self.Trash:Add(ForkThread(function()
local oldStatesHashed = {}
while true do
local newStates = GetStatesOfUnit(self)
local newStatesHashed = table.hash(GetStatesOfUnit(self))
for _, state in possibleUnitStates do
if newStatesHashed[state] ~= oldStatesHashed[state] then
self:DebugLog(string.format("New states at tick %d: %s", GetGameTick(), table.concat(newStates, ', ')))
end
end
oldStatesHashed = newStatesHashed
WaitTicks(1)
end
end))
else
KillThread(self.StateChangeTracker)
self.StateChangeTracker = nil
end
end,
}
15 changes: 12 additions & 3 deletions lua/system/repr.lua
Original file line number Diff line number Diff line change
@@ -182,7 +182,12 @@ function Inspector:getId(v)
if not id then
local tv = type(v)
id = (ids[tv] or 0) + 1
ids[v], ids[tv] = id, id
ids[tv] = id
if tv == "function" then
local info = debug.getinfo(v, "S")
id = fmt("%s %s(%d)", id, DiskToLocal(string.sub(info.source, 2)), info.linedefined)
end
ids[v] = id
end
return tostring(id)
end
@@ -223,7 +228,11 @@ function Inspector:putValue(v)
puts(buf, "]")
end
puts(buf, ' = ')
self:putValue(t[k])
if k == "__index" and tostring(t[k]) == tostring(t) then
puts(buf, string.format("{...} -- %s (%g bytes)", tostring(t), debug.allocatedsize(t)))
else
self:putValue(t[k])
end
end
end

@@ -249,7 +258,7 @@ function Inspector:putValue(v)
end

else
puts(buf, fmt('<%s %d>', tv, self:getId(v)))
puts(buf, fmt('<%s %s>', tv, self:getId(v)))
end
end

0 comments on commit b5509fa

Please sign in to comment.