refactor(cb): 컨트롤러 횡단 관심사 모듈 분리 (이동·본문 무변경)

화면 전환·NPC·포지션 관심사를 state.mjs/render.mjs/runend.mjs에서
전용 모듈로 분리. 런타임은 단일 SlayDeckController codeblock 유지.

- state.mjs → screens.mjs 개명 (화면 라우팅·버튼 바인딩)
- npc.mjs 신규: OnLobbyNpcInteract
- navigation.mjs 신규: GoLobbyMap·TeleportToActMap (월드 텔레포트)
- layout.mjs 신규: PositionMonsterSlot (UI 슬롯 배치)
- gen-slaydeck.mjs import·spread 갱신

검증: tools/verify/cbset.mjs (순서 무관 집합 비교) = 189/189 무손실,
본문/exec/params 변경 0. cbgap GAP 0, 테스트 93/93.
산출물 재생성(SlayDeckController.codeblock) 포함 — 메서드 순서만 바뀜.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-26 18:35:51 +09:00
parent 7b5e79bcf2
commit 8d2e320d60
9 changed files with 691 additions and 627 deletions

View File

@@ -1342,44 +1342,6 @@
"Attributes": [],
"Name": "ShowLobby"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "self.LobbyTpTries = 0\nlocal eventId = 0\nlocal function go()\n\tself.LobbyTpTries = self.LobbyTpTries + 1\n\tlocal lp = _UserService.LocalPlayer\n\tif lp ~= nil then\n\t\tif lp.CurrentMapName ~= \"lobby\" then\n\t\t\t_TeleportService:TeleportToMapPosition(lp, Vector3(-5, 0.03, 0), \"lobby\")\n\t\tend\n\t\t_TimerService:ClearTimer(eventId)\n\telseif self.LobbyTpTries > 50 then\n\t\t_TimerService:ClearTimer(eventId)\n\tend\nend\neventId = _TimerService:SetTimerRepeat(go, 0.1)",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "GoLobbyMap"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "string",
"DefaultValue": "\"\"",
"SyncDirection": 0,
"Attributes": [],
"Name": "id"
}
],
"Code": "if self.RunActive == true then\n\treturn\nend\nif id == \"run\" then\n\tself:ShowCharacterSelect()\nelseif id == \"codex\" then\n\tself:ShowCodex()\nelseif id == \"shop\" then\n\tself:ShowSoulShop()\nelseif id == \"board\" then\n\tself:ShowBoard()\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "OnLobbyNpcInteract"
},
{
"Return": {
"Type": "void",
@@ -1455,6 +1417,59 @@
"Attributes": [],
"Name": "CloseBoard"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "string",
"DefaultValue": "\"\"",
"SyncDirection": 0,
"Attributes": [],
"Name": "id"
}
],
"Code": "if self.RunActive == true then\n\treturn\nend\nif id == \"run\" then\n\tself:ShowCharacterSelect()\nelseif id == \"codex\" then\n\tself:ShowCodex()\nelseif id == \"shop\" then\n\tself:ShowSoulShop()\nelseif id == \"board\" then\n\tself:ShowBoard()\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "OnLobbyNpcInteract"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "self.LobbyTpTries = 0\nlocal eventId = 0\nlocal function go()\n\tself.LobbyTpTries = self.LobbyTpTries + 1\n\tlocal lp = _UserService.LocalPlayer\n\tif lp ~= nil then\n\t\tif lp.CurrentMapName ~= \"lobby\" then\n\t\t\t_TeleportService:TeleportToMapPosition(lp, Vector3(-5, 0.03, 0), \"lobby\")\n\t\tend\n\t\t_TimerService:ClearTimer(eventId)\n\telseif self.LobbyTpTries > 50 then\n\t\t_TimerService:ClearTimer(eventId)\n\tend\nend\neventId = _TimerService:SetTimerRepeat(go, 0.1)",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "GoLobbyMap"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "local maps = { \"map01\", \"map02\", \"map03\", \"map04\", \"map05\" }\nlocal target = maps[self.Floor]\nif target == nil then\n\treturn\nend\nlocal lp = _UserService.LocalPlayer\nif lp == nil then\n\treturn\nend\nif lp.CurrentMapName == target then\n\treturn\nend\n_TeleportService:TeleportToMapPosition(lp, Vector3(-6, 0.03, 0), target)",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "TeleportToActMap"
},
{
"Return": {
"Type": "void",
@@ -3937,21 +3952,6 @@
"Attributes": [],
"Name": "SetJob"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "local maps = { \"map01\", \"map02\", \"map03\", \"map04\", \"map05\" }\nlocal target = maps[self.Floor]\nif target == nil then\n\treturn\nend\nlocal lp = _UserService.LocalPlayer\nif lp == nil then\n\treturn\nend\nif lp.CurrentMapName == target then\n\treturn\nend\n_TeleportService:TeleportToMapPosition(lp, Vector3(-6, 0.03, 0), target)",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "TeleportToActMap"
},
{
"Return": {
"Type": "void",
@@ -4230,29 +4230,6 @@
"Attributes": [],
"Name": "SetHpBar"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "number",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "slot"
}
],
"Code": "local m = self.Monsters[slot]\nif m == nil or m.entity == nil or not isvalid(m.entity) then\n\treturn\nend\nlocal tr = m.entity.TransformComponent\nif tr == nil then\n\treturn\nend\nlocal wp = tr.WorldPosition\nlocal screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + 1.4))\nlocal uipos = _UILogic:ScreenToUIPosition(screen)\nlocal e = _EntityService:GetEntityByPath(\"/ui/RunUIGroup/CombatHud/MonsterStatus\" .. tostring(slot))\nif e ~= nil and e.UITransformComponent ~= nil then\n\te.UITransformComponent.anchoredPosition = uipos\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "PositionMonsterSlot"
},
{
"Return": {
"Type": "void",
@@ -4291,6 +4268,29 @@
"Attributes": [],
"Name": "RenderRun"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "number",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "slot"
}
],
"Code": "local m = self.Monsters[slot]\nif m == nil or m.entity == nil or not isvalid(m.entity) then\n\treturn\nend\nlocal tr = m.entity.TransformComponent\nif tr == nil then\n\treturn\nend\nlocal wp = tr.WorldPosition\nlocal screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + 1.4))\nlocal uipos = _UILogic:ScreenToUIPosition(screen)\nlocal e = _EntityService:GetEntityByPath(\"/ui/RunUIGroup/CombatHud/MonsterStatus\" .. tostring(slot))\nif e ~= nil and e.UITransformComponent ~= nil then\n\te.UITransformComponent.anchoredPosition = uipos\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "PositionMonsterSlot"
},
{
"Return": {
"Type": "any",