From f715ad2176a29e85823166018572d084873885a5 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sat, 11 Jul 2026 20:37:28 -0500 Subject: [PATCH] Nuke it all --- CLAUDE.md | 455 --- README.md | 3 - assets/chunks/-1_0_0.dcf | Bin 2235 -> 0 bytes assets/chunks/0_0_0.dcf | Bin 2146 -> 0 bytes assets/chunks/0_1_0.dcf | Bin 2234 -> 0 bytes assets/chunks/1_0_0.dcf | Bin 2322 -> 0 bytes assets/chunks/1_1_0.dcf | Bin 2234 -> 0 bytes assets/chunks/2_0_0.dcf | Bin 2102 -> 0 bytes assets/locale/en_US.po | 66 - assets/locale/es_MX.po | 70 - assets/locale/jp_JP.po | 70 - assets/meshes/buildings/house_1_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_1_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_1_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_1_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_1_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_1_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_1_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_1_8.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_2_8.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_3_8.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_4_8.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_5_8.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_6_8.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_7_8.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_1.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_2.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_3.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_4.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_5.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_6.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_7.dmf | Bin 1332 -> 0 bytes assets/meshes/buildings/house_8_8.dmf | Bin 1332 -> 0 bytes assets/meshes/chunks/chunk_-1_0_0_0.dmf | Bin 26172 -> 0 bytes assets/meshes/chunks/chunk_0_0_0_0.dmf | Bin 28932 -> 0 bytes assets/meshes/chunks/chunk_0_1_0_0.dmf | Bin 25332 -> 0 bytes assets/meshes/chunks/chunk_1_0_0_0.dmf | Bin 27492 -> 0 bytes assets/meshes/chunks/chunk_1_1_0_0.dmf | Bin 26652 -> 0 bytes assets/meshes/chunks/chunk_2_0_0_0.dmf | Bin 30252 -> 0 bytes assets/models/buildings/house_1_1.json | 4 - assets/models/buildings/house_1_2.json | 4 - assets/models/buildings/house_1_3.json | 4 - assets/models/buildings/house_1_4.json | 4 - assets/models/buildings/house_1_5.json | 4 - assets/models/buildings/house_1_6.json | 4 - assets/models/buildings/house_1_7.json | 4 - assets/models/buildings/house_1_8.json | 4 - assets/models/buildings/house_2_1.json | 4 - assets/models/buildings/house_2_2.json | 4 - assets/models/buildings/house_2_3.json | 4 - assets/models/buildings/house_2_4.json | 4 - assets/models/buildings/house_2_5.json | 4 - assets/models/buildings/house_2_6.json | 4 - assets/models/buildings/house_2_7.json | 4 - assets/models/buildings/house_2_8.json | 4 - assets/models/buildings/house_3_1.json | 4 - assets/models/buildings/house_3_2.json | 4 - assets/models/buildings/house_3_3.json | 4 - assets/models/buildings/house_3_4.json | 4 - assets/models/buildings/house_3_5.json | 4 - assets/models/buildings/house_3_6.json | 4 - assets/models/buildings/house_3_7.json | 4 - assets/models/buildings/house_3_8.json | 4 - assets/models/buildings/house_4_1.json | 4 - assets/models/buildings/house_4_2.json | 4 - assets/models/buildings/house_4_3.json | 4 - assets/models/buildings/house_4_4.json | 4 - assets/models/buildings/house_4_5.json | 4 - assets/models/buildings/house_4_6.json | 4 - assets/models/buildings/house_4_7.json | 4 - assets/models/buildings/house_4_8.json | 4 - assets/models/buildings/house_5_1.json | 4 - assets/models/buildings/house_5_2.json | 4 - assets/models/buildings/house_5_3.json | 4 - assets/models/buildings/house_5_4.json | 4 - assets/models/buildings/house_5_5.json | 4 - assets/models/buildings/house_5_6.json | 4 - assets/models/buildings/house_5_7.json | 4 - assets/models/buildings/house_5_8.json | 4 - assets/models/buildings/house_6_1.json | 4 - assets/models/buildings/house_6_2.json | 4 - assets/models/buildings/house_6_3.json | 4 - assets/models/buildings/house_6_4.json | 4 - assets/models/buildings/house_6_5.json | 4 - assets/models/buildings/house_6_6.json | 4 - assets/models/buildings/house_6_7.json | 4 - assets/models/buildings/house_6_8.json | 4 - assets/models/buildings/house_7_1.json | 4 - assets/models/buildings/house_7_2.json | 4 - assets/models/buildings/house_7_3.json | 4 - assets/models/buildings/house_7_4.json | 4 - assets/models/buildings/house_7_5.json | 4 - assets/models/buildings/house_7_6.json | 4 - assets/models/buildings/house_7_7.json | 4 - assets/models/buildings/house_7_8.json | 4 - assets/models/buildings/house_8_1.json | 4 - assets/models/buildings/house_8_2.json | 4 - assets/models/buildings/house_8_3.json | 4 - assets/models/buildings/house_8_4.json | 4 - assets/models/buildings/house_8_5.json | 4 - assets/models/buildings/house_8_6.json | 4 - assets/models/buildings/house_8_7.json | 4 - assets/models/buildings/house_8_8.json | 4 - assets/models/chunks/chunk_-1_0_0_0.json | 10 - assets/models/chunks/chunk_0_0_0_0.json | 10 - assets/models/chunks/chunk_0_1_0_0.json | 10 - assets/models/chunks/chunk_1_0_0_0.json | 10 - assets/models/chunks/chunk_1_1_0_0.json | 10 - assets/models/chunks/chunk_2_0_0_0.json | 10 - assets/tiles.png | Bin 110 -> 0 bytes assetsraw/chunks/chunk_-1_0_0.json | 1992 ------------- assetsraw/chunks/chunk_0_0_0.json | 2183 -------------- assetsraw/chunks/chunk_0_1_0.json | 1929 ------------- assetsraw/chunks/chunk_1_0_0.json | 2107 -------------- assetsraw/chunks/chunk_1_1_0.json | 2028 ------------- assetsraw/chunks/chunk_2_0_0.json | 2543 ----------------- editor/client/public/common/chunkterrain.js | 159 -- editor/client/public/common/dmf.js | 64 - editor/client/public/index.html | 6 - editor/client/public/map/index.html | 92 - editor/client/public/map/map.css | 65 - editor/client/public/map/map.js | 918 ------ editor/client/public/map/renderer.js | 298 -- editor/client/public/template.html | 23 - editor/server/server.py | 295 -- editor/start.sh | 4 - src/dusk/CMakeLists.txt | 3 - src/dusk/asset/CMakeLists.txt | 1 - src/dusk/asset/asset.c | 4 - src/dusk/asset/assetbatch.c | 165 -- src/dusk/asset/assetbatch.h | 124 - src/dusk/asset/loader/CMakeLists.txt | 1 - src/dusk/asset/loader/assetentry.c | 17 - src/dusk/asset/loader/assetentry.h | 29 - src/dusk/asset/loader/assetloader.c | 6 - src/dusk/asset/loader/assetloader.h | 5 - src/dusk/asset/loader/chunk/CMakeLists.txt | 10 - .../asset/loader/chunk/assetchunkloader.c | 181 -- .../asset/loader/chunk/assetchunkloader.h | 70 - src/dusk/engine/engine.c | 10 - src/dusk/event/CMakeLists.txt | 9 - src/dusk/event/event.c | 76 - src/dusk/event/event.h | 64 - src/dusk/input/input.c | 22 - src/dusk/input/inputaction.h | 10 - src/dusk/locale/localeinfo.h | 4 + src/dusk/rpg/CMakeLists.txt | 20 - src/dusk/rpg/battle/CMakeLists.txt | 12 - src/dusk/rpg/battle/battle.c | 223 -- src/dusk/rpg/battle/battle.h | 194 -- src/dusk/rpg/battle/battlefighter.c | 43 - src/dusk/rpg/battle/battlefighter.h | 87 - src/dusk/rpg/battle/party.c | 71 - src/dusk/rpg/battle/party.h | 73 - src/dusk/rpg/cutscene/CMakeLists.txt | 13 - src/dusk/rpg/cutscene/cutscene.h | 232 -- src/dusk/rpg/cutscene/cutscenepause.h | 24 - src/dusk/rpg/cutscene/cutscenesystem.c | 157 - src/dusk/rpg/cutscene/cutscenesystem.h | 120 - src/dusk/rpg/cutscene/item/CMakeLists.txt | 17 - .../rpg/cutscene/item/battle/CMakeLists.txt | 9 - .../item/battle/cutscenestartbattle.c | 71 - .../item/battle/cutscenestartbattle.h | 53 - .../rpg/cutscene/item/control/CMakeLists.txt | 11 - .../item/control/cutsceneconcurrent.c | 46 - .../item/control/cutsceneconcurrent.h | 62 - .../cutscene/item/control/cutscenesetpause.c | 23 - .../cutscene/item/control/cutscenesetpause.h | 35 - .../rpg/cutscene/item/control/cutscenewait.c | 24 - .../rpg/cutscene/item/control/cutscenewait.h | 38 - src/dusk/rpg/cutscene/item/cutscenecallback.c | 23 - src/dusk/rpg/cutscene/item/cutscenecallback.h | 37 - src/dusk/rpg/cutscene/item/cutsceneitem.c | 152 - src/dusk/rpg/cutscene/item/cutsceneitem.h | 163 -- .../rpg/cutscene/item/entity/CMakeLists.txt | 14 - .../cutscene/item/entity/cutsceneentityadd.c | 33 - .../cutscene/item/entity/cutsceneentityadd.h | 41 - .../item/entity/cutsceneentityremove.c | 25 - .../item/entity/cutsceneentityremove.h | 39 - .../item/entity/cutsceneentityteleport.c | 27 - .../item/entity/cutsceneentityteleport.h | 40 - .../cutscene/item/entity/cutsceneentityturn.c | 30 - .../cutscene/item/entity/cutsceneentityturn.h | 42 - .../item/entity/cutsceneentitywalkto.c | 36 - .../item/entity/cutsceneentitywalkto.h | 46 - .../item/entity/cutsceneentitywalktoentity.c | 41 - .../item/entity/cutsceneentitywalktoentity.h | 46 - .../rpg/cutscene/item/item/CMakeLists.txt | 9 - .../rpg/cutscene/item/item/cutsceneitemgive.c | 24 - .../rpg/cutscene/item/item/cutsceneitemgive.h | 40 - .../rpg/cutscene/item/maparea/CMakeLists.txt | 11 - .../item/maparea/cutscenemapareaadd.c | 29 - .../item/maparea/cutscenemapareaadd.h | 44 - .../item/maparea/cutscenemaparearemove.c | 24 - .../item/maparea/cutscenemaparearemove.h | 40 - .../item/maparea/cutscenemapareawait.c | 40 - .../item/maparea/cutscenemapareawait.h | 49 - src/dusk/rpg/cutscene/item/ui/CMakeLists.txt | 14 - src/dusk/rpg/cutscene/item/ui/cutsceneemoji.c | 25 - src/dusk/rpg/cutscene/item/ui/cutsceneemoji.h | 43 - src/dusk/rpg/cutscene/item/ui/cutscenefade.c | 32 - src/dusk/rpg/cutscene/item/ui/cutscenefade.h | 43 - src/dusk/rpg/cutscene/item/ui/cutsceneshake.c | 23 - src/dusk/rpg/cutscene/item/ui/cutsceneshake.h | 41 - src/dusk/rpg/cutscene/item/ui/cutscenetext.c | 23 - src/dusk/rpg/cutscene/item/ui/cutscenetext.h | 41 - .../rpg/cutscene/item/ui/cutscenetextmini.c | 33 - .../rpg/cutscene/item/ui/cutscenetextmini.h | 44 - .../cutscene/item/ui/cutscenetextminihide.c | 25 - .../cutscene/item/ui/cutscenetextminihide.h | 39 - src/dusk/rpg/cutscene/scene/testcutscene.h | 31 - src/dusk/rpg/entity/CMakeLists.txt | 19 - src/dusk/rpg/entity/anim/CMakeLists.txt | 13 - src/dusk/rpg/entity/anim/entityanim.c | 44 - src/dusk/rpg/entity/anim/entityanim.h | 46 - src/dusk/rpg/entity/anim/entityanimidle.c | 17 - src/dusk/rpg/entity/anim/entityanimidle.h | 18 - src/dusk/rpg/entity/anim/entityanimrun.c | 24 - src/dusk/rpg/entity/anim/entityanimrun.h | 21 - src/dusk/rpg/entity/anim/entityanimturn.c | 17 - src/dusk/rpg/entity/anim/entityanimturn.h | 21 - src/dusk/rpg/entity/anim/entityanimwalk.c | 24 - src/dusk/rpg/entity/anim/entityanimwalk.h | 22 - src/dusk/rpg/entity/entity.c | 316 -- src/dusk/rpg/entity/entity.h | 167 -- src/dusk/rpg/entity/entitydir.c | 51 - src/dusk/rpg/entity/entitydir.h | 54 - src/dusk/rpg/entity/entitypathstep.c | 59 - src/dusk/rpg/entity/entitypathstep.h | 26 - src/dusk/rpg/entity/entitytype.h | 62 - src/dusk/rpg/entity/global/CMakeLists.txt | 9 - src/dusk/rpg/entity/global/entityglobal.h | 17 - src/dusk/rpg/entity/global/entityglobaldefs.h | 44 - src/dusk/rpg/entity/global/entitygloballist.h | 30 - src/dusk/rpg/entity/interact/CMakeLists.txt | 9 - src/dusk/rpg/entity/interact/entityinteract.c | 58 - src/dusk/rpg/entity/interact/entityinteract.h | 53 - src/dusk/rpg/entity/item/CMakeLists.txt | 10 - src/dusk/rpg/entity/item/entityitem.c | 44 - src/dusk/rpg/entity/item/entityitem.h | 56 - src/dusk/rpg/entity/npc/CMakeLists.txt | 13 - src/dusk/rpg/entity/npc/npc.c | 60 - src/dusk/rpg/entity/npc/npc.h | 81 - src/dusk/rpg/entity/npc/npcpath.c | 43 - src/dusk/rpg/entity/npc/npcpath.h | 44 - src/dusk/rpg/entity/npc/npcturn.c | 27 - src/dusk/rpg/entity/npc/npcturn.h | 36 - src/dusk/rpg/entity/npc/npcwalk.c | 52 - src/dusk/rpg/entity/npc/npcwalk.h | 54 - src/dusk/rpg/entity/player.c | 101 - src/dusk/rpg/entity/player.h | 52 - src/dusk/rpg/item/CMakeLists.txt | 22 - src/dusk/rpg/item/backpack.c | 79 - src/dusk/rpg/item/backpack.h | 97 - src/dusk/rpg/item/inventory.c | 250 -- src/dusk/rpg/item/inventory.h | 123 - src/dusk/rpg/item/item.c | 30 - src/dusk/rpg/item/item.h | 24 - src/dusk/rpg/item/item.json | 5 - src/dusk/rpg/item/itemgive.c | 32 - src/dusk/rpg/item/itemgive.h | 20 - src/dusk/rpg/overworld/CMakeLists.txt | 16 - src/dusk/rpg/overworld/chunk.c | 16 - src/dusk/rpg/overworld/chunk.h | 48 - src/dusk/rpg/overworld/map.c | 438 --- src/dusk/rpg/overworld/map.h | 177 -- src/dusk/rpg/overworld/maparea.c | 150 - src/dusk/rpg/overworld/maparea.h | 161 -- src/dusk/rpg/overworld/tile.c | 8 - src/dusk/rpg/overworld/tile.h | 20 - src/dusk/rpg/overworld/tileshape.c | 39 - src/dusk/rpg/overworld/tileshape.h | 45 - src/dusk/rpg/overworld/worldpos.c | 98 - src/dusk/rpg/overworld/worldpos.h | 104 - src/dusk/rpg/rpg.c | 111 - src/dusk/rpg/rpg.h | 34 - src/dusk/rpg/rpgcamera.c | 134 - src/dusk/rpg/rpgcamera.h | 94 - src/dusk/rpg/story/CMakeLists.txt | 19 - src/dusk/rpg/story/storyflag.c | 14 - src/dusk/rpg/story/storyflag.csv | 2 - src/dusk/rpg/story/storyflag.h | 25 - src/dusk/rpg/story/storyflagdefs.h | 11 - src/dusk/save/CMakeLists.txt | 11 - src/dusk/save/save.c | 108 - src/dusk/save/save.h | 74 - src/dusk/save/savefile.h | 30 - src/dusk/save/savestream.c | 340 --- src/dusk/save/savestream.h | 468 --- src/dusk/scene/CMakeLists.txt | 6 +- src/dusk/scene/battle/CMakeLists.txt | 9 - src/dusk/scene/battle/scenebattle.c | 26 - src/dusk/scene/battle/scenebattle.h | 46 - src/dusk/scene/overworld/CMakeLists.txt | 9 - src/dusk/scene/overworld/sceneoverworld.c | 262 -- src/dusk/scene/overworld/sceneoverworld.h | 149 - src/dusk/scene/scenetype.c | 14 - src/dusk/scene/scenetype.h | 8 +- src/dusk/ui/CMakeLists.txt | 3 - src/dusk/ui/debug/CMakeLists.txt | 1 - src/dusk/ui/debug/uiplayerpos.c | 48 - src/dusk/ui/debug/uiplayerpos.h | 18 - src/dusk/ui/frame/CMakeLists.txt | 15 - src/dusk/ui/frame/backpack/CMakeLists.txt | 9 - src/dusk/ui/frame/backpack/uibackpack.c | 116 - src/dusk/ui/frame/backpack/uibackpack.h | 65 - src/dusk/ui/frame/battle/CMakeLists.txt | 9 - src/dusk/ui/frame/battle/uibattlemenu.c | 137 - src/dusk/ui/frame/battle/uibattlemenu.h | 57 - src/dusk/ui/frame/game/CMakeLists.txt | 9 - src/dusk/ui/frame/game/uigamemenu.c | 106 - src/dusk/ui/frame/game/uigamemenu.h | 62 - src/dusk/ui/frame/settings/CMakeLists.txt | 13 - src/dusk/ui/frame/settings/uisettings.c | 250 -- src/dusk/ui/frame/settings/uisettings.h | 133 - src/dusk/ui/frame/settings/uisettingsaudio.c | 47 - src/dusk/ui/frame/settings/uisettingsaudio.h | 36 - src/dusk/ui/frame/settings/uisettingsdata.h | 67 - .../ui/frame/settings/uisettingsdisplay.c | 47 - .../ui/frame/settings/uisettingsdisplay.h | 36 - .../ui/frame/settings/uisettingsgeneral.c | 117 - .../ui/frame/settings/uisettingsgeneral.h | 36 - src/dusk/ui/frame/settings/uisettingsinput.c | 80 - src/dusk/ui/frame/settings/uisettingsinput.h | 36 - src/dusk/ui/frame/uiconfirm.c | 128 - src/dusk/ui/frame/uiconfirm.h | 94 - src/dusk/ui/frame/uiframe.c | 121 - src/dusk/ui/frame/uiframe.h | 64 - src/dusk/ui/overlay/CMakeLists.txt | 2 - src/dusk/ui/overlay/uifullbox.c | 122 - src/dusk/ui/overlay/uifullbox.h | 109 - src/dusk/ui/overlay/uiloading.c | 109 - src/dusk/ui/overlay/uiloading.h | 63 - src/dusk/ui/rpg/CMakeLists.txt | 12 - src/dusk/ui/rpg/textbox/CMakeLists.txt | 12 - src/dusk/ui/rpg/textbox/uitextbox.c | 244 -- src/dusk/ui/rpg/textbox/uitextbox.h | 138 - src/dusk/ui/rpg/textbox/uitextboxmain.c | 122 - src/dusk/ui/rpg/textbox/uitextboxmain.h | 94 - src/dusk/ui/rpg/textbox/uitextboxmini.c | 122 - src/dusk/ui/rpg/textbox/uitextboxmini.h | 116 - src/dusk/ui/rpg/textbox/uitextboxminilist.c | 40 - src/dusk/ui/rpg/textbox/uitextboxminilist.h | 44 - src/dusk/ui/rpg/uiemoji.c | 119 - src/dusk/ui/rpg/uiemoji.h | 66 - src/dusk/ui/transition/CMakeLists.txt | 10 - src/dusk/ui/transition/uitransition.c | 81 - src/dusk/ui/transition/uitransition.h | 74 - src/dusk/ui/transition/uitransitiondata.h | 23 - src/dusk/ui/transition/uitransitionfade.c | 56 - src/dusk/ui/transition/uitransitionfade.h | 29 - src/dusk/ui/uielement.c | 102 +- src/dusk/ui/widget/CMakeLists.txt | 2 - src/dusk/ui/widget/uiitem.c | 77 - src/dusk/ui/widget/uiitem.h | 89 - src/dusk/ui/widget/uiitemlist.c | 179 -- src/dusk/ui/widget/uiitemlist.h | 200 -- src/duskdolphin/CMakeLists.txt | 1 - src/duskdolphin/save/CMakeLists.txt | 11 - src/duskdolphin/save/savedolphin.c | 145 - src/duskdolphin/save/savedolphin.h | 68 - src/duskdolphin/save/saveplatform.h | 30 - src/duskdolphin/save/savestreamdolphin.c | 112 - src/duskdolphin/save/savestreamdolphin.h | 91 - src/dusklinux/CMakeLists.txt | 1 - src/dusklinux/save/CMakeLists.txt | 11 - src/dusklinux/save/savelinux.c | 84 - src/dusklinux/save/savelinux.h | 61 - src/dusklinux/save/saveplatform.h | 30 - src/dusklinux/save/savestreamlinux.c | 75 - src/dusklinux/save/savestreamlinux.h | 78 - src/duskpsp/CMakeLists.txt | 1 - src/duskpsp/save/CMakeLists.txt | 11 - src/duskpsp/save/saveplatform.h | 30 - src/duskpsp/save/savepsp.c | 81 - src/duskpsp/save/savepsp.h | 63 - src/duskpsp/save/savestreampsp.c | 77 - src/duskpsp/save/savestreampsp.h | 77 - src/duskvita/CMakeLists.txt | 1 - src/duskvita/save/CMakeLists.txt | 11 - src/duskvita/save/saveplatform.h | 30 - src/duskvita/save/savestreamvita.c | 77 - src/duskvita/save/savestreamvita.h | 78 - 425 files changed, 7 insertions(+), 31421 deletions(-) delete mode 100644 CLAUDE.md delete mode 100644 assets/chunks/-1_0_0.dcf delete mode 100644 assets/chunks/0_0_0.dcf delete mode 100644 assets/chunks/0_1_0.dcf delete mode 100644 assets/chunks/1_0_0.dcf delete mode 100644 assets/chunks/1_1_0.dcf delete mode 100644 assets/chunks/2_0_0.dcf delete mode 100644 assets/locale/en_US.po delete mode 100644 assets/locale/es_MX.po delete mode 100644 assets/locale/jp_JP.po delete mode 100644 assets/meshes/buildings/house_1_1.dmf delete mode 100644 assets/meshes/buildings/house_1_2.dmf delete mode 100644 assets/meshes/buildings/house_1_3.dmf delete mode 100644 assets/meshes/buildings/house_1_4.dmf delete mode 100644 assets/meshes/buildings/house_1_5.dmf delete mode 100644 assets/meshes/buildings/house_1_6.dmf delete mode 100644 assets/meshes/buildings/house_1_7.dmf delete mode 100644 assets/meshes/buildings/house_1_8.dmf delete mode 100644 assets/meshes/buildings/house_2_1.dmf delete mode 100644 assets/meshes/buildings/house_2_2.dmf delete mode 100644 assets/meshes/buildings/house_2_3.dmf delete mode 100644 assets/meshes/buildings/house_2_4.dmf delete mode 100644 assets/meshes/buildings/house_2_5.dmf delete mode 100644 assets/meshes/buildings/house_2_6.dmf delete mode 100644 assets/meshes/buildings/house_2_7.dmf delete mode 100644 assets/meshes/buildings/house_2_8.dmf delete mode 100644 assets/meshes/buildings/house_3_1.dmf delete mode 100644 assets/meshes/buildings/house_3_2.dmf delete mode 100644 assets/meshes/buildings/house_3_3.dmf delete mode 100644 assets/meshes/buildings/house_3_4.dmf delete mode 100644 assets/meshes/buildings/house_3_5.dmf delete mode 100644 assets/meshes/buildings/house_3_6.dmf delete mode 100644 assets/meshes/buildings/house_3_7.dmf delete mode 100644 assets/meshes/buildings/house_3_8.dmf delete mode 100644 assets/meshes/buildings/house_4_1.dmf delete mode 100644 assets/meshes/buildings/house_4_2.dmf delete mode 100644 assets/meshes/buildings/house_4_3.dmf delete mode 100644 assets/meshes/buildings/house_4_4.dmf delete mode 100644 assets/meshes/buildings/house_4_5.dmf delete mode 100644 assets/meshes/buildings/house_4_6.dmf delete mode 100644 assets/meshes/buildings/house_4_7.dmf delete mode 100644 assets/meshes/buildings/house_4_8.dmf delete mode 100644 assets/meshes/buildings/house_5_1.dmf delete mode 100644 assets/meshes/buildings/house_5_2.dmf delete mode 100644 assets/meshes/buildings/house_5_3.dmf delete mode 100644 assets/meshes/buildings/house_5_4.dmf delete mode 100644 assets/meshes/buildings/house_5_5.dmf delete mode 100644 assets/meshes/buildings/house_5_6.dmf delete mode 100644 assets/meshes/buildings/house_5_7.dmf delete mode 100644 assets/meshes/buildings/house_5_8.dmf delete mode 100644 assets/meshes/buildings/house_6_1.dmf delete mode 100644 assets/meshes/buildings/house_6_2.dmf delete mode 100644 assets/meshes/buildings/house_6_3.dmf delete mode 100644 assets/meshes/buildings/house_6_4.dmf delete mode 100644 assets/meshes/buildings/house_6_5.dmf delete mode 100644 assets/meshes/buildings/house_6_6.dmf delete mode 100644 assets/meshes/buildings/house_6_7.dmf delete mode 100644 assets/meshes/buildings/house_6_8.dmf delete mode 100644 assets/meshes/buildings/house_7_1.dmf delete mode 100644 assets/meshes/buildings/house_7_2.dmf delete mode 100644 assets/meshes/buildings/house_7_3.dmf delete mode 100644 assets/meshes/buildings/house_7_4.dmf delete mode 100644 assets/meshes/buildings/house_7_5.dmf delete mode 100644 assets/meshes/buildings/house_7_6.dmf delete mode 100644 assets/meshes/buildings/house_7_7.dmf delete mode 100644 assets/meshes/buildings/house_7_8.dmf delete mode 100644 assets/meshes/buildings/house_8_1.dmf delete mode 100644 assets/meshes/buildings/house_8_2.dmf delete mode 100644 assets/meshes/buildings/house_8_3.dmf delete mode 100644 assets/meshes/buildings/house_8_4.dmf delete mode 100644 assets/meshes/buildings/house_8_5.dmf delete mode 100644 assets/meshes/buildings/house_8_6.dmf delete mode 100644 assets/meshes/buildings/house_8_7.dmf delete mode 100644 assets/meshes/buildings/house_8_8.dmf delete mode 100644 assets/meshes/chunks/chunk_-1_0_0_0.dmf delete mode 100644 assets/meshes/chunks/chunk_0_0_0_0.dmf delete mode 100644 assets/meshes/chunks/chunk_0_1_0_0.dmf delete mode 100644 assets/meshes/chunks/chunk_1_0_0_0.dmf delete mode 100644 assets/meshes/chunks/chunk_1_1_0_0.dmf delete mode 100644 assets/meshes/chunks/chunk_2_0_0_0.dmf delete mode 100644 assets/models/buildings/house_1_1.json delete mode 100644 assets/models/buildings/house_1_2.json delete mode 100644 assets/models/buildings/house_1_3.json delete mode 100644 assets/models/buildings/house_1_4.json delete mode 100644 assets/models/buildings/house_1_5.json delete mode 100644 assets/models/buildings/house_1_6.json delete mode 100644 assets/models/buildings/house_1_7.json delete mode 100644 assets/models/buildings/house_1_8.json delete mode 100644 assets/models/buildings/house_2_1.json delete mode 100644 assets/models/buildings/house_2_2.json delete mode 100644 assets/models/buildings/house_2_3.json delete mode 100644 assets/models/buildings/house_2_4.json delete mode 100644 assets/models/buildings/house_2_5.json delete mode 100644 assets/models/buildings/house_2_6.json delete mode 100644 assets/models/buildings/house_2_7.json delete mode 100644 assets/models/buildings/house_2_8.json delete mode 100644 assets/models/buildings/house_3_1.json delete mode 100644 assets/models/buildings/house_3_2.json delete mode 100644 assets/models/buildings/house_3_3.json delete mode 100644 assets/models/buildings/house_3_4.json delete mode 100644 assets/models/buildings/house_3_5.json delete mode 100644 assets/models/buildings/house_3_6.json delete mode 100644 assets/models/buildings/house_3_7.json delete mode 100644 assets/models/buildings/house_3_8.json delete mode 100644 assets/models/buildings/house_4_1.json delete mode 100644 assets/models/buildings/house_4_2.json delete mode 100644 assets/models/buildings/house_4_3.json delete mode 100644 assets/models/buildings/house_4_4.json delete mode 100644 assets/models/buildings/house_4_5.json delete mode 100644 assets/models/buildings/house_4_6.json delete mode 100644 assets/models/buildings/house_4_7.json delete mode 100644 assets/models/buildings/house_4_8.json delete mode 100644 assets/models/buildings/house_5_1.json delete mode 100644 assets/models/buildings/house_5_2.json delete mode 100644 assets/models/buildings/house_5_3.json delete mode 100644 assets/models/buildings/house_5_4.json delete mode 100644 assets/models/buildings/house_5_5.json delete mode 100644 assets/models/buildings/house_5_6.json delete mode 100644 assets/models/buildings/house_5_7.json delete mode 100644 assets/models/buildings/house_5_8.json delete mode 100644 assets/models/buildings/house_6_1.json delete mode 100644 assets/models/buildings/house_6_2.json delete mode 100644 assets/models/buildings/house_6_3.json delete mode 100644 assets/models/buildings/house_6_4.json delete mode 100644 assets/models/buildings/house_6_5.json delete mode 100644 assets/models/buildings/house_6_6.json delete mode 100644 assets/models/buildings/house_6_7.json delete mode 100644 assets/models/buildings/house_6_8.json delete mode 100644 assets/models/buildings/house_7_1.json delete mode 100644 assets/models/buildings/house_7_2.json delete mode 100644 assets/models/buildings/house_7_3.json delete mode 100644 assets/models/buildings/house_7_4.json delete mode 100644 assets/models/buildings/house_7_5.json delete mode 100644 assets/models/buildings/house_7_6.json delete mode 100644 assets/models/buildings/house_7_7.json delete mode 100644 assets/models/buildings/house_7_8.json delete mode 100644 assets/models/buildings/house_8_1.json delete mode 100644 assets/models/buildings/house_8_2.json delete mode 100644 assets/models/buildings/house_8_3.json delete mode 100644 assets/models/buildings/house_8_4.json delete mode 100644 assets/models/buildings/house_8_5.json delete mode 100644 assets/models/buildings/house_8_6.json delete mode 100644 assets/models/buildings/house_8_7.json delete mode 100644 assets/models/buildings/house_8_8.json delete mode 100644 assets/models/chunks/chunk_-1_0_0_0.json delete mode 100644 assets/models/chunks/chunk_0_0_0_0.json delete mode 100644 assets/models/chunks/chunk_0_1_0_0.json delete mode 100644 assets/models/chunks/chunk_1_0_0_0.json delete mode 100644 assets/models/chunks/chunk_1_1_0_0.json delete mode 100644 assets/models/chunks/chunk_2_0_0_0.json delete mode 100644 assets/tiles.png delete mode 100644 assetsraw/chunks/chunk_-1_0_0.json delete mode 100644 assetsraw/chunks/chunk_0_0_0.json delete mode 100644 assetsraw/chunks/chunk_0_1_0.json delete mode 100644 assetsraw/chunks/chunk_1_0_0.json delete mode 100644 assetsraw/chunks/chunk_1_1_0.json delete mode 100644 assetsraw/chunks/chunk_2_0_0.json delete mode 100644 editor/client/public/common/chunkterrain.js delete mode 100644 editor/client/public/common/dmf.js delete mode 100644 editor/client/public/index.html delete mode 100644 editor/client/public/map/index.html delete mode 100644 editor/client/public/map/map.css delete mode 100644 editor/client/public/map/map.js delete mode 100644 editor/client/public/map/renderer.js delete mode 100644 editor/client/public/template.html delete mode 100644 editor/server/server.py delete mode 100755 editor/start.sh delete mode 100644 src/dusk/asset/assetbatch.c delete mode 100644 src/dusk/asset/assetbatch.h delete mode 100644 src/dusk/asset/loader/chunk/CMakeLists.txt delete mode 100644 src/dusk/asset/loader/chunk/assetchunkloader.c delete mode 100644 src/dusk/asset/loader/chunk/assetchunkloader.h delete mode 100644 src/dusk/event/CMakeLists.txt delete mode 100644 src/dusk/event/event.c delete mode 100644 src/dusk/event/event.h delete mode 100644 src/dusk/rpg/CMakeLists.txt delete mode 100644 src/dusk/rpg/battle/CMakeLists.txt delete mode 100644 src/dusk/rpg/battle/battle.c delete mode 100644 src/dusk/rpg/battle/battle.h delete mode 100644 src/dusk/rpg/battle/battlefighter.c delete mode 100644 src/dusk/rpg/battle/battlefighter.h delete mode 100644 src/dusk/rpg/battle/party.c delete mode 100644 src/dusk/rpg/battle/party.h delete mode 100644 src/dusk/rpg/cutscene/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/cutscene.h delete mode 100644 src/dusk/rpg/cutscene/cutscenepause.h delete mode 100644 src/dusk/rpg/cutscene/cutscenesystem.c delete mode 100644 src/dusk/rpg/cutscene/cutscenesystem.h delete mode 100755 src/dusk/rpg/cutscene/item/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/item/battle/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.c delete mode 100644 src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.h delete mode 100644 src/dusk/rpg/cutscene/item/control/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.c delete mode 100644 src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.h delete mode 100644 src/dusk/rpg/cutscene/item/control/cutscenesetpause.c delete mode 100644 src/dusk/rpg/cutscene/item/control/cutscenesetpause.h delete mode 100644 src/dusk/rpg/cutscene/item/control/cutscenewait.c delete mode 100644 src/dusk/rpg/cutscene/item/control/cutscenewait.h delete mode 100644 src/dusk/rpg/cutscene/item/cutscenecallback.c delete mode 100644 src/dusk/rpg/cutscene/item/cutscenecallback.h delete mode 100644 src/dusk/rpg/cutscene/item/cutsceneitem.c delete mode 100644 src/dusk/rpg/cutscene/item/cutsceneitem.h delete mode 100644 src/dusk/rpg/cutscene/item/entity/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.c delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.h delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.c delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.h delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.c delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.h delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.c delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.h delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.c delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.h delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.c delete mode 100644 src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.h delete mode 100644 src/dusk/rpg/cutscene/item/item/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/item/item/cutsceneitemgive.c delete mode 100644 src/dusk/rpg/cutscene/item/item/cutsceneitemgive.h delete mode 100644 src/dusk/rpg/cutscene/item/maparea/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.c delete mode 100644 src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.h delete mode 100644 src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.c delete mode 100644 src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.h delete mode 100644 src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.c delete mode 100644 src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.h delete mode 100644 src/dusk/rpg/cutscene/item/ui/CMakeLists.txt delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutsceneemoji.c delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutsceneemoji.h delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenefade.c delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenefade.h delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutsceneshake.c delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutsceneshake.h delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenetext.c delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenetext.h delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenetextmini.c delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenetextmini.h delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.c delete mode 100644 src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.h delete mode 100755 src/dusk/rpg/cutscene/scene/testcutscene.h delete mode 100644 src/dusk/rpg/entity/CMakeLists.txt delete mode 100644 src/dusk/rpg/entity/anim/CMakeLists.txt delete mode 100644 src/dusk/rpg/entity/anim/entityanim.c delete mode 100644 src/dusk/rpg/entity/anim/entityanim.h delete mode 100644 src/dusk/rpg/entity/anim/entityanimidle.c delete mode 100644 src/dusk/rpg/entity/anim/entityanimidle.h delete mode 100644 src/dusk/rpg/entity/anim/entityanimrun.c delete mode 100644 src/dusk/rpg/entity/anim/entityanimrun.h delete mode 100644 src/dusk/rpg/entity/anim/entityanimturn.c delete mode 100644 src/dusk/rpg/entity/anim/entityanimturn.h delete mode 100644 src/dusk/rpg/entity/anim/entityanimwalk.c delete mode 100644 src/dusk/rpg/entity/anim/entityanimwalk.h delete mode 100644 src/dusk/rpg/entity/entity.c delete mode 100644 src/dusk/rpg/entity/entity.h delete mode 100644 src/dusk/rpg/entity/entitydir.c delete mode 100644 src/dusk/rpg/entity/entitydir.h delete mode 100644 src/dusk/rpg/entity/entitypathstep.c delete mode 100644 src/dusk/rpg/entity/entitypathstep.h delete mode 100644 src/dusk/rpg/entity/entitytype.h delete mode 100644 src/dusk/rpg/entity/global/CMakeLists.txt delete mode 100644 src/dusk/rpg/entity/global/entityglobal.h delete mode 100644 src/dusk/rpg/entity/global/entityglobaldefs.h delete mode 100644 src/dusk/rpg/entity/global/entitygloballist.h delete mode 100644 src/dusk/rpg/entity/interact/CMakeLists.txt delete mode 100644 src/dusk/rpg/entity/interact/entityinteract.c delete mode 100644 src/dusk/rpg/entity/interact/entityinteract.h delete mode 100644 src/dusk/rpg/entity/item/CMakeLists.txt delete mode 100644 src/dusk/rpg/entity/item/entityitem.c delete mode 100644 src/dusk/rpg/entity/item/entityitem.h delete mode 100644 src/dusk/rpg/entity/npc/CMakeLists.txt delete mode 100644 src/dusk/rpg/entity/npc/npc.c delete mode 100644 src/dusk/rpg/entity/npc/npc.h delete mode 100644 src/dusk/rpg/entity/npc/npcpath.c delete mode 100644 src/dusk/rpg/entity/npc/npcpath.h delete mode 100644 src/dusk/rpg/entity/npc/npcturn.c delete mode 100644 src/dusk/rpg/entity/npc/npcturn.h delete mode 100644 src/dusk/rpg/entity/npc/npcwalk.c delete mode 100644 src/dusk/rpg/entity/npc/npcwalk.h delete mode 100644 src/dusk/rpg/entity/player.c delete mode 100644 src/dusk/rpg/entity/player.h delete mode 100644 src/dusk/rpg/item/CMakeLists.txt delete mode 100644 src/dusk/rpg/item/backpack.c delete mode 100644 src/dusk/rpg/item/backpack.h delete mode 100644 src/dusk/rpg/item/inventory.c delete mode 100644 src/dusk/rpg/item/inventory.h delete mode 100644 src/dusk/rpg/item/item.c delete mode 100644 src/dusk/rpg/item/item.h delete mode 100644 src/dusk/rpg/item/item.json delete mode 100644 src/dusk/rpg/item/itemgive.c delete mode 100644 src/dusk/rpg/item/itemgive.h delete mode 100644 src/dusk/rpg/overworld/CMakeLists.txt delete mode 100644 src/dusk/rpg/overworld/chunk.c delete mode 100644 src/dusk/rpg/overworld/chunk.h delete mode 100644 src/dusk/rpg/overworld/map.c delete mode 100644 src/dusk/rpg/overworld/map.h delete mode 100644 src/dusk/rpg/overworld/maparea.c delete mode 100644 src/dusk/rpg/overworld/maparea.h delete mode 100644 src/dusk/rpg/overworld/tile.c delete mode 100644 src/dusk/rpg/overworld/tile.h delete mode 100644 src/dusk/rpg/overworld/tileshape.c delete mode 100644 src/dusk/rpg/overworld/tileshape.h delete mode 100644 src/dusk/rpg/overworld/worldpos.c delete mode 100644 src/dusk/rpg/overworld/worldpos.h delete mode 100644 src/dusk/rpg/rpg.c delete mode 100644 src/dusk/rpg/rpg.h delete mode 100644 src/dusk/rpg/rpgcamera.c delete mode 100644 src/dusk/rpg/rpgcamera.h delete mode 100644 src/dusk/rpg/story/CMakeLists.txt delete mode 100644 src/dusk/rpg/story/storyflag.c delete mode 100644 src/dusk/rpg/story/storyflag.csv delete mode 100644 src/dusk/rpg/story/storyflag.h delete mode 100644 src/dusk/rpg/story/storyflagdefs.h delete mode 100644 src/dusk/save/CMakeLists.txt delete mode 100644 src/dusk/save/save.c delete mode 100644 src/dusk/save/save.h delete mode 100644 src/dusk/save/savefile.h delete mode 100644 src/dusk/save/savestream.c delete mode 100644 src/dusk/save/savestream.h delete mode 100644 src/dusk/scene/battle/CMakeLists.txt delete mode 100644 src/dusk/scene/battle/scenebattle.c delete mode 100644 src/dusk/scene/battle/scenebattle.h delete mode 100644 src/dusk/scene/overworld/CMakeLists.txt delete mode 100644 src/dusk/scene/overworld/sceneoverworld.c delete mode 100644 src/dusk/scene/overworld/sceneoverworld.h delete mode 100644 src/dusk/ui/debug/uiplayerpos.c delete mode 100644 src/dusk/ui/debug/uiplayerpos.h delete mode 100644 src/dusk/ui/frame/CMakeLists.txt delete mode 100644 src/dusk/ui/frame/backpack/CMakeLists.txt delete mode 100644 src/dusk/ui/frame/backpack/uibackpack.c delete mode 100644 src/dusk/ui/frame/backpack/uibackpack.h delete mode 100644 src/dusk/ui/frame/battle/CMakeLists.txt delete mode 100644 src/dusk/ui/frame/battle/uibattlemenu.c delete mode 100644 src/dusk/ui/frame/battle/uibattlemenu.h delete mode 100644 src/dusk/ui/frame/game/CMakeLists.txt delete mode 100644 src/dusk/ui/frame/game/uigamemenu.c delete mode 100644 src/dusk/ui/frame/game/uigamemenu.h delete mode 100644 src/dusk/ui/frame/settings/CMakeLists.txt delete mode 100644 src/dusk/ui/frame/settings/uisettings.c delete mode 100644 src/dusk/ui/frame/settings/uisettings.h delete mode 100644 src/dusk/ui/frame/settings/uisettingsaudio.c delete mode 100644 src/dusk/ui/frame/settings/uisettingsaudio.h delete mode 100644 src/dusk/ui/frame/settings/uisettingsdata.h delete mode 100644 src/dusk/ui/frame/settings/uisettingsdisplay.c delete mode 100644 src/dusk/ui/frame/settings/uisettingsdisplay.h delete mode 100644 src/dusk/ui/frame/settings/uisettingsgeneral.c delete mode 100644 src/dusk/ui/frame/settings/uisettingsgeneral.h delete mode 100644 src/dusk/ui/frame/settings/uisettingsinput.c delete mode 100644 src/dusk/ui/frame/settings/uisettingsinput.h delete mode 100644 src/dusk/ui/frame/uiconfirm.c delete mode 100644 src/dusk/ui/frame/uiconfirm.h delete mode 100644 src/dusk/ui/frame/uiframe.c delete mode 100644 src/dusk/ui/frame/uiframe.h delete mode 100644 src/dusk/ui/overlay/uifullbox.c delete mode 100644 src/dusk/ui/overlay/uifullbox.h delete mode 100644 src/dusk/ui/overlay/uiloading.c delete mode 100644 src/dusk/ui/overlay/uiloading.h delete mode 100644 src/dusk/ui/rpg/CMakeLists.txt delete mode 100644 src/dusk/ui/rpg/textbox/CMakeLists.txt delete mode 100644 src/dusk/ui/rpg/textbox/uitextbox.c delete mode 100644 src/dusk/ui/rpg/textbox/uitextbox.h delete mode 100644 src/dusk/ui/rpg/textbox/uitextboxmain.c delete mode 100644 src/dusk/ui/rpg/textbox/uitextboxmain.h delete mode 100644 src/dusk/ui/rpg/textbox/uitextboxmini.c delete mode 100644 src/dusk/ui/rpg/textbox/uitextboxmini.h delete mode 100644 src/dusk/ui/rpg/textbox/uitextboxminilist.c delete mode 100644 src/dusk/ui/rpg/textbox/uitextboxminilist.h delete mode 100644 src/dusk/ui/rpg/uiemoji.c delete mode 100644 src/dusk/ui/rpg/uiemoji.h delete mode 100644 src/dusk/ui/transition/CMakeLists.txt delete mode 100644 src/dusk/ui/transition/uitransition.c delete mode 100644 src/dusk/ui/transition/uitransition.h delete mode 100644 src/dusk/ui/transition/uitransitiondata.h delete mode 100644 src/dusk/ui/transition/uitransitionfade.c delete mode 100644 src/dusk/ui/transition/uitransitionfade.h delete mode 100644 src/dusk/ui/widget/uiitem.c delete mode 100644 src/dusk/ui/widget/uiitem.h delete mode 100644 src/dusk/ui/widget/uiitemlist.c delete mode 100644 src/dusk/ui/widget/uiitemlist.h delete mode 100644 src/duskdolphin/save/CMakeLists.txt delete mode 100644 src/duskdolphin/save/savedolphin.c delete mode 100644 src/duskdolphin/save/savedolphin.h delete mode 100644 src/duskdolphin/save/saveplatform.h delete mode 100644 src/duskdolphin/save/savestreamdolphin.c delete mode 100644 src/duskdolphin/save/savestreamdolphin.h delete mode 100644 src/dusklinux/save/CMakeLists.txt delete mode 100644 src/dusklinux/save/savelinux.c delete mode 100644 src/dusklinux/save/savelinux.h delete mode 100644 src/dusklinux/save/saveplatform.h delete mode 100644 src/dusklinux/save/savestreamlinux.c delete mode 100644 src/dusklinux/save/savestreamlinux.h delete mode 100644 src/duskpsp/save/CMakeLists.txt delete mode 100644 src/duskpsp/save/saveplatform.h delete mode 100644 src/duskpsp/save/savepsp.c delete mode 100644 src/duskpsp/save/savepsp.h delete mode 100644 src/duskpsp/save/savestreampsp.c delete mode 100644 src/duskpsp/save/savestreampsp.h delete mode 100644 src/duskvita/save/CMakeLists.txt delete mode 100644 src/duskvita/save/saveplatform.h delete mode 100644 src/duskvita/save/savestreamvita.c delete mode 100644 src/duskvita/save/savestreamvita.h diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 451c4d16..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,455 +0,0 @@ -# Dusk — Claude Code rules - -## File headers -Every C, H, and JS file starts with: - -```c -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ -``` - -JS files use `//` comment style instead. - ---- - -## C conventions - -### Types -Always use the project-defined aliases instead of bare C primitives: - -| Use | Not | -|-----------|--------------| -| `bool_t` | `bool` | -| `int_t` | `int` | -| `float_t` | `float` | -| `char_t` | `char` | - -Use `uint8_t`, `uint16_t`, `int32_t`, etc. for fixed-width integers. -All struct and enum types end in `_t` (`animation_t`, `errorret_t`, …). - -### Naming -- **Functions** — snake_case, prefixed with their module: - `assetLock()`, `entityPositionInit()`, `moduleAssetBatchCtor()` -- **Struct fields** — camelCase: `keyframeCount`, `localPosition` -- **Macros / constants** — UPPER_SNAKE_CASE: - `ENTITY_ID_INVALID`, `ERROR_OK`, `COMPONENT_TYPE_COUNT` -- **Files** — snake_case matching the primary type: `entityposition.c`, - `moduleassetbatch.c` - -### Header files (`.h`) -- Use `#pragma once` — no include guards. -- Declare every public function, `#define`, and `extern` global. -- Write a JSDoc block (`/** … */`) above every declaration explaining - purpose, `@param`s, and `@returns`. -- Only include headers that the `.h` file itself strictly requires for - the types it exposes. Move everything else to the `.c` file. - Do not use forward declarations as a workaround — use the real - include in the `.c` file instead. - -### Implementation files (`.c`) -- Contain function bodies only; no declarations. -- Pull in whatever additional includes the implementation needs. -- Do not use `static` or `inline` on **functions**. Every function, - including internal helpers, must be declared in the matching `.h` and - defined in the `.c` file. Internal helpers belong near the bottom of - the `.c` file, not at the top with a `static` qualifier. - `static` and `inline` on functions are only appropriate when the - function body is written directly inside a `.h` file. - `static` on **variables** (file-scope state) is fine and expected. - -### Formatting -- Hard-wrap all lines at **80 characters**. - -### Error handling -Return `errorret_t` from fallible functions. Use these macros: - -```c -errorOk(); // return success -errorThrow("msg %d", val); // return failure with message -errorChain(someCall()); // propagate failure, continue on success -errorIsOk(ret) / errorIsNotOk(ret) // test a result -errorCatch(ret); // handle + free an error -``` - -Never return raw error codes or use `errno` for in-engine errors. - -### Memory -Use the project allocator — never raw `malloc`/`free`: - -```c -memoryAllocate(size) // allocate -memoryFree(ptr) // free -memoryZero(dest, size) // zero a block -memoryCopy(dest, src, size) // copy -``` - -### Asserts -Prefer specific assert macros over bare `assert()`: - -```c -assertNotNull(ptr, "msg"); -assertTrue(cond, "msg"); -assertFalse(cond, "msg"); -assertUnreachable("msg"); -assertIsMainThread("msg"); -``` - ---- - -## Build system -Each subdirectory has its own `CMakeLists.txt` that adds sources with: - -```cmake -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - myfile.c -) -``` - -Never add source files to the root `CMakeLists.txt` directly. - ---- - -## Platform support - -### Targets -Set `DUSK_TARGET_SYSTEM` at CMake configure time to select a platform: - -| `DUSK_TARGET_SYSTEM` | Macro defined | Platform | -|----------------------|-------------------|------------------| -| `linux` | `DUSK_LINUX` | Linux desktop | -| `knulli` | `DUSK_KNULLI` | Knulli (handheld)| -| `psp` | `DUSK_PSP` | Sony PSP | -| `vita` | `DUSK_VITA` | PlayStation Vita | -| `gamecube` | `DUSK_GAMECUBE` | Nintendo GameCube| -| `wii` | `DUSK_WII` | Nintendo Wii | - -### Layer structure -``` -src/dusk/ core, platform-agnostic game logic -src/duskgl/ OpenGL abstraction (Linux, Knulli, PSP, Vita) -src/dusksdl2/ SDL2 window + input (Linux, Knulli, PSP, Vita) -src/dusklinux/ Linux + Knulli platform impl -src/duskpsp/ PSP platform impl -src/duskvita/ Vita platform impl -src/duskdolphin/ GameCube / Wii platform impl (no SDL2/OpenGL) -``` - -Dolphin is the only target that bypasses SDL2 and OpenGL entirely — -it uses native GameCube/Wii rendering and input APIs. - -### Platform guards -Use the compile-time macros for platform-specific code: - -```c -#ifdef DUSK_PSP - // PSP-only path -#elif defined(DUSK_GAMECUBE) || defined(DUSK_WII) - // GameCube / Wii path -#else - // Generic / Linux fallback -#endif -``` - -Additional capability macros set per-target: -`DUSK_SDL2`, `DUSK_OPENGL`, `DUSK_OPENGL_ES`, `DUSK_OPENGL_LEGACY`, -`DUSK_INPUT_GAMEPAD`, `DUSK_INPUT_KEYBOARD`, `DUSK_INPUT_POINTER`, -`DUSK_PLATFORM_ENDIAN_BIG` / `DUSK_PLATFORM_ENDIAN_LITTLE`. - -### Abstraction pattern -Platform-specific implementations are wired in via `#define` macros in -each platform's `displayplatform.h` / `inputplatform.h` etc., which -the core calls through. Functions that a platform does not support are -simply left undefined — the core guards calls with `#ifdef`. - -### Adding platform-specific code -- Put it under `src/dusk/` in the matching subsystem folder. -- Gate any core call-site with the appropriate `#ifdef DUSK_` - or capability macro. -- Keep the `src/dusk/` core free of platform ifdefs — delegate through - the platform header macros instead. - ---- - -## Adding a new asset loader type -1. Add an enum value to `assetloadertype_t` (before `_COUNT`) in - `src/dusk/asset/loader/assetloader.h`. -2. Add fields to the input/loading/output unions in `assetloader.h`. -3. Implement `assetXxxLoaderSync`, `assetXxxLoaderAsync`, and - `assetXxxDispose` in a new `src/dusk/asset/loader/xxx/` directory. -4. Register the three callbacks in `ASSET_LOADER_CALLBACKS[]` in - `src/dusk/asset/loader/assetloader.c`. -5. If user-facing, create a JS module (see below) and a `.d.ts` file. - ---- - -## Adding a new entity component -1. Create `src/dusk/entity/component//entityMyComp.h/.c` with - struct `entityMyComp_t`, `entityMyCompInit()`, and optionally - `entityMyCompDispose()`. -2. Add the include to `src/dusk/entity/componentlist.h` header block. -3. Add a row to `src/dusk/entity/componentlist.h`: - ```c - X(MYCOMP, entityMyComp_t, myComp, entityMyCompInit, NULL, NULL) - ``` - This auto-generates the enum, union field, and definition entry. -4. If JS-facing, create the script module and `.d.ts` (see below). - ---- - -## Adding a new script (JS) module -1. Create `src/dusk/script/module//moduleMyMod.h/.c`. - - Declare `extern scriptproto_t MODULE_MYMOD_PROTO;` in the header. - - Use `moduleBaseFunction(name)` to define JS-callable functions. - - Register props/funcs in `moduleMyModInit()` with - `scriptProtoDefineProp` / `scriptProtoDefineFunc` / - `scriptProtoDefineStaticFunc`. -2. `#include` the header in - `src/dusk/script/module/modulelist.c` and call - `moduleMyModInit()` in `moduleListInit()` (and `Dispose` in - `moduleListDispose()`). -3. For component modules also register in - `src/dusk/script/module/entity/component/modulecomponentlist.c` - so `entity.add()` returns the typed wrapper. -4. Create `types//mymod.d.ts` and add a - `/// ` line to `types/index.d.ts`. - ---- - -## Script module type declarations -Whenever a `src/dusk/script/module/**/*.c` file is created or modified, -check whether the corresponding `types/**/*.d.ts` needs updating and -apply any changes before finishing the task. - ---- - -## JavaScript (asset scripts) -- Use `var` for module-level state; `const` for values that never - change. -- Always use semicolons. -- Scene objects are plain objects (`var scene = {}`) with assigned - methods. -- Export via `module.exports = scene`. -- Async scene init should use `async function` and `await`. - ---- - -## Coding style - -### ASCII only -Source files (`.c`, `.h`, `.js`) must contain only ASCII characters (U+0000–U+007F). -Non-ASCII characters are banned even in comments and string literals. -Use ASCII-only substitutes instead: -- `--` or `-` instead of `—` (em dash) -- `->` instead of `→` (arrow) -- `x` or `*` instead of `×` (multiplication) - -Only non-script asset files (e.g. `.po` locale files) may contain non-ASCII text. - -### Indentation -2 spaces. No tabs. - -### Keyword and operator spacing -No space between a keyword or function name and its opening parenthesis: - -```c -if(!ptr) return; -for(uint8_t i = 0; i < count; i++) { -while(entry->state != DONE) { -switch(type) { -sizeof(assetbatch_t) -memoryZero(ptr, size) -``` - -Spaces around all binary operators and after every comma: - -```c -pos->flags |= ENTITY_POSITION_FLAG_WORLD_DIRTY; -(size_t)end - (size_t)start -foo(a, b, c) -``` - -### Braces -Opening brace on the **same line** as the statement (K&R style) for all -constructs — functions, `if`, `else`, `for`, `while`, `switch`: - -```c -void assetEntryLock(assetentry_t *entry) { - ... -} - -if(dirty) { - ... -} else { - ... -} -``` - -### Guard returns -Short guards go on one line with no braces: - -```c -if(!ptr) return; -if(!b || !b->batch) return jerry_undefined(); -if(!(flags & DIRTY)) return; -``` - -### Blank lines -- One blank line between functions; no blank line at the start or end of - a function body. -- One blank line between logical blocks inside a function body. -- No trailing blank lines at the end of a file. - -### Pointer placement -`*` is attached to the variable name, not the type: - -```c -assetentry_t *entry -const char_t *name -void *ptr -uint8_t *d = (uint8_t *)dest; -``` - -### Casts -Space between cast and operand: - -```c -(assetbatch_t *)user -(uint8_t *)dest -(textureformat_t)v -``` - -### Return -No parentheses around the return value: - -```c -return ptr; -return MEMORY_POINTERS_IN_USE; -``` - -### switch / case -`case` indented 2 spaces from `switch`; body indented 2 more from `case`: - -```c -switch(type) { - case ASSET_LOADER_TYPE_TEXTURE: - descs[i].input.texture = (textureformat_t)v; - break; - default: - break; -} -``` - -### Multi-line function signatures -When parameters don't fit on one line, put each on its own line indented -2 spaces; the closing `) {` (definition) or `);` (declaration) goes on -its own line at column 0: - -```c -void assetEntryInit( - assetentry_t *entry, - const char_t *name, - const assetloadertype_t type, - assetloaderinput_t *input -) { - -errorret_t memoryCompare( - const void *a, - const void *b, - const size_t size -); -``` - -### Structs and enums -Anonymous inner struct or enum with a `typedef`, `_t` suffix, closing -brace and name on the same line: - -```c -typedef struct { - errorcode_t code; - char_t *message; -} errorstate_t; - -typedef enum { - ASSET_LOADER_TYPE_NULL, - ASSET_LOADER_TYPE_COUNT -} assetloadertype_t; -``` - -### Designated initialisers -Spaces inside braces; `.field = value`: - -```c -jsassetentry_t e = { .entry = entry }; -assetbatchloadedpend_t init = { .batch = batch }; -``` - -### Ternary operator -Spaces around `?` and `:`: - -```c -const float val = psx > 0.0f ? pt[0][0] / psx : 0.0f; -``` - -### const placement -`const` before the type, `*` attached to the variable: - -```c -const char_t *name -const void *src -const size_t size -``` - -### Comments in `.c` files -- Do not use section dividers (`/* ---- ... ---- */`). Just let the - functions follow one another with a single blank line between them. -- Multi-line explanatory comments inside function bodies use `//` lines: - ```c - // Script modules are freed; orphaned JS wrapper objects now get GC'd - // so their finalizers fire before assetDispose() checks ref counts. - jerry_heap_gc(JERRY_GC_PRESSURE_HIGH); - ``` -- Do not use `/* */` for inline or inline-block comments inside `.c` - function bodies. - -### Comments in `.h` files -Every public declaration gets a Javadoc block (`/** … */`) with -`@param` and `@returns` where relevant. Keep it on the lines immediately -above the declaration with no blank line in between. - ---- - -## Color system - -Colors are defined in `src/dusk/display/color.csv` and code-generated -into a `color.h` header by `tools/color/csv/__main__.py`. - -Each row in the CSV has `name,r,g,b,a` with channel values in `[0.0, 1.0]`. -The script emits four `#define` variants per color plus a bare alias: - -``` -COLOR__4B color4b(r8, g8, b8, a8) // default alias target -COLOR__3B color3b(r8, g8, b8) -COLOR__3F color3f(rf, gf, bf) -COLOR__4F color4f(rf, gf, bf, af) -COLOR_ COLOR__4B -``` - -`color_t` is `color4b_t` (four `uint8_t` channels). - -To add a new color, append a row to `color.csv` and rebuild — do not -hand-edit the generated header. - ---- - -## Tests -- Tests live in `test/` mirroring `src/dusk/` structure. -- Use cmocka; include `dusktest.h`. -- Test functions: `static void test_something(void **state)`. -- After each test, assert `memoryGetAllocatedCount() == 0` to catch - leaks. -- Build with `-DDUSK_BUILD_TESTS=ON`. diff --git a/README.md b/README.md index 2da2f6eb..f91c4828 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,3 @@ -# Dusk -RPG Game Project, small and able to run on a PSP. - # Building Each build target has different requirements. You can take a look at the git workflow to see how the builds are done for each target. In addition, for diff --git a/assets/chunks/-1_0_0.dcf b/assets/chunks/-1_0_0.dcf deleted file mode 100644 index 70bb62209e75de265f3e91e145eb939fa13cea15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2235 zcmZ>9c4J^+U|?VbVh|WCG{iNyNm{!Tx6KflQTyo=4zvzudYO-&p6F#S%$|X^ALb51 zG`c$p@d=qnsyre4(B(-rpOAWV^9k_@nKvpA3Bl2Dz#k4Qx%nxnImP9Mt*5=YP?Cj30$oM14Dy7ND~gVX7R=_wIFo@ Vj(F4>#T&uYIsnxj0GiFf003?mG?f4V diff --git a/assets/chunks/0_0_0.dcf b/assets/chunks/0_0_0.dcf deleted file mode 100644 index eccdb75949aa81127f031acf4528f6750656d4fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmZ>9c4J^+U|?VbVh|W;8sZAVB(2;@*k*`|;c7pv{6#Hu*`N``L?X=&RZpoqn32o@ znMEvSMbZailIxC9c4J^+U|?VbVh|W;8sZA_NlM*MzReJw==S3>4_zIMk4rtV;xKbyG%kHGd2||= zdSb1w znwJfw;tk>rf!IJVt2jRoB_Ti+CzWRAq-5r$7wc!_mlmhSTg02d)Hc{NFn}-v0}i#u b@y0N<297{w4tUfW#T&uYIsnyy)iVG9`nfam diff --git a/assets/chunks/1_0_0.dcf b/assets/chunks/1_0_0.dcf deleted file mode 100644 index f9f7654c958f4a2fbe56df7be1117e7cf60ba87f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2322 zcmZ>9c4J^+U|?VbVh|W;8sZ8}l3wn@v>76T%YJnAxYW@~e5Bh?t8k^2x#;l)SYz@=fM&(n1(7&D$UGE$;?YH*3ZZ9c4J^+U|?VbVh|XmQNsbkBTUjN+z8u@>Ry;T(DlK@Nu|-v!No^67hN5?Jh6Oq zb8zv|%|lm*E>A2U-5gweV$B;>2MNK^a2TB7Fq*yxXS~olzp&)yr=;c->nCTF=4C^v zctapGh&Ry7D$dVCNf=PYNu`-NDVcfc#rhffrNyc7rtzjQwGIwI4Is>bL#i3=9AuWiz}0 diff --git a/assets/chunks/2_0_0.dcf b/assets/chunks/2_0_0.dcf deleted file mode 100644 index d26e7bb528801010fb62e7275a921da5084cf6c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmZ>9c4J^+U|?VbVh|XmN5f&LqyuJXdL@>|=PyXCBS>QM0kQVN)D33)iSaM8`$1&} z6A%+ilWIO8^{_IFSelS|q{@Tr1p#7dQq3P#4+-DVaG+B-c`{LB?9hI(4{7NaW&wJd)7|;CH^?e+@pL?x-b&eq% zr#{z+cTBZ&s(HrDLN81{oUWHfx}Dp7;*}%+h;=S~iD|Vi0o9!q>z&+#x^-2{PhD_d zG`b5I_n!Iya$dU!ie)B%z&7*giP@91O_|aeb-E)s*U3Bb|GdYX0bDw19P1nu=50-3 zps^Z{Y$_WV>V0mad;{`X>eSn#CstnSeG6}@PE5Yt%O0}rF6BJ_56v`P^I0$>9GMt6 zeVPF!Jt!`I2f3IU^p16Z;YH-Xw_--pI-xtQ!dg=^G?VznT;lNRt_U_S+FsGse4E6W Nk(5r}ukwg7?+5NxZI1u| diff --git a/assets/meshes/buildings/house_1_2.dmf b/assets/meshes/buildings/house_1_2.dmf deleted file mode 100644 index c308143767f69062fbeedd4c1179f68347c01bd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiwYi;c+XPN z-hXtrK2|I*W$EAq-<bD*D2`sJKF9SIFO9#shH%FS5kO%tIb!dp=7ziTvd3Vb zW8R?$O#^?rD+#*kQR!@s-oSf`8_phQd+7->ocl@gh#TuBt##BDp$hZ}H3Iq$ZV+(J z=91AHiLU9~)xPpl#C{V!H@1CCN7^E?>sovNyo(Q9{44L$G$UNBZ=x5hbME`#K*TTd C7i%a0 diff --git a/assets/meshes/buildings/house_1_3.dmf b/assets/meshes/buildings/house_1_3.dmf deleted file mode 100644 index 2cef82ef397e17c7bed828d9200297a28e52b76d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaix?QH}h3<(_ADR{hTJH*RaUr@Fe?|D}A@>AmuMJ)&m9)u~w- zz2w*8g|TGLgxRm%npMY{Ft@1l$*5UZE}r>MJYo7yFEwF5>p^pmT=z_vI?l#?H$i3@ z{amXTMyza*-3vqes-NDTqh{iD24}+D-)*4UV;t42UKmSOrh2}1Yq(Q~XN#zcyY=0; NnR;}0KiHM)5x>|wcW3|r diff --git a/assets/meshes/buildings/house_1_4.dmf b/assets/meshes/buildings/house_1_4.dmf deleted file mode 100644 index 4c6a9fb1008ff36e6827799770ae31a07acbb3ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)&Q4Yf}2t%`z4NcSjcBdYFHqA>(muf?zfMXlf=lj)et+j`8jxF|iyC1b;#(A5S z!i#pryVBVQZT9T8pAxUE9n;GQv@0GvhjysCZydnT8&i(C-(!rZek-0a2etNR41EeB zzmtwzs>jZn{p)?auQXuw4zyrfh^1t{l#T=g}1`&1YWhN^Z&M& zlBj;o-aX-Yc2E<)z|PuTS-w$vT4CsNhi9c@+8JfeSAB#v?lqI~(#fGH%3pfA61IdbH4OH%v9qTjVes<|tdhs;X+LImk6h#QcK`dG zwK8$uR;SrF-G4sK!K)r!GH-YG!lWbcqESW1tidov-I?x#`MNi4!HA&?fKN5U8&f}6 z>34=-dhSb+0{I}S$*!5mL2S*TIfEaGc?sJri4}RDW9@yq8mD9iDh`N QQS^ov9ktFAyM^!YH-=Yv*Z=?k diff --git a/assets/meshes/buildings/house_1_6.dmf b/assets/meshes/buildings/house_1_6.dmf deleted file mode 100644 index 267305335aa0ac01c3cb2de77b751871121aa0a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaixQBDLw2nF$E5@Y=HP99~CGDnl@?wV$1*GR$u)$hSZKfk}?Eh0WDuW{s@f8KZP z4DQ?28S$U)FCTmK(yJRR=j>e>Izz7-sycU_OjFf6V?J44?+#lrmcjFh1xVD5{h={kCKqshJBw^)q1dxyS%O7|4S^xeJ8gumH&QXVSTO_(}*Kcf=*HX(!-XLl2X!^at!vfv9qTjVes<|tdjflVLxW}8@a~m?f$yW zTA4U+tJCb8?mwUA;8l+T?o9W=eBGP2V8qY`z^9twjj123 z^gF{Zy?LICPYe&WsV2{R=&oY-NVDt|a2<2r{`@!a_Ed(wdc~xz>}np~tUh;2%MNx@Ep#8z8Jg-9Q^KnEluy|;(G4B5#4^0s QD0;(-j#}r59pQWXA8dPu7ytkO diff --git a/assets/meshes/buildings/house_1_8.dmf b/assets/meshes/buildings/house_1_8.dmf deleted file mode 100644 index 9eea5b56e1cbacb3d8abdb13d53bdf45f4d5b94b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)4(GtQi2*WQEJ#TOR(>`sVCSe2%>zv%xHX#XX&)0jAn}|GZwR-G$y$}1qfoHEd zMJ{xwJ_Lmq$JBw-9p~KOpv#)g9lX$aX6WeaT%SSgI+&Esnm5zY!yQhZxswA;Lj{*w!<((kxqO4kTQMtV#SCEY&F+h)+KN1%Z+O!WS2S}` diff --git a/assets/meshes/buildings/house_2_1.dmf b/assets/meshes/buildings/house_2_1.dmf deleted file mode 100644 index 52187c10703c12310072ee5af5361bac7008025e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmah^TaLp(2%|UIn-r~9{p+22^x6ayXOec2B7+|=`FlR%77@Srj`g~4voJD3J+XRl zSM{Gy`nN1K`E-luJ>TTz{?#YV|6{Vb-y(OF6;~Pfr_gIRarH^_w|?T*EN_gLL)whq zYxTLN{@`hn+=0(c5LXCJbH@h6%QpfVX(ui>W^}ya2i(l+g|w>&vc_xK;u2zW^i^g1 zfz(!C%`{SHrR_&w1*C7ywz>m+rvmpWJGbpW4tZolcPX@wt*UmUrVYgr)rVz^qt!TV ykbgY6?;s~VF0!?w{j0BL8lYDRdvtEReS`D5&ttA#W!*dXN#?$Ha^R|nr@LyQ=-G&?Vn%c^fHi;o-yLgqekXT+iaE$#<@yxMP5Xl966jU}BpStEQ%N zoD|=^rVWqwRjAL*? zd+kQ_5YI3!YH~Kv1D>f#ta`PNju|-DE&HUVZj0bjs|s?rcjZ&&_p&Wi4Y37h@<2eRqdK;MgX{*KDx*A|3)`3|LXzztPJi*)t_Rc#o zy3M;+3|=$pRJroP?*+3?J_^B9Sl=;m%vo+mwYFEyF9*SsHlG0e@n*Y^wSFtkp- RP28H?-=+yztJlE?N4tUX`F^!qYwdwG$7Q{~?!i%4<~%f^ z$nBRdd!}O~@{&mB%zCZ4V#B$=pLFWg*avG0)RnC>Sc|z2`V8dq?sV>>7&^s??PjEw zW{Z17&P}oE#Opq3;(%=8)(^z|ZD6XymYcYAd4R-O1!C5ry#6k*wRXP#|Gs$L&vW() z9jZ~2>AlRcsH<~9_rG)Kjx*fYy-IVpK4a&tv!}br3~$q&$xu^Q!|MZM|9|H0`mJ~K z*@u4Bf6~={u3zq4S=I7=tew%rntKVa4L~}cp(f8>WDN6f{~(t)bvoy+e$25h`vA4} BV_5(I diff --git a/assets/meshes/buildings/house_2_5.dmf b/assets/meshes/buildings/house_2_5.dmf deleted file mode 100644 index 76f6f45335c433d089812d6a5723cbc2317d52eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma))(G9{d3`ET)Y(j((f9%8vjL=azJ9)0#rUFYP_RHNRMSZ-Ub}_TNo^36y&+psd znkx%FG((ZgFI{G)V{Py{K^Ls`nR8*QbACT`WSMe;RpXBB&+r)*HtDm}lQ+|a&&ASF zXKZ#xYTew{|D@*m)?VjqUmMNXbhhEGZ@}W+#F&RI7dX1yP!p^ISnCk)Rr5y=v#BR< z#@r3B-eB^=To={WJmY=E(2-?gQCiQ~=^4YC8O*-6o;UMy&fzZjH)y%gMOf#%{xu5aA+C)cI>XnhD9&hTz LqI@M!eb4&>sR(I# diff --git a/assets/meshes/buildings/house_2_6.dmf b/assets/meshes/buildings/house_2_6.dmf deleted file mode 100644 index b200e0b65cb843ba743a90a1f93b52c0de88881c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)&(TxHz3`9+3XCZWd^h7C?LTQYhJg;}j3M_@h&oh%OxBI_c%3K0a>Vh3>rT>$pZ^rmT!5+_llt-%fzy@pRvMxoEmSL diff --git a/assets/meshes/buildings/house_2_7.dmf b/assets/meshes/buildings/house_2_7.dmf deleted file mode 100644 index 5a5b54616b300c36a9a10af0b9bfff924cf54d5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma))(G9{d3`EUjLQ9hJ9)0#rUFYP_RHNRMZG^Cb}_S?o^5?vpI_I( zHCGmVXoez}U%Jdp$J*d^f-YF=Gv~rq=lp)?$TH;wtHvGMpW!nsY|>|`CvT<;pNplV z&e-gX)VjH?|4GgBt-a3KzBZb%>1@MW-+;xti7^jbE^u_Yp(a=bu+|~oMe|z^v#BR< z#@r3B-eB^=To={WJmY=E(2-?gQCiQ~=^4YC8O*-6o;UMy&fzZjXnhD9&hTz LqI@M!eb4&>k1Tb$ diff --git a/assets/meshes/buildings/house_2_8.dmf b/assets/meshes/buildings/house_2_8.dmf deleted file mode 100644 index 38b1707c5b83a946cc4fab9e4dc991b5164f36b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)4K@P$&3@a}qAjFM7?P)v>JBy<>%YaC2Q^$^%YLC}*T*er8tP;2VzFh-1oD=3a zu`Yh_vga2qOUYwD+wbWc7|ftms<+a& w`Ak3hEqd$cUHVY~-XQ`LSM#3Dk$SyB^H%DW-0<)_^J%ukm>8D&A>Y5{19|0Q@&Et; diff --git a/assets/meshes/buildings/house_3_1.dmf b/assets/meshes/buildings/house_3_1.dmf deleted file mode 100644 index a36cffe899cefc502698e95655238bdeebb2745a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)&Q4Yc|3`4_BxCs$L{Bb9aPVB~AmUTd+t&RPhb$z^^b}_SiJo|dzMz7V~Ona<& zpsnf`C;wX(o;a>PdhF*}LaSBz&dHnE671S4D~&PV!Ziz~bLdgvRA*Yxf)~rIZ+)G& z;>fqxZdQ8GcDfHk8rRU&XKXIg#Z4nN@(!90W%_Z3YiR1{ot|h&i?x!4#(PN(9IDO( z-#PT+#%7z(c{GRCv*hc`Ym@uXkXvQ-ZOb#yUSlE)Z|cd(#!AntvT5+}^n3Ydo|t-n xXY+PnkF%_}I*)vChe}PX<^Qhc)hu~r^MC1;Y-J5xR{uB1yen?vmGh`^-Uln+WpDrh diff --git a/assets/meshes/buildings/house_3_2.dmf b/assets/meshes/buildings/house_3_2.dmf deleted file mode 100644 index b78ceb508a8daf699d57c875c28d4ba1c66eb9a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmZ{gQ4Yf}2t%`z4NcSjcBdVEcEA+U1c?9-Lz=$7pYa%Dyx@zO*T1JnV@-#V(I<1% zPxJDm)6PB=Rm`$V9T~js3x>{R=IKtSUG*IrTp6{=u(R#s5ST1=06Sf~H-=7(eD0&p zTrBOZz*MKsWyz%r+=6B+Bx~Hfn~XI)Yj5Y792$LdHpx~q06I*wjC_x3=2LTE=%%*L z)_m@u5LWk%crRJir*0D+oHgGkw$7dz?pe81YQwe~=sqsOTGeY^v;Gjg&j z{^>OHmzO>1a$byDd&PW4wO2aL3eG`#>}=n`S}c9B-0rP(WDM#QSFGA0ZF*z<6Q9T4 zu1o#)IBAX^*@?$!h;`OT)uX$f;?k`SJn-$|I(c(Gw5o$=WODm|V(3h5YM`Z;890mK zltI>!hz;v|D$cwRzid=R}-^^qAjfP>l1K5ojWl<2d&i z1I}wc>#pnB#ZYiaQuRgNX{By5w z^E_(OrOo0WN6#y-YH+2W)ttF#vBzvK9KFo@z~LRWafWiV;_)6t^v*bG3US0ro6UeN zUOT=??5Enu6@GYh%wCh$=~fG9S-CIrT0NfVa7X3*omGn*-px|_`XV>q!_72r)7a=0 zD=(Tjg|zG|X@$Fli!+?)ey_YG{4H)ZW2fqjmh77gFSEz9v=;77;f~;1-8Wf`RtU7! zna8=o+WNtm9Wz$_qF-m3aj{?Fojb*@!ET=O-;k!Wpha(%Piyk6=;hTK#-{ee3un~z HKHd2b!_slN diff --git a/assets/meshes/buildings/house_3_6.dmf b/assets/meshes/buildings/house_3_6.dmf deleted file mode 100644 index bb150cf015061c0ce710584cd8cdddb9a20d5536..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmah`!4bnC409)|uh;9ZJ9U(d!f3Ss5kZ{9cMe#VWCHK+#~x<(ikzc(tAEe7den*m z2bRShkDgar^vJ7z-fGSzrXJZ`^62H^Lmss&w$4CJtZKr8q1ucG3;`bF49jMaTeZI5 ziTa_p@+yD%Oq|{WHsRhH#0u(2)~&mLiIcZ?j`xh7@~Cw;+ak3lFT>!YIJLmwg#^Yx zT_O!BZwY*hRIgx6{|ioySiw7+(OGTADEj6?tF!ei!y>dMZ^Sc?eryUjNC{$RXI|%u xboeRf&QJ9?OEy>iDnEFK=$LZ1z%oD8@_d%u6}<+(&p_?5rV%t9Xx6l!K@$>wc>#pnB#ZYiaQuRgNX{By5w z^E_(OrOo0WN6#y-YH+2W)ttF#vBzvK9KFo@z~LRWafWiV;_)6t^v*bG3US0ro6UeN zUOT=??5Enu6@GYh%wCh$=~fG9S-CIrT0NfVa7X3*omGn*-px|_`XV>q!_72r)7a=0 zD=(Tjg|zG|X@$Fli!+?)ey_YG{4H)ZW2fqjmh77gFSEz9v=;77;f~;1-8Wf`RtU7! zna8=o+WNtm9Wz$_qF-m3aj{?Fojb*@!ET=O-;k!Wpha(%Piyk6=;hTK#-{ee3un~z HKHd2bsrG&O diff --git a/assets/meshes/buildings/house_3_8.dmf b/assets/meshes/buildings/house_3_8.dmf deleted file mode 100644 index 675c68de43860d4f838342de5dfe6c95601c0e28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)3NfH7v2#hZiEz6sKny2|R(?B!8WYkn;q0>v2$Ll#RV~qRkt=+8Nt~QIzIbpyR zv+X+m;L)>+ymBq7-~kh>BiAwTqOEe17QB29>N?glPzR5s^ZeJs+O2A=-ypWM(TKb}qB;D=w) s%lf{>4}!@%G{?y0eNm(1EX0bIZ?JePdIjGzP{WV!N1kH3Ifp~;2b8aCG5`Po diff --git a/assets/meshes/buildings/house_4_1.dmf b/assets/meshes/buildings/house_4_1.dmf deleted file mode 100644 index c3349b074cf9b614855bc6a979a030b13a693241..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmah_TXF+22%|U2P0D04{p+1_^dcFt+O3l?;|25puOGiZ@f8vGI_G$PuYPhyOkEu6 zXJNbeq!a(n3r;%b?47+=n9p!MYTQq{;e?rSbdBx2!YHX33indu?@~J7JD$=Y{QY)b zYFbM}?&s}v)L%Zji^JMGSguN1=EBsEt_$JPIWO)XmJ1oa{_$3r`gzkA7~Il^d4cgw z8-otv^Ps=#&`ZZ6kNKPju(7Kb)G6}Rt)?*gHuux+=sQoZG35m}c*)5 z^U?#0VQ3NLvNL+sox$^6Hr|rId@JqrH>KV`xf*GscW~#Mz0|`CO&x}L8(Arj?)q7+;`U~H34pRd2`ab4H1atoXN_=%gIRDgM! zx1UGgCtiAf3WbE0S@FP>i(g=xyu)UB$4jpPCwP-B-wktpV!9VUM9d<(_KvsgO-=u% z4XeFiHV3KqPFVK7cT)UJJb7(Y<-!RRY{6{~3Zqw6KgV?zE>6C=hG2V`08)`!ZnM^_ zcFqCQ^j3?{2n~K2VCi?o@9n&L2Ry=>ziJQN?tj=3thuL}D86WG_x26SLfU*Y7<>ck zVQR=8rbc;s^S-xB-7B=RTzr?^$t6VkJh7&l*Ne7(p5kj`I)5b^!|K|uQA3qp1mU0dfw`d zwKMWrnx*L9Pda6`qdR#?q)QfSt+`_Dygr|F%9_YYX2vr+&&ajk7a1z|Ug>=9;jwS( zOmmaP+L2#OYtHo&PZqw@{iZ2Qw(;_c<+lRUy3!wz zW2Cry$*2>fj!*t;3!#KDiQ8?f|UoKJIJr*CkW;T?5mGU?c>BGB=% z5@UWov3to_|K&+DWB)&{@-j?6(5Hs8(QAh1r4)OAs+hFyCG$M@>b|4y%RTqHc0{k3 QCol6^WLbPy9@)zK1u&0yi2wiq diff --git a/assets/meshes/buildings/house_4_4.dmf b/assets/meshes/buildings/house_4_4.dmf deleted file mode 100644 index c49548905919438e759ac7dd9860aead0c6ed30c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmZ{iQEtO93`4z>O(=%_?M^-VBwEjAQpZ5zh<>ExqCbDX<78(qwSBXc|U7v56fq{Xc1i?*G69`6h1S>8i^Dmx$6y@%(C3CQWgd*Zw=t|v`? zvU`V>H#KT{O3xQM9J=oprVmQH=rIq_)F(CSwyg~vZXM*uea1R-4)2JmQx^kw(v;Kx zOZOJLe3`-WywUe{&U?rcnbY~=N^I?^Mw1=bAsckJTEivQj(cxtE#8;kQ~@7`jK5<--f7 Lx(@Sxy&P diff --git a/assets/meshes/buildings/house_4_5.dmf b/assets/meshes/buildings/house_4_5.dmf deleted file mode 100644 index a6501df9d6a9b7ee6605ee3d39a95ac3c7a9fa25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiy>y5)O41?WGvdIaDqW^9ukI)e^>XEW(GmeW2a3XysCFk+{dzD8iVqU-L)N?v!CNGI}$)eSoD>j|`^GT;(6@8MKab@d_to?b>L*d??&gTw~ zy;EnJn=IOn{9>v(*F!v6_|D8PnvTgXynDs+U4f~d-C8Cto$n`efZTQR9#P60OLavq z-HxHn(7Kmedc~+?keyhCt3NNE4kmiFV$dS98|0$m(Y%lWy!I zIRh6i3$dKJc`xf+vyOh!)R;3q^>aVZveS9L)I)cR&ZIq1>lEp8hSvvK? SZi`TI{Wqkm+UNcDzx)H6w&Lw?BWs@rsCV5z1Lo`<=nrYbeh#LrF!gI%uf(PE^I{HAyH4KBhy$s9}T|K$zQu7DW; diff --git a/assets/meshes/buildings/house_4_7.dmf b/assets/meshes/buildings/house_4_7.dmf deleted file mode 100644 index 160e5e1f2c1e1ba30490d0266eb2d587fee68697..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiy+pWVe3`5?O6EpGe#zS>{(pD^HW zU{n0yx#uMH8ps6?ezMO|*D&xRrn*TB9(y*P>pIqJ@SN`}uB?6&4;UiP>I|b^Naua2 zGd)qwP1=b^e*3sK!>rkA6u&mVtetoz-{#Dm`DHC;bLjH^;yq5VGcE4|jV}0kWWR-X z#L~R;N?nMMvzbtvu&za_gp|`hC`MhYi)5~I7!P=a=+1fu<~?H{k!ISlf9r-0oA&0M zLBi-MC%r(Aob?Q?_Y4d{KWqe_7P8Nodnh*f6{XK$n3a14U;RATOS&8I(%;uTKCgLm AasU7T diff --git a/assets/meshes/buildings/house_5_1.dmf b/assets/meshes/buildings/house_5_1.dmf deleted file mode 100644 index e01e4b0f4e8a7b9d7a5440b1424251d012b23da5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)3?F~XP2*gd?L}HBp+{sZKRgQ9$VxLM4N%*ymXct5x+~M=rg^*s-0LnA>!ks~4KC!;FHCb%b><^whdn=Unr4 zI@hta$1Ix02o+!WuU}Eyk>@*^ld6T$+4y9m4Km0;D3nRI@c->Zj&` z>GbGj58m8|j@b8&_}^WJzH~IU_D}D|p6)<0!=mm*4ByF{cT+8NyOp<$@WN9^Ut#LV zJxqfVJ$XfMa0M)DGAH_)XKL{7?6gmc6?VS2?L#fyzX+CEs)1n=_nlyKPMtinu6}q#Ihu(xj!G}QcAh`8evxJ_qFbu z*O`NdTj8HhnZLaBq>DVOwdRV;8LPR{DQoi_>ExZcc?Pw(@OXxhy(=9YKqs7Ws~OUU z*ZP~}JbJS(^wVe1v>x2RTWyFlYG0~rw|~V;*E`2|rk8c{?tX`t^% H`(f?}J@k92 diff --git a/assets/meshes/buildings/house_5_4.dmf b/assets/meshes/buildings/house_5_4.dmf deleted file mode 100644 index 7eaf2865f0698065f45a00c94ac37dfe7429b49f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiwQ4Yf(3`5z;hNfwMyHk(CQD+AXE=#vaX~~P7&_3Uwb$A!<}}p47hIgKIsMq(?Zryp-<}KsSfjA54F~7~A80RrtMH3ku z$GOKCaD;ma=yjIO3!@&?CwsM%^CI*fr88*@G~AudbDQp0l7BU4$$)tZ-bG&N$Rhau G`i>9y?|1nC diff --git a/assets/meshes/buildings/house_5_5.dmf b/assets/meshes/buildings/house_5_5.dmf deleted file mode 100644 index eff99b288a07dec6b931e21f1fa9e348c94fad2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiy?TrI52t>I~wv(Xflz-_dC2R>PH9Xs6vz((t@~#=)0QvZRKJ3TL?s2a1_MX3P z{Y{=Vbmg5`Pw6l_PCb`n-Q-0P*EH|B`bk^PwGT|?a<4oCKY7-6UTJM!@QUn(sT?^` z`|q^sg^{1T`O0%YN|i&aabZRg?V@`xNNaOKQ$B3-C0*Ps#HH>?Epzf7Zg$2|4kK=- zMVrZHFDyQ3a0D91IO#VMmuCdA|DL_i{5GTchIig|@$X*EuDi&ZcSaL8>v4H|JUA(& z(SNsdotvz)pBQ@m*Dw3oWj8nXYkY8jVrXKI$o1bqV-IQBi*B6pdE+)Y^+Idm;~g)2 Q@``IYNYvC1?TB;w2kZfU82|tP diff --git a/assets/meshes/buildings/house_5_6.dmf b/assets/meshes/buildings/house_5_6.dmf deleted file mode 100644 index 66cf599382ee5341cb0d26243d6df36a59bd2fd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)4(X9g^45O1Zs-F7SojMAmFk0gTL*T+|Bjq5D?I5_n*R$M8DG$vxnt1)b`&zY* z7;s=&eB;scKP`IXnV)#gxx}JJHkUklRrMi{+8x_xpeAM-^*fAF-xGv6 diff --git a/assets/meshes/buildings/house_5_7.dmf b/assets/meshes/buildings/house_5_7.dmf deleted file mode 100644 index d77782b777683ac16d6f44c64af82353dea70a79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiy>kY#o420duimIyrxfgzAuBEjeHZ1Q-%Uv@LI2i6!Vl>Boq z_lVqU)TyoFAE%yIUe?6rexc-=E6w*<%@wC!5q-qTJ8Sa{=F+kUJrv%%;;1pmDR$aw zhS=;4{hj!Jtj%2Jr^~?98nr;vD-CTL z>%C;@l}3(1Enyj#` L&d9<0>6`xm(j|&n diff --git a/assets/meshes/buildings/house_5_8.dmf b/assets/meshes/buildings/house_5_8.dmf deleted file mode 100644 index eabf0f664a380859abce6bcc765d582de8e4cdff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)3TM_~>2&*R(9mhZKv`6tM9!)|C3v7Kb)9n%x($d@GK2BqdtF9K8nQ!O0KSlS1 z0XJ-x>-PtbJ*&tw*CGoZFqwJyItE_E$~S4j%lDwJW8DLJU=RtFwcm;d3}GJgH}2K3 zl?U}Em3<~zi(2OyzkLeFYrqOFvk+LDUu(H*zr07$Bpy9B^?d1KZg*?G8ACsEvlbY5 z#K1!oZF)=c*vohj$lkwWpFAM55a08r7<4Nwz57{0uG*2_h`gxdC(ShQG{1j*LznvT yY&L@*{fb`J_bvS(P~IUNBbWC@j)k)jD_YKAF)Q{8zIz}?KhBRl!%#%+;QI!=-glA! diff --git a/assets/meshes/buildings/house_6_1.dmf b/assets/meshes/buildings/house_6_1.dmf deleted file mode 100644 index 9eb483a1351ca2fa0481b8f0c2699ae4009c43cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)3?F~XP2*gd?L}HBp+{w`#O^$MuVxLM4N%*ymXct5x+~M=rg^*s-0LnA>!ks~4KC!;FHCb%b><^whdn=Unr4 zI@hta$1Ix02o+!WuU}Eyk>@*^ld6T$+4y9m4Km0;D3nRI@c->Zj&` z>GbGj58m8|j@b8&_}^WJzH~IU_D}D|p6)<0!=mm*4ByF{cT+8NyOp<$@WN9^Ut#LV zJxqfVJ$XfMa0M)DGAH_)XKL{7?6gmc6?VS2?L#fyzX+CEs)ax+7p&k_pfEtK3Q{53D`RTK&1Vy`s(> zd2%cK(kb)G%bs+eXRX#;aXDi(S2|@? zCOMD2S?Bucv(rS6+>W=_5NE8hRJZQ$wFZ+3ym5v-y&9}pyosC}CrgtGnZ@qd0^j6-O*tVF#f_cUotNU0Jh820# GwYgtQS%1j@ diff --git a/assets/meshes/buildings/house_6_4.dmf b/assets/meshes/buildings/house_6_4.dmf deleted file mode 100644 index cda4f39bf86d8348373d7f3620a46d2855ea7b67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiwQ4Yf(3`5z;hNfwMyHk(G(Pjq>E=#vaX~~P7&_3Uwb$A!<}}p47hIgKIsMq(?Zryp-<}KsSfjA54F~7~A80RrtMH3ku z$GOKCaD;ma=yjIO3!@&?CwsM%^CI*fr88*@G~AudbDQp0l7BU4$$)tZ-bG&N$Rhau G`i>6kY#o420cHvPn@@^Boq z_k`SQ)TyoFAE%yIUe?6rexc-=E6w*<%@wC!34O%LJ8Sa{=F+kUJrv%%;;1pmDR$aw zhS=;4{hj!Jtj%2Jr^~?98nr%C;@l}3(1En*p$` L&d9<0>6`xm`DTJS diff --git a/assets/meshes/buildings/house_6_6.dmf b/assets/meshes/buildings/house_6_6.dmf deleted file mode 100644 index 75e4d9af7ef65051df4b11422a3fc25c53c60a94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiyVXgu(2!!!u5@Y=5ojgj9vPY9?JMAp8k%VU%z5(L%`F`2W%pQ^FIDFKf`}jny z8g$l!*ng>msW{Huj{Tw+3c0TNs5y_?cJ6z?WKL)44){^4R(YxQeZe!-3np`@5qW;4 zWiJ@|@iyPJ&O!@Hy?iO3c~aZ9yV=XE}~pO_k1kGe%x^VG}xOn%SmRn}r213r4Wv)2Hk$9d2^ GviTS6c!*g5 diff --git a/assets/meshes/buildings/house_6_7.dmf b/assets/meshes/buildings/house_6_7.dmf deleted file mode 100644 index b02e05153b2391a7db49eaa1aeb77697c4e8de0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiy>kY#o420duimIyrxfgzAuBEjeHZ1Q-%Uv@LI2i6!Vl>Boq z_lVqU)TyoFAE%yIUe?6rexc-=E6w*<%@wC!5q-qTJ8Sa{=F+kUJrv%%;;1pmDR$aw zhS=;4{hj!Jtj%2Jr^~?98nr;vD-CTL z>%C;@l}3(1Enyj#` L&d9<0>6`xm--?cT diff --git a/assets/meshes/buildings/house_6_8.dmf b/assets/meshes/buildings/house_6_8.dmf deleted file mode 100644 index 637bfa2126e3d2d4c3ac40d810767a8b81a1918e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)4Q5M252&*R(eLnxZ(~joRB+xLxZpwRWOPY|u_IN$VWsGsxr^U_l?dtnmbWa#? z!~D9gKX|NJMKhaPWWfU_o`>(mz>8SP;&9OtKbtooD>E6wbT@R&eo)z}oy;$z6N$J&Gpr=&`9M`eAOpHQ$V(9=TZy%<9Z~ z;30}Oeaoy39uBhCH*La>JV3FKx#vwW=vG=_i2g2)>MHt7Eim$Mjz}}@*uTD^!{KE1 rNA-$c*8Q^AJkz2>qFMyG?DwZHXRw$RYk6f|B~InvAg{dN*LV8>%0qjy diff --git a/assets/meshes/buildings/house_7_1.dmf b/assets/meshes/buildings/house_7_1.dmf deleted file mode 100644 index 0d26b2b4693911a46dcc0a837e63baf99abb3b45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)3?F~XP2*gd?L}HBp+{sZLMUHZmVxLM4N%*ymXct5x+~M=rg^*s-0LnA>!ks~4KC!;FHCb%b><^whdn=Unr4 zI@hta$1Ix02o+!WuU}Eyk>@*^ld6T$+4y9m4Km0;D3nRI@c->Zj&` z>GbGj58m8|j@b8&_}^WJzH~IU_D}D|p6)<0!=mm*4ByF{cT+8NyOp<$@WN9^Ut#LV zJxqfVJ$XfMa0M)DGAH_)XKL{7?6gmc6?VS2?L#fyzX+CEs)@~ diff --git a/assets/meshes/buildings/house_7_3.dmf b/assets/meshes/buildings/house_7_3.dmf deleted file mode 100644 index af0bd704366e6cd0ad94df7be3928f5416d389fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiw(GkKh3`4_Y_&AO~c3>1n>nI%sKPMtinu6}q#Ihu(xj!G}QcAh`8evxJ_qFc3 z*O`NdTj8HhnZLaBq>DVOwdRV;8LPR{DQou}>ExZcc?Pw(@OXxhy(=9YKqs7Ws~OUU z*ZP~}JbJS(^wVe1v>x2RTWyFlYG0~rw|~V;*E`2|rk8c{ZhnWC^%=XLrIRLe H`(f?}SiXbl diff --git a/assets/meshes/buildings/house_7_4.dmf b/assets/meshes/buildings/house_7_4.dmf deleted file mode 100644 index 442b265f788d7bf0da6a5b96aa761c3080ad402f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiwQ4Yf(3`5z;hNfwMyHk(KQDz4WE=#vaX~~P7&_3Uwb$A!<}}p47hIgKIsMq(?Zryp-<}KsSfjA54F~7~A80RrtMH3ku z$GOKCaD;ma=yjIO3!@&?CwsM%^CI*fr88*@G~AudbDQp0l7BU4$$)tZ-bG&N$Rhau G`i>71$bdNj diff --git a/assets/meshes/buildings/house_7_5.dmf b/assets/meshes/buildings/house_7_5.dmf deleted file mode 100644 index 275dc21d31e535269417f1e7605f2cad5370fb23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiy>kY#o420cHvPn@@^fgzAuBEjeHZ1Q-%Uv@LI2i6!dl>Boq z_k`SQ)TyoFAE%yIUe?6rexc-=E6w*<%@wC!34O%LJ8Sa{=F+kUJrv%%;;1pmDR$aw zhS=;4{hj!Jtj%2Jr^~?98nr%C;@l}3(1En*p$` L&d9<0>6`xm2HJ*M diff --git a/assets/meshes/buildings/house_7_6.dmf b/assets/meshes/buildings/house_7_6.dmf deleted file mode 100644 index 64a40b7713167298911f7d21e664758022e3089a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaiy(G9{d3`E0ZSP1dQPK?q~GD=3_F3BZM>VhS=@%f!yTAuG$x}}sJ$ThOH`g3ph zg4%1;sYUUR)68F9_QchB)@tpQ=4V8E#c5W-9C7mQ+P;IewCceOh4)4rH3m7wl@{#~ zTfH{liJ!;b&Q*T9EKKiFTXbs;X_+-rb?eTnbaAtDe$VWAPF}N=4y5XWv$#mZn8A84 zS$d_BV^GV;#B|?MoZkUr`Mvbkz@6OHj!v~5qv(epUhUqWWsHC~xo;$H^l`{!m@cGU zJ@dZTS;ssv#paHydEU=wi8w#6^59O_#~OcYl5(p-FSS)Hjn$?!!Blai*t^b_x%6b z-{e_CSKf*Bln%4w)N?u3OIhJuWYg2PcIz z`tNqGbCY%U6GN|G{j#53c5`#T#s~KiLlb*MuKxxadq~S(bmNTA8@I`+7g`G+?|9*p QS6s_MqNaXmN1Ug>0qpORnE(I) diff --git a/assets/meshes/buildings/house_7_8.dmf b/assets/meshes/buildings/house_7_8.dmf deleted file mode 100644 index 9eccf6f73164da4d72478feabdf152285ec9afd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)3TM_~>2&*R(9mhZKv`6zO9z{Y43v7Kb)9n%x($d@GK2BqdtF9K8nQ!O0zeM+h z0XJ-x>-PtbJ*&tw*CGoZFqwJyItE_E$~S4j%lDwJW8DLJU=RtFwcm;d3}GJgH}2K3 zl?U}Em3<~zi(2OyzkLeFYrqOFvk+LDUu(H*zr07$Bpy9B^?d4LZg*?G8ACsEvlbY5 z#K1!oZF)=c*vohj$lkwWpFAM55a08r7<4Nwz57{0uG*2_h`gxdC(ShQG{1j*LznvT yY&L@*{fb`J_bvS(P~IUNBbWC@j)k)jD_YKAF)Q{8zIz}?KhBRl!%#%+;QI#GsDIJ` diff --git a/assets/meshes/buildings/house_8_1.dmf b/assets/meshes/buildings/house_8_1.dmf deleted file mode 100644 index 180481bfebc52296f171aee749170d7068e4a4e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmah|TMhz22*aCr6VVv|ypuW#AEi+v({b$t5Nx#r&&EmYUMY9J*_ZOJe5}c!09~ppqINk!nzi+vk{1Kt1tG zPPso|#GBu;y6>O2`jH>JO-wAgbASKVB_CSt55`4{Hp8>}{l9_H1EccI(=X5a1!-Dc AQ2+n{ diff --git a/assets/meshes/buildings/house_8_2.dmf b/assets/meshes/buildings/house_8_2.dmf deleted file mode 100644 index 611d63ddf2b8de1fee9fbed784d1e06dc12dbc28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmaJ<;c|l^2y;)ithejGzEdB42?8S1<_?jN;HT~H>p8y07!O7RX8rzl{)f46#)~@v zla%J9%b6d%YNZY=7~4GO*jd2bo^&~@+#`*RGi`93xy_S_Tq1NNPP*+}H{CenHBW%8 z>kXVcdDTkZbxIwZ#+%|c9L=$UC)q4fUWyNPQH^j&Q{*uASTc|!pm*wqHP&m6%}B?kY1s? zRj+ZRE5~vIOpMU<-^2JeZyJ4dZ`W<}B&F^joC~co$SE6lJ6AqM=(w$3mJ3+hemCos K|3S{nbN>Ks99rrC diff --git a/assets/meshes/buildings/house_8_3.dmf b/assets/meshes/buildings/house_8_3.dmf deleted file mode 100644 index 6c57db41daf81c020f395c7105cc2c3dad362361..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma));SEAD2!wGm(HQ@^gQGaw8%>V(nk%o3k{IRV4qEEt^|Xtb-QzQdd&@u9&TnSQ zk_TJGFWu<5Fw=_?b;-QtoJ*!H=!K^0*vsS|!&}(OOO~EE%Lws8Q+1g`EW6sV>V<7+ zk+|g252dODt1)SM5p3e#3S`_f^IcEsw9fZ9F>i!Dk2u3S81wN)8wNME>P;4VA%iZ1 zZ{(5jzM@MXgxqQ9b}YGgVVlCItR=zVTX{L>s5@Yr@EX1GlRB31z1_Y4KX=uSXRGg# v{KpQUsXFbK^WuD`=#1J!_EP()ckF<3qo`ihTAz_D?m;hS>i@vlZ`}6_Q$S}b diff --git a/assets/meshes/buildings/house_8_4.dmf b/assets/meshes/buildings/house_8_4.dmf deleted file mode 100644 index 6e31cd48ae62b973fb37594da9b8240dc9e1fb7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)(Q4Yc|3`4`o2ng}VopyBMw2r*26-1i0yxMM?y*_Wdnb|X*a~(eV<39PrOj+_^ ztNNv@%!Qd=EK!%tN6&r9G=g4ex{g^U_b6{;D=%4k;w)9-g{JGWhgfE{W8Di|Y0RA%(hR?nGk7~G|WX6lk*E|bOAD9JP4 zS9FyHhH}YoY`aGqhnJuA_K~;p*51%eUHR}4%y{P6L#LJfh9Uo-eOGyPHkscpPyIOa qN~d|L58b6ED{b_+-zrbNH3Qxki}2wIcB)`i?QY5CpBwYQ9C=?3N@IEe diff --git a/assets/meshes/buildings/house_8_5.dmf b/assets/meshes/buildings/house_8_5.dmf deleted file mode 100644 index 67ec1b554f4f39d56cb4d48b273007c1f1c59a68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmah{+YJIS3=5mE2?Zhk*ohGsfl+bNI&yO@M7q=2v7PJV{(RWU%x-w*`m~N;m%(4n zlnWl*s{ZLRb77{}Ths;DI_6w*8bPmXs*YJE>qu|mR$g-9!M|jQ*ELla*u}C}JFa@& zmRbi*u;h8G>YS@JX-3nziEq6@j{8i!%cM^GJdXp{I>XE}@EZ?tp3#PLH?`^w4*NpR zbx}N{2E_G>j#+s|(CxVGj2MI$yoUnkzLl4A_|L?d0k6@EPwKLdk59wPA1QL47n!nN zmvPRoJZkEBtny@Z-qWhnywJDF)xqGX<^MUZdFtkRjXE^dt6Cc~f|I+!nR*X0FZb^Y D0bFUC diff --git a/assets/meshes/buildings/house_8_6.dmf b/assets/meshes/buildings/house_8_6.dmf deleted file mode 100644 index 00e3661314681bc6ebf7ec34253dc1883570a984..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcmah{TMoi73=1bCAjBVc;wT(tMujrUncNDrEx1EuL;uYRg1qa{C%Q;*#ab<+p=#5Y6svjSRqY;l3Ipk%g>=!c5 z`ISe_d>^Yk8J%l^X4Yw5>V0rE&^c0%&vIm`m~N;=fPjh zlnWl*s{ZLRb77{}Ths;DI_6w*8bPmXs*YJE>qu|mR$g-9!M|jQ*ELla*u}C}JFa@& zmRbi*u;h8G>YS@JX-3nziEq6@j{8i!%cM^GJdXp{I>XE-@EZ?tp3#PLH?`^w4*NpR zbx}N{2E_G>j#+s|(CxVGj2MI$yoUnkzLl4A_|L?d0k6@EPwKLdk59wPA1QL47n!nN zmvPRoJZkEBtny@Z-qWhnywJDF)xqGX<^MUZdFtkRjXE^dt6Cc~f|I+!nR*X0FZb^Y D=W%t~ diff --git a/assets/meshes/buildings/house_8_8.dmf b/assets/meshes/buildings/house_8_8.dmf deleted file mode 100644 index b29554d5fad9e0dce7f5c98cd7e04eabc7316ec8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1332 zcma)(Q4+#12t?z_M91l$ck0nRnk-=vXtZV~ZQ1N&ll1Z2#$}9g*V)Ex*8A0U)JZel z>qegXqUQnpWMCR|pbia?1UY*-yYd+ad+)!{RvE#= zFYQjC`RG3C`CUATE4s{u(6DdSqMpm~4BdUPfRA+M(36ksE@QlOvNo>gqCR1bR}cG@ zOtR@;(pPc;N!v@(zGlFKA@-~f)xfP-W*_##4$2O)`bi&`?ai}g(Y1ebGs=7B-unMA ueRa=lBJ1;(e( diff --git a/assets/meshes/chunks/chunk_-1_0_0_0.dmf b/assets/meshes/chunks/chunk_-1_0_0_0.dmf deleted file mode 100644 index 484beafe7822144b44788fd302204a2cfa8a08eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26172 zcma)-!Hw+55k#qj?leG$HlZDmR00Iu1hfe>p-rGEZAzO$Q&ca1rY5$2B)A3eH~2Op zUvg)f^Y8!uXZy>xZGZdg{Kua2@4xW*&!7Jci)%9FKZ)!#xpn4xAMJnSw2_~DOcvS6 z%G-5a4o0uK%!@PU)fvgg!sx>8x-Pfw;v8psPw~QHXYqDjms@vnj!$|&;)T(L)$?{; zms@vnj&FLu;)T(LmAC7<+`5Z%TihGr?dR~jIKA6s3xV7Mi*AzuIqB^F3#~x?^C=my0G$gU6)&TagLGR zAzm0=Sb4jy%dNXO$1A-r@xtiB%G-5aZr#N>j`SYlh0%qTx9hsxx{GtX)B6@Lj4rIa zUDxH-U7Vxlp5lekh1GxWx-Pfw!ixbGpZT28!+}fK#ygAq5%KuPbzKe?XZ-qbj_9$= z%#=5JbSEos*NyCwi{=LISb4jy%fWC|_cD%+|Gzx1{48N~VRv1Z zgI(jN>l}M}ck#mL!phrqU2fgQIUebKh!;i|R^G1ba_cV6@l5YiyfC`3@^)R9TX%7e zk=`L*7+qL-yROTvyEw-yy)W^?=)%g|bzN@V#W{}j9^!@3g_XDKy4<>pbG+007B7r0 zth`;<<EV|>q>vAxjqrBgAeCND!T*n_gmNbf_uFuJhvc3qcScX5tqdY|Hj(S?<_ z>$=>!i*t$CMgWULeHdu5gyX(3fOn3gK<13CU*|jjbu<~|YmxJM`?qwWX{wz27S;FYT?z%1q zyTt1pdwO^A!sx=v+jU)T-NiW`>3xV7Mi*AzuIqB^F3#~x?^C=my0G$gU6)&TagLGR zAzm0=Sb4jy%dNXO$1A-r@xtiB%G-5aZr#N>j`SYlh0%qTx9hsxx{GtX)B6@Lj4rIa zUDxH-U7X`g?QX9=SVyX(3f z>=LhY?CIUb3!@7wZ`XCXbrn_gmPVZa1FuJhv zc3qcScX5t0y{C9#bYbP~x-PfwGT#I-FFxn@n&aNZurJ=}|Bi^oKg{FQE?tf;r@GFu z%}mT2Kl5PGo$Rjba$+Ub96#N-UmRENa?RXlUK|)% zSb4jy%faYX_cD$xzpI;kS7CHvcU_l*UE+0)J-xelVRT{T?Yb_v?&2Je^ghH3qYEo< z*LAsd7w34U_bFZ&U08X$uFI{vILAou5HE}_th`;<<3xeAMi*AzuIqB^F3xeL_Y^OTF08y=*X7n-=9?hq#pnE9 zbKKuh*oAlcuMx5Mhk2aZrOVOfRM$DSnTdJhXC5rNlihV)4)%wgjbkJm;)T(Lm3M2p zE(hDBJF=^eGubI#7+u&kFHYBWIT()Wp2qP>_L;fwyf`qru)D6y!A|Ki@0;_=!F^ma zr|g3NiLT4RKGKc(IjvHQZ&hbd^L%cA$u<~|Yms@vnj%RwG;)T(LmAC7<+`5Z%jPwri!sx=v z+jU)T-Q`HfA&z&l_rmDH%G-5a4u+$;&T*#q6fcY}?5^u_>n`*x67@& zkfW=PGubKgV6pRL`YPIU6=c97vmVohInCgVdZuEb-8sH=Qz`QiWe3;i?{2# z+`6-KeA4?7FN`j%p113|+`5Z%eAD|CFN`j%yj|Dj)?J+AO7A6J7+qL-yROTvyEsSu zE>B1NF4yn#yr&B*Z`XCXbr)Q@k*`u)D6y!E|Tlt&Wjwh!;i|R^G1baxmT5IbP{~i5Er}R^G1baxmSQ zd0Wog@XT{0JH!j43oCEebvc;s>>Tg(zQqfp3oCEebvc;s%)Bk<)$^XoPVvI%!phrq zT@I!@^ZykVpLphRe`{e6yz_cwj;!mt9E?+4_x{^vCg#br!J<3aUDxGcyko1&yw$;d zT;k=PF8`13x-JLXr0X2f!y{f;Tz{hLaxqi7albg8^PYX4;)Rig)$?{;mxIx(u5*l; z!8^nYqYJz1x*SY*X5Q*}C3}e%Mi*AzuIq9z-Pt*g^d91c(S?<_>$)6FcV^z6^Y%HD z^G@~_FN`j%yj|DjV7jw&oasHq3!@7wZ`XA>nC{H;!Qyky}O|?)ol?dGc%#qpZ=%zTL#Miy4j+jU(IMz6Zgam)y zgK?_s9NT<{#k}$JY_RA~cGq>e-*z#Mk!*+;Mi*9Iw_lfAcX5t0y{C9#v9ox)uFI`E zJI5!zAMwKI!s>auuFI{vIL9}=U-81|!phrqU2fgQIj;0x;)T(LmAC7<+`5Z%Z2bPr zYm@IPj4rIaUDxH-U7TZ2?=D^#U08X$uFJu6XXf#2>Ubo3h!;i|R^G1baxmT5IiBf# ziWf!~R^G1baxmSQc_ZhIIg`VET;k=PE}8OnU6+ID&dw1%JmQ7LCEl*wmCn(AM#y=(cLC1Z`XA>nC{HH)v+hr#S5bgD{t3zIhgM39FO!q z#0#SfD{t3zIhgLuyjRY9&6%8MvZr`qbYbP~x-JLPotvAyNnR&0A zSI^6RT;k=PE}8OnU6+ID&dw1%JmQ7LCEl*Uq1a%faYX z*E!Ca!F!4qMi+M1bvc;s%CWvLRj=U08YDeqCyF1POD z9N+YQ#S5bgD{t3zxpf!kxYB!x7e*IW-mdF%>n_f*&H3@&lJ6>v?lxI@yROTvyEw<5 z-d(&fy0G$gU6+ID&dlT4)bU965HE}_th`;<|7gpY`>vAyN**RY6eTf%F7gpY`>vAyNnR!RftLNoDF7a|tmrQxPuFJu6 zXXl6>9`VBB5^vXaxtJ;4xL+LSyl3VqUKm+eJ#W`_IT*d_@_Ph}&&fINZ!HXWT$v;5 zx-JLfuy=gAzvuZ*+=lEoS#&46>$==;yBNnvHpB~~3oGx|bX{)U#W~KLcZwGlJBzpL zy4<>pb9~bK5ig7`te&^)y4<>pb9~eL6)%h~th`;<<nC|QxdwO^A!sx=v+jU(IraL>wBfSst!sx=v+jU(IraLq5 zo%8A)_DuE^FN`j%yj|DjV7jw&jPwri!sx=v+jU(IraLq5o%8B>U&&tLh0%qTx9hqb zOm}vUBfW=sVRT{T?Yb@p)18_3&Uy8`+{Yze?&*>#Z`XA>nC|Qx(ZeHNSX|=mx-J(p H|KI%|fwA31 diff --git a/assets/meshes/chunks/chunk_0_0_0_0.dmf b/assets/meshes/chunks/chunk_0_0_0_0.dmf deleted file mode 100644 index 8e70f8fdfcfd8e088383447582fede2b41731f34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28932 zcma)?~>?Z4-=k*~Z= z7TL+l+jU(IMz6Zei!$=>!i*s!C{`qbD9R3!kcblxd zUDxH-U7TZ2?=D^#U08X$uFI{vIL9r$H}S&g!phrqU2fgQIqvDbix);0R^G1ba_cV6 zG15E43!@7wZ`XCXbrvHQZ&QWs@@xtiB>VNOLF1PN&2Lmi#^Eso31DCLk&n)go#N!{=bvam^@$+)# z=bwJ=Ugk3qMmIh?zjR#=hNE_79y>Fyo^9hf`5DO16h;^Jt?P0y9MyG>J-xelVRT{N zx-Pfw;vBd1-oy)|3oCEeb-8sH=eVc$E?yX2Sb4jy%dNXO$4KuGFN`j%yj|Dj)?J+A zk=}=RVRT{T?Yb_v?&2KJ^ghK4qYEo<*LAsd7w34T_a$B!U08X$uFI{vILDFRL%cA$ zu<~|Yms@w4Q(|7cj`;WIGXn=MVI$c{7U{|2jGq@iZ(I(>sqV@Byv_lf*F0CUYs?$2 zd0=B+urV*rnYnY!8?Je}99?qNCAa0g>TdZn-Q;HqqYL}ibvf82Ugy};yNee_7gpY` z>vHQZ&T&icO}sF=u<~|Yms@vnj(d9V;)T(LmAC7<+`5Z%jPwri!sx=v+jU)T-NiW` z>3xV7Mi*AzuIqB^F3#~x?^C=my0G$gU6)&TagJAdU*d()g_XDKy4<>pa~$bC#0#Sf zD{t3zxpkNMNf7hmb-u4T?z0Yd;GOJ?A~$b9}m2vTI>vFJ5yw0(wcNZ^=F08y=*X7n-oa2_>n|NV#Vdd?*F1POD z9QX9z#S5bgD{t3zxpf!k80j72h0%qTx9hsxx{Gr>()$oEj4rIaUDxH-U7X{Y-luqB zbYbP~x-Pfw;vBE^zQhZo3oCEeb-8sH=Qz@Ph!;i|R^G1ba_cVhlOX2B>wI6wtNBdi z^Y4v!`rnz0>}2se^0mp)~DP9;|Sb4jy%dNXO$1A-r@xtiB%G-5a zZr#N>j`SYlh0%qTx9hsxy370|hvAzuym7xcuH5AkFN`d# zyj|DjV7l{V99uriCht`kU08X$uFJu6XXn_{yNee_7gpY`>vHQZ&T&icO}sF=u<~|Y zms@vnj(d9V;)T(LmAC7<+`5Z%jPwri!sx=v+jU)T-NiW`>3xV7Mi<84C8z7U+`5Z% zJk$FWFN`j%yj|Dj)?J+AmEM$CMC%N%?Hdu5g`_^?i*za~Wj*)DL7e*IW-mU4n9Bh;B z$gVn$WQTZRbYa)LI9=D}U^uFK7{@!=d*;r0abR>|-?}abJEY6JGv}3q`?zMVKAX6| z;L-hj|H9vq+v0RNy5z2Tamd9rJ`OT4GUbKEHQANl`()z!139{pbG*{~5-*G{th`;<<$==8yBNnvHpB~~3o9?XT=2>2XW!-4UC7Z@$C2!i zd9c`dvhsFams@vsj(2+B;)T(LmAC7<+`5Z%oasHo`}2JSqYK-9`+Wailk0w6Zr#N> zm=%|Jxu<)Hx9hsxy0ddc4^O;TKi|Lb_!;N(c3qc?nX^#@>?&5`!h1Jiw>$)6F zcXp0jdT-)|(S?<_>$)6FcV-^XrjC2EyLe%AVdd?*E(g<{onxeTh!;i|R^G1baxmSQ zc|5N=9?2fzot}AMbYUCUJYCo2V7jw&Jk$FWFN`j%yj|DjV7fE&cwTk9lD)(WqYEo< z*L69V?(7^#dJpl!=)%g|bzKgoJI^UGFJ75BkNd8L?Re+4XD-6?K8|!<4#ugjb8PeH z&VJjNS2-q&?quJ(F89kW#xar&@xtiB%Io&)a_cV6aisSUFD!NzZ`XCXb!X>zr}r&h z7+qLBZ`XCXbrg=cwuy5 z4dAqL5t-CnKncg$JpYLC~ zu<~|Yms@vnjw`*Fcwuy516=RGs;;)Rig-SYo~bX}K&@f_84 zjxjTMhj?LhVc)tg2h*LIw>lol9^sw8mw8}xVeHN6x-JLPot@*E-luqBbYbP~x-JLP zotd}iygi@emFy*67+qL-yROT@bZ6%{(tC&(Mi*AzuIq9z-I?DLEMDhKj{B~K-SN)r zo;k9v>vAwob)93&&%|wfo(&e=$-Z@6?w4JRVIVeL3*XYh*4urt5MrPIc|~d448tn_f5rS}pqj4rIaUDxH-U7TZ^^W*PD-m5UW+hpbKx-JLP zotd{f_GG(wVRT{T?Yb@p)195;mfl-vAyNnH*hpa37a=xu<&< zZ`XA>nC|Qx(ZeHNSX|=mx-J(pr5pE)<1z1<`3Ud)z03n63u7Nn*L67jj4rIaUDxGcy0dc}={>{?qYEo<*L69V?p(j8c%3sj z?zp za~$bC#0!g^#oKjVZr#~A-sydd7e*IW&)aofZr#N>&h(z*h0%qTx9hsxx{GsM>Al1Y zqYEo<*LAsd7w6dc`vAzux^cfap7WlWPw~RY!s_STbzKfdue#3hni;$=@xtiBzI9y=raLol zbsWhK@xtiB%G-5a4yHTT?=D{FOpf~wg+1}ki@obGk5jvJIl7$cI>(luiQD+hgGG0; zZ(Wyz9lEn|jATQ+FuJhvy8XJ`x{Grh={>{?i=D;WbzN@V**V_neTx@H7go>PbzN@V z#W~LOp5lekg_XDKy4<>pb6n}Y#0#SfD{t3zxpf!k*yj9rf5>|kMt7U6yj|DjV7fE& zR>z)f7cY!1th`;<^+{Yze?&*>#Z`XA>nC|Qx(ZeHNSX|=mx-J(pr5pE)~DP9;|Sb4jy%fWPK=Dl)WJumlhiI;o2 dWXjuhT@I!@J4f{Jh!+-@c)PC4#mxVA{|C`obGQHi diff --git a/assets/meshes/chunks/chunk_0_1_0_0.dmf b/assets/meshes/chunks/chunk_0_1_0_0.dmf deleted file mode 100644 index 5d16a93aaa8807b47435d367386076d40252f544..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25332 zcma)-?XBy`5kzUg0Vo89zyxfM0mJ_cCWpM#VRT`4U6)&TagHm!mv~{Zvv|9%%dNXO$2+}m@xtiB>Uq1a z%dNXO$0xlX@xtiB%G-5aZr#N>zUlpn7e*IW-mdF%>n_f*)#vA*+t1;>IKA6s$)5)&iM86VD@x8 z_a`@-nL%G-5a4u+$;&T*vo5HE}_?5^u_>n_eQ(mTWpqYEo<*LAsd7w34U_bFZ& zU08X$uFI{vILDdZQ@k*`u<~|Yms@vnj#qkL;)T(LmAC7<+`5Z%T|sBpb;hJz1Rb>xIvx%fUF+edKdI_a`@-nL?z%1q!%C| zypCV5?!5uK@J|1gx#*a#%fUF+edKdI_a`@-nL?z%1q!%CpEOj4rHp?z%1q!%VyROTvyTspm&WqQPujW0(`|6E% z`rnz0j_JA_j8ol5KF9huXTM#ZZO51FuIq9z9Mxss>Nt`e;)T(L-F00K#&cBnOvfn> z{^soRS{Pl}UDxGcII8O${0;G5;)T(L-F00KraQ;qda`&Ozh2#Y2=>7{{h!Q5$8=o| z#;LAzY%}vFH-4TC7TwA2x-JL%!_LMrk`3{~=)%goHC>m3ZPFdtRmYX=5-*G{>@zP; z*L67WnNs9l_Pq176ylLak{R{#mw>3jr+y%&0W4T z_nsFAMiy4yuIq9zde!|J$CjVfO+KqIy0E*h%fY_lb&f}RAL514g_XDKy4<>pbL{Ee z#S5bgD{t3zxpf!kIMREF7e*IW-mdF%>n_eQ(mTWpqYEo<*LAsd7w34U_bFZ&U08X$ zuFI{vILDdZQ@k*`u<~|Yms@vnj#qkL;)T(LmAC7<+`5Z%T$)854?7#jNH)X^ zqYEqV)^uGCwn=wnR~=WfOS~|;ul}~tKEw;73%l#O+`5Z%?CIUb3!@7wZ`XCXbr~DP9;|Sb4jy%dNXO$C=(!yfC`3@^)R9TX%7eS9)LKh0%qT zx9hsxx{GsM>Al1YqYEo<*LAsdm-_t2>-=1E+;1psn{NEubk|`Xr*`RbbmL^#Ikq_~ z=8d0uu;@-!-mdF%uuFF~j*)DL7e*IWUUvDyC#&b}a_cVS=&IvNcF8^xa{yROTv zJ3Gfay>Ict=)%g|bzN@V#W_Cd{fHMv7gpY`>vHQZ&hbs}SG+K~u<~|Yms@vnj_Bc$ z&nhe~J_q?(=(;W!GsjOi?ia^{=bG#xUKm+edAqL5!J?NtJI9{hUA!>5u<~|YmxJlf z%;VYAaU?s$3!@7wZ`XA>nC|QxBfUesFuJhvc3qc)>CVjKdDZbu_7pFSF08y=*X3Zk zvvZv3J;e*73oCEebvc;s%sie~9j|0B@xtiB%G-5a4yHRh$CchoyfC`3@^)R9gXzw5 zO3aH_X3pb&LtziR^Lk`1!t*|kbX^X{sjhQu^WUBQwlS}AOcveA?z%4b+b+g2k`3{~ z=)%hD_Um%%F3xeK_YyBGb{22fb-8tC=Xj_0EnXO1SUqpob-8sH=lG=eBVHI?Sb4jy z%dNXO$2YxS@xtiB%G-5aZr#N>;=Mc_@m{X?^Sq}ED{t3zxpf!kh#nrC>4n85-mdF% zF;lv6zc_ZDYhJr}VPs+Tyj|DjVDzf%9LLPyJ;V#63%l#O987m+-s%|1hInCgVdd?* zE(g<{o#UC_r+8s>Vdd?*E(g<{nYZP<4bMDhvQxY;y0G$gU6+ID&d%{l?@PQey0G$g zU6+ID&dl3#UOn%X>=G}GF08y=*X3ZkGykrzc*Qf1`>loTc;~fej;!mt9E?+4=h*T) zaT`C+28-@wcU_nJZ5QJh$%c4gbYbOn`*pc>7w5Rrdx;koJBzpLy4pb9~bK5ig7`th`;<<fk;u@p4a>?~L+xU6+ID&dw1%JmQ7LCEl*N>}k--+A!c{W&dC%fyq+;6)W$4EBB3!@7wuiLN7t-CnKmEKFd zu-I9=UDxH-ot@*I-nV#RbYbvAyN84oO8%WHmX`Mn%?=QT1H9n*C=7^k}S_dLH7xAF6A+hoz5?5^u_zwKfi zBiRryj4rIa>=OT0e$)6FcV^z|cqDs>7e*IW-mdF%Fx}ZX_Vn)Jh0%qTx9hqbOm}A9 zk@Jo@lf!*n;^m$$neujBmxJlf&JjI4;)TT}-mdF%F;lv6zc`-ro|#Ya!pOqvdAqL5 z!RS@jInJ5Edx{rE7k1ZmIhgLuyw&ka_7X3QF08y=*X3ZkvvXYOy~GQn3oCEebvc;s z%=;G>uX85H{r13~c<05xR~^@NIT)w9&avfp;x>Ms4Hn(W?z%4b+b+g2k`3{~=)%hD z_Um%%F7I@_#qmk@Sr}bddAqL5!EjX9Ilk%riWf!~cGq>ebr znC{HHk@Lo!$>BaO@p4a>OnJMm%fWPK=ZGF2@xtN~Z`XCXm?_=3UmWMWXXYth7+F|7 zZ`XA>7`^H`$7^QrzQhZo3%l#O987m+-s-rLUE+n&g_XDKx*SY*=6wW<*Ey5petTdi z-g&Wi9oKa^7^k|vHQZ&T*yp5-%)v z7H`*expimfc&GO*UKm|iJ#W`_xpf!k_@wtEUKm|idAqL5t-CnKH@#o+!sx=v+jU)T z-NiY!IX^xh@>zw^-6kt<*L69V?##T^@ksU%FN`j%yj|DjV7jw&?CIUb3!@7wZ`XA> znC{HHXU==hnVcipAzm0=Sb4jy%fWPK=NRc7;)T(LmAC7<987m+-ZSUb^Ku`Tc)6!b zro3I(j%#M{UgCw( zh23>s4yHTv{)NTsoXK&&wJ>(Pvi~dTyDkUg;O02Tmfwln_<1&1bSJy(y4-KO7{^F9 z#0#SfE3ezH%dNXO$Cchoys+3=yj|Dj)}5W>o!+;2VRT{jyj|Dj)?J+AlirVbVRT{T z?Yb_v?&2KZ^nS$)qYEo<*LAsd7w6dK{P=9iXB9?wo2 z?Yb@(Go>5%i{qO2%)G=4BMYnN?Yb@pqgP$tN3eLEoa26LVYuVU99h?OIT(k%?vLtU08X$uFJu6XXiN6dx{rE y7gpY`>vAyNnR&0ASI^6RT;k=PE}8OnU6+ID&dw1%JmQ7LCEl*0mE+w6oH`-6vBkUP#6kB@tnEcR_$yxxC3wnp0BD; z^M3mI*MI)K{bk#>|NeFSV^9Cv5AOf?{%6>{22=h`M5oBDGuQjs{(DSo@yg3!Gdoy% ztFFtz=w+9A^Ne|UTClb-y0E*h%dNXOM-OioFKq5C-m2?z>n_f5g!d3Hj4mvnx9Ymw zx{Gt1;XTC*qYF!K)pfab7w5Rbdx;lD7na_t>vHQZ&avg^=bzj6@Ln9=ZLsuKU6)&T zagIH_yLe%AVd<^9F1POD9FOom#0#SfOK;V6xpf!kc!u{WUKm|idaJI>t-Cl!3vUxI zj4mv_RoCU#U7X_;-j{e`bYbbOx-Pfw;vDbrzQqfp3rla+b-8sH=lF#8BVHI?SbD3j z%dNXON6ziyh0%rOf3LbOx9-9h18ly=bIu+PT*5ZKv$$_FKL2rDmxImIeqMTf|MhX7 zjw9HyFuJhxR$Z5a;mGb`9A~g|4nUD#dM!}}C3j4mv_RoCU#U7VwZw}}@<7na_t>vHQZ&hZNGOS~|;u=G}4ms@vnj(2$9 z;)T(LrMK$3+`5Z%e8T$?FN`iMy;axc)?J*VhqsFtMi-Xes_Sy=E@R4^H(%TQ_vbqU z2QFbPSPM4OgU!=^UiiLoIT$CqoqOgr;JC&)f*oz#aE$|N8#i3zR5`lj zvP*7@dD%UKog=4=F08@Fsk$x)JKDE<8pjpv8o7;Y92i|#8yBbQx*Y6m-|imomtEd3 zk6@35(S@bA>be{ZM|Pd#8Q!OOVRT`4U6)&TagG+=CSDj_SbD3j%dNXO$1A)q@xtiB z(pz<1Zr#N>-r;?V7e*JB-m2?z>n_gm3GYX|FuJhxR$Z4{cX5s$-Y#AkU08anuFI{v z@HvFd*Y@-3zUyEe@9_7?&5r519E_7)=h#N3k!#;)gU#+>cU_l*{j#%hv|vrVFuJhx zZbjGSV4HMXbk#9?gEJq_fz7LZy;axcV9a7BXWlQ4gUq;&_VvQZ!tS~*2cwr==CzpD z2Iri?&i3`f`nX_sU6+F$(q&$Yd2Mjc73^wXFRYIX*2l#;BX_p@99?qR-Q#n)%jfbD z?6EMqu)D6y!Ej{PIiBHtiWf!~cGq>ebrbl&zi*vlf`w}mVE-bxO z*X7n-oZ}tdw|HT6Vd<^9F1POD9G~!h#0#SfOK;V6xpf!k=;7_+h0%qjx9Ymwx(lB} z*nDmAYJPk8{W$Or{}H*_F|LUDxGczwB%rEm#vTj4mv_ zThVnn*e2Z;U3K(eUA!>5uwz`Ds_Swv9NF#0F?)DMu8)fYn^(KpbF}a_@xtiB(pz<1Zr#N>Ug3R-7e*JB-m2?z>n_gm4)0sM zFuJhxR$Z4{cX5tSct7HW(S@bA>bl&zi*xkwcJadK!qQuHU2ffl&n9fXwx3t`+XFlC z4*was*)d(0gK@I!9NWko5uyb6Ts_Swv9NF#0aRfU?j*A1M%l%!~>6kq{3xmVBI91o>=FIl( z&ilo2#V* pmD_$imWFbzKfdFT0mW#S5bgOK;V6 zxpf!kc!c*MUKm|idaJI>t-CnKGrUjn!sx=%TXkJ--NiXtc$;`(bYbbOx-Pfw;vBE= zzQhZo3rla+b-8sH=Xi(rEnXO1SbD3j%dNXO$0xiW@xtiB(pz<1Zr#N>dU(5dVRT{X zt-3C^?lQg!=DhhjKGz)gTMN7J4*%6=Z2rSMPVQ3W=yI~_9NWmudF?w7HoJq}bzKhj z%g)Bpf;I8N=)%&w6EM1|Bd6?w|3TN~V25<){Fs-H*&FN>vQ@ZnhacuEf-Q=?h zBMW06PStfe7`^N|#~$8YyfC`3yROTvyEw-qybtlh=)%%lbzN@V#W|kgeTo-G7na_t z>vHQZ&e6i##0#SfOK;V6xpf!kc!l>RUKm|idaJI>t-Iv=a=woD8^?XO!?xk>NLPjsDQ8?)xT_MHct-NDjZbzKhDb!X#f!J2qsbYbabmkT~vK5vy&hVb%h0%qjx9Ymwx{GsM;l0EQ zqYF!K)pfab7w4EgJn~tE&5O@Ld={#%%gveX+nx7|W9PXB+r(0 z2=7C@FuJhxR$Z5a>CVjK+0^k2_7pFSE-bxO*X3ZkvvaiYHu1vf!qQuHT@I!@Gmqz0 z$1B)NyfC`3^j2M$gXzv=%A7Y}nK_R8Zinro+sCy>ZidJGJkoVJ7$>_2@8!XcHeRE9 z2Gj2d7+u(1*X3Y1vg;gIcrV!nMi+M1b-8sH=ivG0#q;OibTGQyr?=|5+`5Z%%pM-` z!saF3s_SxdrgZ21;&|{}<9dh}Mi!ROTXkIyMlZY0@f;bvPw~R&!tS~*2h*LIw>ny| zCSDj_SbD3j%fWPK=XizpC0-a^SbD3j%fWPK=4~-=!!yo1*jv0Xy0G+CU6+ID&d%`( z??=2ay0G+CU6+ID&dl3lUOsOR*2N2>3rla+bvc;s%-be|EcXp21!y{hUyu@2|U2e{l?z~?d&vDPp zr+8sxVfnmO*X3aJvg;geWbiie!sx>8x-JLPotd{fUcp}Ch0%qjx9YkaOm}vUcX;38 zh0%qjx9YkaOm}A99`p7wlk*Ao5ig7`EWK6NvF&CVjL}46EBP|EWK{OD!1<9 z96h{Uys){mc&o0n_f5hW8XNj4mv_RoCU#U7X_z?PJ12g8wF=Xi(r zEnXO1*j?An_f5 zh4&IKj4mv_RoCU#U7TYZ^XL0TKC3Xg+hFOfx-JLPotd{f_F%hsVRT{Xt-3A;)195; z5#EP*VRT{Xt-3A;)18_3jCs#7lf(VI#LGQhGU=_lE(g<{on!X!h!-|5@m5`zn=_?5 z?-$2w+%xkfUKm+eK5x}^IT*d{I>&ot@V>8-jh2h*LM;~Czkcwuy5>8-jh2h*LI*J559 zGdbMPOT66EC6nH&>vAyN**Rtpk9cA85^vRYxj9q1^L}x>$2~LO;)Rigl|BrCvNTgY_QoK?5^u_zwKfiEm#vTj4mv_ZoewG?&2Ihyj{GoxwCkyuFI`E zJI4{;L%cA$uzcRC>vHQZ&T)qK6fcY}EWK6N<t-CnKHs;UI zhkRCHbhp9MTXkIyraLolb?m`*@xtiB(pz<14yHRh$0NKC@xtiB(pz<14yHRZ?-lc2 zV?vLtU08anuFJu6XXj|)ZQ_N|g{8OZx*SY*X5K62<@0hsFY$6umrQ!AuFJu6 zXXltbJmQ7TOT1Or<>pN3&ilpj8TZWmh!;i{md{&tT@FSsyUx)^25%QHj4tf1>vAyN znfEVjzK)q3_gf2N#~%Hkr0=>MjDwrw99w)RZteSQu-P5#uIqBY?P44)SQ9UdE-bxn zzbd!x;v7A^UA(Zlvv{kn%dI;*#}VE`yfC`3eBP?-a_cV6afbI4FN`iMy;axc)?J+A z3hyOe7+qL;tFFtfyEw--=FiWTd{$v}x53g|bzN@V#X0uy?&5{fg{8OZx*SY*W**O` zjz_SEcwuy5>8-jh2h*LM;~Czkcwuy5>8-jh2h*LI_l|k*F_Y7RHSxme!qQuHT@I!@ zJI5=$FY&_Y!qQuHT@I!@Gw&Vq@_D(Rmw36SOD4Tl*X3ZkvvbTI9`VBFCElv*a&xA1 z=l$a7ydp=|bzKg|Vek3se$V4Oaci>Q zV6!{eUDxG)+r>CquqIv@U08azqU&<&F3!vHQZ&T)kI5HE}_ET6aP zy4<>pbDZHl#S5bgOK;V6xpf!kxWaph7e*JB-m2?z>n_f*jrsHQp`W+G=x&3hx9Yka zOm}vUJ-oYkVRT{Xt-3A;)195;5#EP*VRT{Xt-3A;)18_3iFx@Q_6+tEFN`iMy;axc zV7jw&wD30Z!sx=%TXkIyraLq56Z7(UU%_7Dh0%qjx9YkaOm}vUcX;38h0%qjx9Yka sOm}A9C+6kzaz8Kea!;2`daJI>!E|Tmm_0n=h0RO6RoCU_%>Q@)2dKTLdH?_b diff --git a/assets/meshes/chunks/chunk_1_1_0_0.dmf b/assets/meshes/chunks/chunk_1_1_0_0.dmf deleted file mode 100644 index e9e5aace3863ee5accc34dd7e5511db1f9238f52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26652 zcma)-!Hwg<5k={P?+k$<=-{jEHemQ>Kp`*$g}_i0ib7E+?pIs2`rGphaswQJZ~w1X z+>tc@{_lUbziiv~x4+IG_FRAeg|B~p{uvh6WXeB@>@>M`=6WCPf8?~0ue?ka*~!Y= zbzKfdue!{OGw0PA$;QIy!oGD~Zr#N>uJm5wg~iU|?Yb_v?&2KJ^ghK4qYJC&?Yb_v z?&2J;^uELkqYEo<*LAsd7w34V_bpx+U08X$uFI{vILB6>pMPzi!+UXhx5>)ebzN@V z#X0u$?&5{fg_XDKy4<>pa~$bC#0#SfD{t3zxpf!kxTW_dUKm|idAqL5t-CnKNbe9Y zj4rIaUDxH-U7X{d-n)2VbYbP~x-Pfw;v8psPw~R&!phrqU2fgQIUebKh!;i|R^G1b za_cV6QFAZx!sx>4-@C5Mt-J8W0E^dr&gkL5C2Zq6i~AAr_~E)P2a7X)y*Nko*kxwQ z8$G&{mAC6gcFDy|-8sK^)iIKd*)1=OF08yUYuT^Mk&PbxdC0N1I<92b_;_J-VbSNM z>AD;YM|H34GOwQPne4eRy0C9umxJM`u5-N7`b{L*r|TShdUx@{=)%g|bzN@V#W{}j z9^!@3g_XDKy4<>pbKKH<6EBP|th`;<<n_f5Pw!p4FuJhv zc3qcScX5t0y{C9#bYbP~x-Pfw;vA3kKEw;73oCEeb-8sH=eW{)i5Er}R^G1ba_cU0 zO3aJb5kG%@XW+mkY$O}WB0X80@#`i2#+V#kPIcpZDRbpux3~tud2uF-?)ctyIT+7T zUgpI$=anORcoqhSee1eh%+zlF-ZuHY?aB6q(S`l?HeHtsuXLT`$a#l&VRT{T?Yb_v z?&2J`^xnh^qYEo<*LAsd7v~u19pZ)2g_XDKy4<>pbKKK=7cY!1th`;<<$=>!%lx*8dGR_w*Btj< z2fOf2|1}~OKbXgn_gmNbf_uFuJhvc3qcScX5s@y_a}lbYbP~x-PfwGT+@X zFJ9;SJYLOr1fTOK-syj4F0zxw>&Vw8N0(Dw`~AXva^v%C+q{qNWZ$|j2m51Z;~2?? zcwuy5<=vXD%fUA7=I?Ej-`k#SUl?83Z*S9ex$sKYIgXrnh!;i|R^G1ba_cT59YY-V zWcP*9g_XDKx*QBgb)Dl(?uJm5wh0%qT zx9hsxy32fb$Gmu*?{kj(j)1-JPXB8}EPgPLQ@eCIx}54d$2K!DZ+zy#qC45QuFJvx z*x5KnvLRj=U08Xyrt5OBO}qJf+vNAQC)*cB7xvrRbX_jI(shm_=N;mO(S?<_>$=>! z%Sgu%$35A7VRT{T?Yb@p!%vHQZ z&T*#q6fcY}th`;<<9p-Urmo7&)PIjGRo3mox_{@Vvce3(!U6+Ghy0dYNWJA0#y0G%H z%NssfJ#Uv=cOget9apkT=D}j;$;#VxU2fgkIiBf#iWf!~R^G1ba_cV6@k;MYyfC`3 z@^)R9TX%7ecY5FAh0%qTx9hsxx{Gr}5089SVR7*}$j?I8b-9>1KHa!q96Qf7*)Cof zSy*|yuFJuqmpePhk={eRFuJhvc3qc)>CVjK+0=1Mb`vj*F08y=*X3ZkvvZ8}4)Mb1 z!phrqT@I!@Gmqz0$359yyfC`3@^)R9gXzxBai;eaFN`j%yj|DjV7fE&cwTipl0C!= zqYEo<*L69V?(7^_dN1+9=)%g|bzKgoJI^UGFJ75BkNX=6+wsn8&s>D(eH`h!9E?+4 z=h)`|JNs>8Ugel9x|4nDy4;UljAJAl;)T(LmDlap<(0*c zOz%^?FuJgM-mdF%>n_gmO7Ba&FuJhvc3qcScX5t)df(!O(S?<_>$=>!i*v+#c{<{~ zT<_<3PZw6+uIqB^F3u4>JUG(}i%Yy+*X3fSbmM+;96Z;&4)Mas!s>auuFJvbRo6Lg zGlTagUKm~2x30^vBJKF^-XJh!;i|R$jMX zms@vnjw`*Fcww=#c)PC4tvfr%Grdpo!sx>4dAqL5t-CnKE4?rA!sx=v+jU)T-NiZH z>3xeAMi*AzuIqB^F3z#d`SJOX&nk@WHd%SQuFJu6XXdRA?&A_K_jLKrC~wzwIhgM3 z9MQugURYe>?Yb@(Go>5%i{m!$nRyd0j4Z64x9hqbj9zt}W6TWRAzm0=*tf3B!E|Tl zt&V%LyLe%AVdd?*E(g<{o#RaJDP9;|Sb4jy%fWPK=IuFepEEg+WDoJe=)%g|bzKgo zJ3Ggf-b=hNy0G$gU6+ID&O9G1Ugu1X`&$dU;honlb7WoD(mZiQD)*8!Wn$ zee1g1k6nyoBpc#|(S?=Q?bqejU7X`e?@41{>vHSP&hbp|Q@k*`uzKFE>vHQZ z&hbj`OS~|;u<~|Yms@vnj(2+B;)T(LmAC7<+`5Z%Y;%5mKIF3sqq|L3-mdF%>n_f* zr*{`Gj4rIaUDxGcx-;{5Hg#|xmw36S%Xd|IyROT@bZ6&?9v<<+;u3Gyb-9=+-MC*I zW8O1!h!;i{R?pjYT@FUCy3TQ*8N7G#!sx=jbzKgoJ2P)}oXJk{!sx=v+jU(IraL>w zBfSst!sx=v+jU(IraLq5$a%+{$+?nU;)T(LmAC7<987n{1B=)4n!mODy&QPwH8K|+ z({(u*r@Hp|z`v*$^*`F08!l68~5KM{eE4Ij)>{$vjx> zEZ(l`a_i2{@l5YiyfC`3dfu+T!uIq9z-I;l-V^6k=7e*IW-mdF%Fx}ZXj`SYlh0%qTx9hqb zOm}A9E$7|lOb+*PiI;o2WXjuhT@I!@J4f{Jh!+-@c)PC4#Z2kO{o=UKduHCn3nL4w z=k2;K2cuVA=Qw8u?pbG+007B7r0th`;<<vAyN**R|My@?k_7gpY`>vAyNnRz4UjX9IU zeO%(@o-Ud4c3qc)>CVm(Jv`!t#UvAzux^cfa&Uw$wQ@k*;uzKFE>vAx9)pd@? z%;0^97e*KMt?P0y-I;l-<4Sgk7e*IW-mdF%Fx{E=5iDNkOpf~-06X!{i@oc(uFJtV z)pd?7zZ19dc{W&dC;QfQxgWb2$4EBB3!@7wuiLN7t-CnKmEKFdu-I9=UDxH-ot@*E z-luqBbYbCVm( zJv`!t#UvAzux^cfa9`l}=5Anjt!s>auuFJvbRo6MLnZbLB7e*KMt?P0y-I@0< zEMDhKj{92+W5+A|zmmS|axe~Vj&p4Jow$w9v%#V}*|)CC{n*7gMzSGZ7+qL--F{te z-NiYs^j_kH#m?gGx-Pfw>>SVZKE(^83#;etx-Pfw;vBE^zQhZo3oCEeb-8sH=Xj_0 zEnXO1Sb4jy%dNXO$2RB3XG=b-FuL1h<}-EF08y=*X3Zkvvb_idlN5=F08y=*X3ZkGxN@zcg~rdk!*+;Mi*AzuIq9z-Pt+r z>Ai~=Mi*AzuIq9z-I;l3&a3C;J}&WcPnS%2yROT@bZ6&?9v<<+;u3Gyb-9=+-MC*I z*Su%uC0-a=SUqpobvYQl>heB<#p~o8_qP^?JFd);bzPT(ao9Uv-QV;4PTYp$=>!i*r2F`xGyXF07un>$=>! zi*vlv`w}mVF08y=*X7n-oa3F|w|HT6Vdd?*F1POD9NU~9pAY@KO-6T{th`;<k diff --git a/assets/meshes/chunks/chunk_2_0_0_0.dmf b/assets/meshes/chunks/chunk_2_0_0_0.dmf deleted file mode 100644 index 7d390ce7063abdb7dd71caa3343fe5795eea1a05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30252 zcmai&&CMgrkwr_u2-?yFn!t^glJWrq?F7&Snm`lMlyX8^7ch?0a`tjSae@)5__A+2 zCQwb)dH2SN>gEri|NY0`w?Ay#_WyshKjfKz`QZ7t>p#Q%GFJJOh)$DRXRi0&{%cGd z@yd%a&l*c_*Ht+fz3ej2kIl<7f{lgIg?;O)+`5Z$%<#_Qh563K+jUiL-9#E$ki*lUdJ&PAc7na_xt8(iu%CY6==eO-Tycf;8 z8B1^1Rk?K+<+z3SR=hB}u=I9am0NdFj(d3T#S5bgOK;azxpf!ic!c*+yfC`3^mbj9 zTX#{85#CX}FuJhxc3qWQcTtXKc%Q`!qYF!K*HyW77v*?`_f@Gd96W9jX>o?UW2v+f+CMi-V|pSA4Q<;Z%Ez8!MxT^%#n z9G4eH7v_Clny$*haAbEzmwEYYd$4_BbYb7RDhI=nUFA5!dsr@afzgG1>#7`VFJ0#G z_go!ku+wtsh0%p=Tz0yy%E54C_Y{te&kygH@>zw^g?;O)9PAudS2=Fsy%jHvE-bxW zSLN1Sl;a-Wd-1~P!qVGyRc_ryIUeDC6fcY}EWKS<<b1hFzRJa{I6wE<0V0F1hTI+hSgJ&tRwJDx(V< za64UBlmfo(ba#E$k zi*mfe`zl@-U08a%uF9>uD91az@8X5gg{8Oas@%GZa?J3~;)T(LrMK&<+`0?jJ1~D8 zpI7x83Y&P%KO^TI(N#GZC%ekAS!R$M*R#RAYwTNB76RXNx>t}gTNR>v*at$1N{Vd?F#E$ki*n5H&f;e(Wq9BiJZj7+qL;x2CIdu&s1QbgN?qo5c&G z3)}7DbX}E$;mGb34)5Wy+_Z}W^J{$Xs+`X(UB6!(N9=M~F1;|au-z_B*Ht+fz3d*s zaRxgrH|^rU=)%5rRStHPF7sy0OUD+U)vbJ1VRT{X?Yb%lJBwF2ZsENZFN`iMy5k}D#|$=$7e*I$*v09(DhI=n-6$)lj`|Nzp z+hbljw)m`W{#pIxV02;WJ?&m~RSs5nR*qYEZ^a9v3rla;Rk?K+<+z9UUc4~6u=I9a zm0NdFjz@SO#S5bgOK;azxpf!i7~vho3!@85Z`W11b(fzGd*9f3hWF{-i_wMgzT|XW zmAiKNbd}>3-dFL$=)%(5byaTNMLFK#eHSl`E-bxWSLN1Slw*c>7B7r0EWKS<<^NyI8jy>3JxytCm zPP;f=SLI-HT-{wbj$k;sI54{0pLTJ&uFApoadnR$j_bDq&iwq2py!u&Ke?`}a~_?&j~^>-UH*?EIbIM!G7u?xGyG@ZO3SMi-XeuB&qEF3NEa@4a|obYbc3x+=Hs zq8yL#K8hDc7na_xt8(iu$}z$_iWf!~mfo(ba_cTX9rnJl^9=9Py%(bk%g<5QRk>@I zYu*v_c%O4#;e8b^j4mv_YQHYG?xGy;@V<)|Mi-XeuB&qE&dM>vJBt@a7na_xt8(iu zo6Ul4oiz3rla;Rk?MSpN{Ld;>7LVi_wK`zkOKORk>@IYu@Vc9?$3R-A@kY z7w@U?dT-gU%lXW4b^U&E+;}cyx8jA7g{8OasvOM!ePUdwsLc|Q)DY3CX2>E4Ucg>77R zx~|H>K0AN9%JB;Ct9W5_Vd?F`X4>KZJM=ED!ftr&x&|0mm ze%V<#MzB%5FuJhxs{Oj$x{Gqm@Xq3e`Od}LbyaTNSvmIb?!^nE3(M#2x+=Hsq8vwf zkK%>Vg{8Oas@%HEPsjD!$ouMa@5SiCZomEefBwl1Klc0m+_lT6dq%f9{Jm^*{kAETh`|SMb zD#t6lui}N#g{8OasvNBDtQ_y~zKa(|7na_xt8%cqGxN5Xx8bofgU#ZF(S@bA>#7{A z?u-ZKuj#elU+>~7?2gy2dob^auFAnU+2!|lb!_onyp78X^RBUPU6uP~7vUJeM)AVv z!qThu>vHQZ$}z(`ix=iQ7jM^9xpimd*u%RQFN`iMpSSC(+`5Z$9N|5R7e*JB-ma^1 z>n=YX*KZ^5wbQ*9qYJy+@9&@4;m3ZzpSyPXbkFEk$7VDAv*n-F&pa62%~*Q7uFApc z&dggK-1}9$+|%XroZhaha`zl@- zU08a%uFApc&dlR^tK%K)UA!>5u=I9am4nrtm1Bl?7B7r0EWKS<3!y^1{4p>|0mme%VDhMzB%5FuJhxs{Oj$x{Gqm z@Xq3e`Od}LbyaTNSvmIb?!^nE3(M#2x+=Hsq8vwfkK%>Vg{8Oas@%HEPsjD!$ouqk z@5SiC(%W@aZr$aKXRD6Q=KJTvKdT=vjP7PEyuD92{={j*g*t1!Bo zvGjIbm4nrtnYTJ_!EVJ1qYF!K*Ht-K-B~&A;k_3xj4mv_U03B`b!X;1VqShXaqn00 za!;2`db_U5!RpS+;XORX3-haZyRORl%+mGy#qqRzW~Era)6yfC`3Z(Wsx)t#BQ zI%cq0yfC`3^mbj9gVmjRAHn?9W^(v#^e(Q#UU=wrjaxhMIm1B$V#BE$&n0JkR z>#E!@y9mb!Hi{QU7nWYNUzb~VQH~kjS-ddcxp=#-%B?#q#~$9jcwuy5`Mh0M<zw^-HfHT>#7{A?##T^ zaSL`UUKm|idb_U5!RpS+aS!jkcwuy5>Fv5I2dg_X?-}#*yXg_^QM@p^u=I9am4nrt zm1Bf=6fcY}EWKS<uv6)*R6$)vaIsvNBDtQ_9MQ@k+0inr^koX;#> zzh4}0yJzORcwuB=`Mh0MFv5Ix9*}GxA5MI7e*JB-ma^1u(~tzc(&@e2fG(9j4mv_U03B` zb!X*xg!fUrFuJhxc3qW&)t#C5ig_=a$r-^$@xtiB(%W@a4pw(oj%RqE#S5bgOK;az zIauA9d9Rq4&&$1E#mhZiGU@HQDhI1OD~I>+6fexL;_bRB=QB&!?-$3kduGn!g^`8j z^LAa8gVD<_?<1JM8t3ra=-tRB!|hk(;Hs-~Fb;eBt8i@bow$v%pE2(m`_@&tUv?3W z5o{DMj4mv_YQHYG?xGwsyt8;=zH{+*U6osRR*pTqd-1~P!t!~$uF9>uD8~`rqj+I- zVd?Fyci1D?qj+I-Vd?FtUq+%Km+&Y z6%VEbCnh8$Bz{OZz#sC#o1cx@#EJbDD|7yV42hmLMrLM)O_^K)ON6~I0}WvCboFyt I=akR{0DW;G6951J diff --git a/assetsraw/chunks/chunk_-1_0_0.json b/assetsraw/chunks/chunk_-1_0_0.json deleted file mode 100644 index c9641377..00000000 --- a/assetsraw/chunks/chunk_-1_0_0.json +++ /dev/null @@ -1,1992 +0,0 @@ -{ - "meshes": [ - { - "file": "house_4_4.dmf", - "pos": [ - 2, - 1, - 0 - ] - }, - { - "file": "house_6_3.dmf", - "pos": [ - 1, - 9, - 0 - ] - }, - { - "file": "house_2_2.dmf", - "pos": [ - 12, - 6, - 0 - ] - } - ], - "tiles": [ - { - "pos": [ - 0, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 15, - 0 - ], - "type": 1, - "tile": 0 - } - ] -} \ No newline at end of file diff --git a/assetsraw/chunks/chunk_0_0_0.json b/assetsraw/chunks/chunk_0_0_0.json deleted file mode 100644 index 06fce022..00000000 --- a/assetsraw/chunks/chunk_0_0_0.json +++ /dev/null @@ -1,2183 +0,0 @@ -{ - "tiles": [ - { - "pos": [ - 0, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 5, - 0 - ], - "type": 6, - "tile": 0 - }, - { - "pos": [ - 6, - 5, - 0 - ], - "type": 2, - "tile": 0 - }, - { - "pos": [ - 7, - 5, - 0 - ], - "type": 2, - "tile": 0 - }, - { - "pos": [ - 8, - 5, - 0 - ], - "type": 2, - "tile": 0 - }, - { - "pos": [ - 9, - 5, - 0 - ], - "type": 2, - "tile": 0 - }, - { - "pos": [ - 10, - 5, - 0 - ], - "type": 2, - "tile": 0 - }, - { - "pos": [ - 11, - 5, - 0 - ], - "type": 2, - "tile": 0 - }, - { - "pos": [ - 12, - 5, - 0 - ], - "type": 7, - "tile": 0 - }, - { - "pos": [ - 13, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 6, - 0 - ], - "type": 3, - "tile": 0 - }, - { - "pos": [ - 12, - 6, - 0 - ], - "type": 5, - "tile": 0 - }, - { - "pos": [ - 13, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 7, - 0 - ], - "type": 3, - "tile": 0 - }, - { - "pos": [ - 12, - 7, - 0 - ], - "type": 5, - "tile": 0 - }, - { - "pos": [ - 13, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 8, - 0 - ], - "type": 3, - "tile": 0 - }, - { - "pos": [ - 12, - 8, - 0 - ], - "type": 5, - "tile": 0 - }, - { - "pos": [ - 13, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 9, - 0 - ], - "type": 8, - "tile": 0 - }, - { - "pos": [ - 6, - 9, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 7, - 9, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 8, - 9, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 9, - 9, - 0 - ], - "type": 12, - "tile": 0 - }, - { - "pos": [ - 12, - 9, - 0 - ], - "type": 5, - "tile": 0 - }, - { - "pos": [ - 13, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 10, - 0 - ], - "type": 3, - "tile": 0 - }, - { - "pos": [ - 12, - 10, - 0 - ], - "type": 5, - "tile": 0 - }, - { - "pos": [ - 13, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 11, - 0 - ], - "type": 3, - "tile": 0 - }, - { - "pos": [ - 12, - 11, - 0 - ], - "type": 5, - "tile": 0 - }, - { - "pos": [ - 13, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 12, - 0 - ], - "type": 8, - "tile": 0 - }, - { - "pos": [ - 10, - 12, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 11, - 12, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 12, - 12, - 0 - ], - "type": 9, - "tile": 0 - }, - { - "pos": [ - 13, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 6, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 6, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 6, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 6, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 6, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 6, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 7, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 7, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 7, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 7, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 7, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 7, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 8, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 8, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 8, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 8, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 8, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 8, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 9, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 9, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 10, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 10, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 11, - 1 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 11, - 1 - ], - "type": 1, - "tile": 0 - } - ], - "meshes": [ - { - "file": "house_5_3.dmf", - "pos": [ - 1, - 1, - 0 - ] - } - ] -} \ No newline at end of file diff --git a/assetsraw/chunks/chunk_0_1_0.json b/assetsraw/chunks/chunk_0_1_0.json deleted file mode 100644 index b94a6497..00000000 --- a/assetsraw/chunks/chunk_0_1_0.json +++ /dev/null @@ -1,1929 +0,0 @@ -{ - "meshes": [ - { - "file": "house_8_4.dmf", - "pos": [ - 1, - 1, - 0 - ] - }, - { - "file": "house_3_3.dmf", - "pos": [ - 11, - 2, - 0 - ] - }, - { - "file": "house_2_2.dmf", - "pos": [ - 3, - 11, - 0 - ] - } - ], - "tiles": [ - { - "pos": [ - 0, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 15, - 0 - ], - "type": 1, - "tile": 0 - } - ] -} \ No newline at end of file diff --git a/assetsraw/chunks/chunk_1_0_0.json b/assetsraw/chunks/chunk_1_0_0.json deleted file mode 100644 index 5d69f9b8..00000000 --- a/assetsraw/chunks/chunk_1_0_0.json +++ /dev/null @@ -1,2107 +0,0 @@ -{ - "meshes": [ - { - "file": "house_3_2.dmf", - "pos": [ - 1, - 1, - 0 - ] - }, - { - "file": "house_2_3.dmf", - "pos": [ - 7, - 2, - 0 - ] - }, - { - "file": "house_4_2.dmf", - "pos": [ - 1, - 8, - 0 - ] - }, - { - "file": "house_1_1.dmf", - "pos": [ - 11, - 10, - 0 - ] - }, - { - "file": "house_5_2.dmf", - "pos": [ - 13, - 6, - 0 - ] - } - ], - "tiles": [ - { - "pos": [ - 0, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 15, - 0 - ], - "type": 1, - "tile": 0 - } - ] -} \ No newline at end of file diff --git a/assetsraw/chunks/chunk_1_1_0.json b/assetsraw/chunks/chunk_1_1_0.json deleted file mode 100644 index 72c719fe..00000000 --- a/assetsraw/chunks/chunk_1_1_0.json +++ /dev/null @@ -1,2028 +0,0 @@ -{ - "meshes": [ - { - "file": "house_5_5.dmf", - "pos": [ - 3, - 2, - 0 - ] - }, - { - "file": "house_2_3.dmf", - "pos": [ - 10, - 3, - 0 - ] - }, - { - "file": "house_3_1.dmf", - "pos": [ - 1, - 12, - 0 - ] - } - ], - "tiles": [ - { - "pos": [ - 0, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 15, - 0 - ], - "type": 1, - "tile": 0 - } - ] -} \ No newline at end of file diff --git a/assetsraw/chunks/chunk_2_0_0.json b/assetsraw/chunks/chunk_2_0_0.json deleted file mode 100644 index 7ad75503..00000000 --- a/assetsraw/chunks/chunk_2_0_0.json +++ /dev/null @@ -1,2543 +0,0 @@ -{ - "tiles": [ - { - "pos": [ - 0, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 0, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 1, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 2, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 3, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 4, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 5, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 6, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 7, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 8, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 9, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 10, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 7, - 10, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 8, - 10, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 9, - 10, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 10, - 10, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 11, - 10, - 0 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 12, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 10, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 11, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 12, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 13, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 14, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 0, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 1, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 2, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 3, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 4, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 5, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 12, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 13, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 14, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 15, - 15, - 0 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 9, - 1 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 7, - 9, - 1 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 8, - 9, - 1 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 9, - 9, - 1 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 10, - 9, - 1 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 11, - 9, - 1 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 6, - 8, - 2 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 7, - 8, - 2 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 8, - 8, - 2 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 9, - 8, - 2 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 10, - 8, - 2 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 11, - 8, - 2 - ], - "type": 4, - "tile": 0 - }, - { - "pos": [ - 6, - 5, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 5, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 5, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 5, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 5, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 5, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 6, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 6, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 6, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 6, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 6, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 6, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 6, - 7, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 7, - 7, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 8, - 7, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 9, - 7, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 10, - 7, - 3 - ], - "type": 1, - "tile": 0 - }, - { - "pos": [ - 11, - 7, - 3 - ], - "type": 1, - "tile": 0 - } - ], - "meshes": [] -} \ No newline at end of file diff --git a/editor/client/public/common/chunkterrain.js b/editor/client/public/common/chunkterrain.js deleted file mode 100644 index 4a19360e..00000000 --- a/editor/client/public/common/chunkterrain.js +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2026 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -"use strict"; - -// ChunkTerrain - JS port of the terrain-quad generation performed by -// tools/asset/chunk/__main__.py (build_terrain_verts / _tile_quad / -// _RAMP_CORNERS) so the editor's 3D preview can show the same geometry the -// Python compiler will bake into the chunk's terrain mesh, without waiting -// for a compile pass. Vertex layout matches DMF: interleaved [u, v, x, y, z]. - -const ChunkTerrain = (() => { - const CHUNK_WIDTH = 16; - const CHUNK_HEIGHT = 16; - const CHUNK_DEPTH = 4; - const TILE_COUNT = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH; - - // World-space Z distance of one Z-layer/story, in world-float space. - // Must match WORLD_LAYER_HEIGHT in src/dusk/rpg/overworld/worldpos.h. - const WORLD_LAYER_HEIGHT = Math.SQRT1_2; - - const TILE_SHAPE_NULL = 0; - const TILE_SHAPE_GROUND = 1; - const TILE_SHAPE_RAMP_NORTH = 2; - const TILE_SHAPE_RAMP_EAST = 3; - const TILE_SHAPE_RAMP_SOUTH = 4; - const TILE_SHAPE_RAMP_WEST = 5; - const TILE_SHAPE_RAMP_NORTHEAST = 6; - const TILE_SHAPE_RAMP_NORTHWEST = 7; - const TILE_SHAPE_RAMP_SOUTHEAST = 8; - const TILE_SHAPE_RAMP_SOUTHWEST = 9; - const TILE_SHAPE_RAMP_NORTHEAST_INNER = 10; - const TILE_SHAPE_RAMP_NORTHWEST_INNER = 11; - const TILE_SHAPE_RAMP_SOUTHEAST_INNER = 12; - const TILE_SHAPE_RAMP_SOUTHWEST_INNER = 13; - - // Per-shape corner heights as [sw, se, ne, nw] offsets from tile base Z. - // NORTH=+Y, EAST=+X. Cardinal ramps: low face at 0, high face at 1. - // Diagonal outer-corner ramps: only the named corner raised, rest at 0. - // Diagonal inner-corner ramps: only the corner opposite the named one is - // lowered to 0, the rest (including the named corner) stay raised at 1. - const RAMP_CORNERS = { - [TILE_SHAPE_GROUND]: [0.0, 0.0, 0.0, 0.0], - [TILE_SHAPE_RAMP_NORTH]: [0.0, 0.0, 1.0, 1.0], - [TILE_SHAPE_RAMP_SOUTH]: [1.0, 1.0, 0.0, 0.0], - [TILE_SHAPE_RAMP_EAST]: [0.0, 1.0, 1.0, 0.0], - [TILE_SHAPE_RAMP_WEST]: [1.0, 0.0, 0.0, 1.0], - [TILE_SHAPE_RAMP_NORTHEAST]: [0.0, 0.0, 1.0, 0.0], - [TILE_SHAPE_RAMP_NORTHWEST]: [0.0, 0.0, 0.0, 1.0], - [TILE_SHAPE_RAMP_SOUTHEAST]: [0.0, 1.0, 0.0, 0.0], - [TILE_SHAPE_RAMP_SOUTHWEST]: [1.0, 0.0, 0.0, 0.0], - [TILE_SHAPE_RAMP_NORTHEAST_INNER]: [0.0, 1.0, 1.0, 1.0], - [TILE_SHAPE_RAMP_NORTHWEST_INNER]: [1.0, 0.0, 1.0, 1.0], - [TILE_SHAPE_RAMP_SOUTHEAST_INNER]: [1.0, 1.0, 1.0, 0.0], - [TILE_SHAPE_RAMP_SOUTHWEST_INNER]: [1.0, 1.0, 0.0, 1.0], - }; - - function tileIndex(x, y, z) { - return x + y * CHUNK_WIDTH + z * CHUNK_WIDTH * CHUNK_HEIGHT; - } - - // Six vertices (2 CCW triangles) for a quad with per-corner Z heights. - // Corner order: SW=(fx,fy), SE=(fx+1,fy), NE=(fx+1,fy+1), NW=(fx,fy+1). - function pushTileQuad(out, u0, u1, v0, v1, fx, fy, swZ, seZ, neZ, nwZ) { - out.push( - u0, v0, fx, fy, swZ, - u1, v0, fx + 1, fy, seZ, - u1, v1, fx + 1, fy + 1, neZ, - u0, v0, fx, fy, swZ, - u1, v1, fx + 1, fy + 1, neZ, - u0, v1, fx, fy + 1, nwZ, - ); - } - - // Generate terrain quads for every non-null tile in a flat tiles array - // (length TILE_COUNT, indexed via tileIndex). Returns a Float32Array of - // interleaved [u, v, x, y, z] vertices, matching DMF.VERTEX_FLOATS. - function buildTerrainVerts(tiles) { - const out = []; - for(let z = 0; z < CHUNK_DEPTH; z++) { - for(let y = 0; y < CHUNK_HEIGHT; y++) { - for(let x = 0; x < CHUNK_WIDTH; x++) { - const type = tiles[tileIndex(x, y, z)] || TILE_SHAPE_NULL; - const corners = RAMP_CORNERS[type]; - if(!corners) continue; - - const u0 = x / CHUNK_WIDTH; - const u1 = (x + 1) / CHUNK_WIDTH; - const v0 = y / CHUNK_HEIGHT; - const v1 = (y + 1) / CHUNK_HEIGHT; - const [sw, se, ne, nw] = corners; - - pushTileQuad( - out, u0, u1, v0, v1, x, y, - (z + sw) * WORLD_LAYER_HEIGHT, - (z + se) * WORLD_LAYER_HEIGHT, - (z + ne) * WORLD_LAYER_HEIGHT, - (z + nw) * WORLD_LAYER_HEIGHT - ); - } - } - } - return new Float32Array(out); - } - - // Four edges (SW-SE, SE-NE, NE-NW, NW-SW) of a tile's quad as line - // segments, lifted slightly above the terrain surface to avoid - // z-fighting - same corner-height convention as pushTileQuad(). - function pushTileGridLines(out, fx, fy, swZ, seZ, neZ, nwZ) { - const eps = 0.01; - const sw = [fx, fy, swZ + eps]; - const se = [fx + 1, fy, seZ + eps]; - const ne = [fx + 1, fy + 1, neZ + eps]; - const nw = [fx, fy + 1, nwZ + eps]; - const edges = [sw, se, se, ne, ne, nw, nw, sw]; - for(const [x, y, z] of edges) out.push(0, 0, x, y, z); - } - - // Generate grid-outline line segments for every non-null tile, following - // the same per-corner heights as buildTerrainVerts() so lines hug ramps - // instead of cutting through them. Returns a Float32Array of interleaved - // [u, v, x, y, z] vertices meant to be drawn with gl.LINES (pairs). - function buildGridLines(tiles) { - const out = []; - for(let z = 0; z < CHUNK_DEPTH; z++) { - for(let y = 0; y < CHUNK_HEIGHT; y++) { - for(let x = 0; x < CHUNK_WIDTH; x++) { - const type = tiles[tileIndex(x, y, z)] || TILE_SHAPE_NULL; - const corners = RAMP_CORNERS[type]; - if(!corners) continue; - - const [sw, se, ne, nw] = corners; - pushTileGridLines( - out, x, y, - (z + sw) * WORLD_LAYER_HEIGHT, - (z + se) * WORLD_LAYER_HEIGHT, - (z + ne) * WORLD_LAYER_HEIGHT, - (z + nw) * WORLD_LAYER_HEIGHT - ); - } - } - } - return new Float32Array(out); - } - - return Object.freeze({ - CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, TILE_COUNT, WORLD_LAYER_HEIGHT, - TILE_SHAPE_NULL, TILE_SHAPE_GROUND, - TILE_SHAPE_RAMP_NORTH, TILE_SHAPE_RAMP_EAST, - TILE_SHAPE_RAMP_SOUTH, TILE_SHAPE_RAMP_WEST, - TILE_SHAPE_RAMP_NORTHEAST, TILE_SHAPE_RAMP_NORTHWEST, - TILE_SHAPE_RAMP_SOUTHEAST, TILE_SHAPE_RAMP_SOUTHWEST, - TILE_SHAPE_RAMP_NORTHEAST_INNER, TILE_SHAPE_RAMP_NORTHWEST_INNER, - TILE_SHAPE_RAMP_SOUTHEAST_INNER, TILE_SHAPE_RAMP_SOUTHWEST_INNER, - RAMP_CORNERS, tileIndex, buildTerrainVerts, buildGridLines, - }); -})(); diff --git a/editor/client/public/common/dmf.js b/editor/client/public/common/dmf.js deleted file mode 100644 index 2a293cb5..00000000 --- a/editor/client/public/common/dmf.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2026 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -"use strict"; - -// DMF - Dusk Mesh Format -// -// Header (12 bytes): -// [0-3] "DMF\0" magic -// [4-7] uint32 version (little-endian) -// [8-11] uint32 vertCount (little-endian) -// -// Followed by vertCount vertices, each 20 bytes: -// [0-7] float32[2] uv (little-endian) -// [8-19] float32[3] pos (little-endian) - -const DMF = (() => { - const MAGIC = [0x44, 0x4d, 0x46, 0x00]; // "DMF\0" - const VERSION = 1; - const HEADER_SIZE = 12; - const VERTEX_FLOATS = 5; // uv[2] + pos[3] - const VERTEX_SIZE = VERTEX_FLOATS * 4; - - // Decode a DMF ArrayBuffer into { version, vertexCount, floats }, where - // floats is a Float32Array of tightly interleaved [u, v, x, y, z] per - // vertex - ready to hand straight to gl.bufferData(). - function decode(buffer) { - const bytes = new Uint8Array(buffer); - const view = new DataView(buffer); - - if(bytes.length < HEADER_SIZE) throw new Error("File too small to be a valid DMF"); - if( - bytes[0] !== MAGIC[0] || bytes[1] !== MAGIC[1] || - bytes[2] !== MAGIC[2] || bytes[3] !== MAGIC[3] - ) { - throw new Error("Invalid DMF magic bytes - not a DMF file"); - } - - const version = view.getUint32(4, true); - if(version !== VERSION) { - throw new Error(`Unsupported DMF version: ${version}`); - } - - const vertexCount = view.getUint32(8, true); - const expected = HEADER_SIZE + vertexCount * VERTEX_SIZE; - if(bytes.length < expected) { - throw new Error(`DMF vertex data truncated (expected ${expected} bytes, got ${bytes.length})`); - } - - const floats = new Float32Array(vertexCount * VERTEX_FLOATS); - for(let i = 0; i < floats.length; i++) { - floats[i] = view.getFloat32(HEADER_SIZE + i * 4, true); - } - - return { version, vertexCount, floats }; - } - - return Object.freeze({ - decode, - VERSION, HEADER_SIZE, VERTEX_FLOATS, VERTEX_SIZE, - }); -})(); diff --git a/editor/client/public/index.html b/editor/client/public/index.html deleted file mode 100644 index 2eb5fe25..00000000 --- a/editor/client/public/index.html +++ /dev/null @@ -1,6 +0,0 @@ -
-
-

Dusk Map Editor

-

Browse and edit project assets.

-
-
diff --git a/editor/client/public/map/index.html b/editor/client/public/map/index.html deleted file mode 100644 index 5e491709..00000000 --- a/editor/client/public/map/index.html +++ /dev/null @@ -1,92 +0,0 @@ - - -
-
-
-
- - -
-
- - -
-
- - -
- - - - -
- - - - -
-
- - -
- - -
-
 
-
- -
-
- - - - - 0 -
-
-
-
- -
- -
Meshes
-
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    - -
    -
    - -
    -

    Preview (scroll to zoom)

    - -
    -
    - - - - - diff --git a/editor/client/public/map/map.css b/editor/client/public/map/map.css deleted file mode 100644 index 54b8843d..00000000 --- a/editor/client/public/map/map.css +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -.tile-palette { - display: flex; - flex-direction: column; - flex-wrap: wrap; - gap: 6px; - max-height: 600px; -} - -.tile-swatch { - position: relative; - width: 32px; - height: 32px; - border: 2px solid transparent; - border-radius: 4px; - cursor: pointer; - padding: 0; -} - -.tile-swatch.active { - border-color: #fff; -} - -.tile-swatch-icon { - position: absolute; - top: 0; - left: 0; - pointer-events: none; -} - -.dpad { - display: grid; - grid-template-columns: repeat(3, 2rem); - grid-template-rows: repeat(3, 2rem); - grid-template-areas: - ". n ." - "w . e" - ". s ."; - gap: 2px; -} - -.dpad-n { grid-area: n; } -.dpad-w { grid-area: w; } -.dpad-e { grid-area: e; } -.dpad-s { grid-area: s; } -.dpad button { padding: 0; } - -.tile-grid { - image-rendering: pixelated; - cursor: crosshair; - touch-action: none; - max-width: 100%; - height: auto; -} - -#previewCanvas { - width: 100%; - aspect-ratio: 1 / 1; - height: auto; -} diff --git a/editor/client/public/map/map.js b/editor/client/public/map/map.js deleted file mode 100644 index 0693663c..00000000 --- a/editor/client/public/map/map.js +++ /dev/null @@ -1,918 +0,0 @@ -// Copyright (c) 2026 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -"use strict"; - -(() => { - const SHAPES = [ - { type: ChunkTerrain.TILE_SHAPE_NULL, name: "Erase", color: "#20232a" }, - { type: ChunkTerrain.TILE_SHAPE_GROUND, name: "Ground", color: "#4caf50" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_NORTH, name: "Ramp North", color: "#2196f3" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_EAST, name: "Ramp East", color: "#03a9f4" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTH, name: "Ramp South", color: "#00bcd4" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_WEST, name: "Ramp West", color: "#009688" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_NORTHEAST, name: "Ramp NE", color: "#ff9800" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST, name: "Ramp NW", color: "#ff5722" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST, name: "Ramp SE", color: "#9c27b0" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST, name: "Ramp SW", color: "#e91e63" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_NORTHEAST_INNER, name: "Ramp NE Inner", color: "#795548" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST_INNER, name: "Ramp NW Inner", color: "#607d8b" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST_INNER, name: "Ramp SE Inner", color: "#8bc34a" }, - { type: ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST_INNER, name: "Ramp SW Inner", color: "#ffc107" }, - ]; - const SHAPE_COLORS = Object.fromEntries(SHAPES.map((s) => [s.type, s.color])); - - // Arrow direction per ramp, in canvas/screen space: north is up (dy < 0), - // east is right (dx > 0) - matches renderGrid()'s north-is-up convention. - const SHAPE_DIRECTIONS = { - [ChunkTerrain.TILE_SHAPE_RAMP_NORTH]: { dx: 0, dy: -1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_SOUTH]: { dx: 0, dy: 1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_EAST]: { dx: 1, dy: 0 }, - [ChunkTerrain.TILE_SHAPE_RAMP_WEST]: { dx: -1, dy: 0 }, - [ChunkTerrain.TILE_SHAPE_RAMP_NORTHEAST]: { dx: 1, dy: -1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST]: { dx: -1, dy: -1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST]: { dx: 1, dy: 1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST]: { dx: -1, dy: 1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_NORTHEAST_INNER]: { dx: 1, dy: -1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST_INNER]: { dx: -1, dy: -1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST_INNER]: { dx: 1, dy: 1 }, - [ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST_INNER]: { dx: -1, dy: 1 }, - }; - - const INNER_CORNER_SHAPES = new Set([ - ChunkTerrain.TILE_SHAPE_RAMP_NORTHEAST_INNER, - ChunkTerrain.TILE_SHAPE_RAMP_NORTHWEST_INNER, - ChunkTerrain.TILE_SHAPE_RAMP_SOUTHEAST_INNER, - ChunkTerrain.TILE_SHAPE_RAMP_SOUTHWEST_INNER, - ]); - - // Draws a single-headed arrow from (tailX, tailY) to (tipX, tipY). - function drawArrowSegment(ctx, tailX, tailY, tipX, tipY, size) { - ctx.strokeStyle = "#ffffff"; - ctx.fillStyle = "#ffffff"; - ctx.lineWidth = Math.max(1, size * 0.08); - ctx.lineCap = "round"; - - ctx.beginPath(); - ctx.moveTo(tailX, tailY); - ctx.lineTo(tipX, tipY); - ctx.stroke(); - - const headLen = size * 0.18; - const angle = Math.atan2(tipY - tailY, tipX - tailX); - const leftAngle = angle + Math.PI * 0.8; - const rightAngle = angle - Math.PI * 0.8; - ctx.beginPath(); - ctx.moveTo(tipX, tipY); - ctx.lineTo(tipX + Math.cos(leftAngle) * headLen, tipY + Math.sin(leftAngle) * headLen); - ctx.lineTo(tipX + Math.cos(rightAngle) * headLen, tipY + Math.sin(rightAngle) * headLen); - ctx.closePath(); - ctx.fill(); - } - - // Draws an arrow centered at (cx, cy) pointing toward the ramp's high - // side, so ramp direction is visible at a glance on both the palette - // swatches and the tile grid. Used for cardinal ramps and outer-corner - // ramps (a single raised corner). - function drawArrow(ctx, cx, cy, size, dx, dy) { - const mag = Math.hypot(dx, dy) || 1; - const ux = dx / mag, uy = dy / mag; - const len = size * 0.32; - drawArrowSegment(ctx, cx - ux * len, cy - uy * len, cx + ux * len, cy + uy * len, size); - } - - // Draws a plain right-angle bracket - two line segments meeting at 90 - // degrees at the tile's corner, one running along each of the two edges - // adjacent to it - so inner-corner ramps (three corners raised, one - // dropped) read as "the adjacent sides meeting in a 90-degree corner", - // distinct from the single diagonal arrow used for outer-corner ramps. - function drawCornerBracket(ctx, cx, cy, size, dx, dy) { - const cornerDist = size * 0.42; - const armLen = size * 0.34; - const cornerX = cx + dx * cornerDist; - const cornerY = cy + dy * cornerDist; - - ctx.strokeStyle = "#ffffff"; - ctx.lineWidth = Math.max(1, size * 0.08); - ctx.lineCap = "round"; - ctx.lineJoin = "round"; - - ctx.beginPath(); - ctx.moveTo(cornerX - dx * armLen, cornerY); - ctx.lineTo(cornerX, cornerY); - ctx.lineTo(cornerX, cornerY - dy * armLen); - ctx.stroke(); - } - - // Draws the direction icon for a ramp tile `type` in a `size`x`size` area - // centered at (cx, cy): a diagonal arrow for cardinal/outer-corner ramps, - // or a right-angle bracket for inner-corner ramps. No-op for shapes with - // no direction (ground, erase). - function drawShapeIcon(ctx, cx, cy, size, type) { - const dir = SHAPE_DIRECTIONS[type]; - if(!dir) return; - if(INNER_CORNER_SHAPES.has(type)) { - drawCornerBracket(ctx, cx, cy, size, dir.dx, dir.dy); - } else { - drawArrow(ctx, cx, cy, size, dir.dx, dir.dy); - } - } - - // Draws a small pencil icon centered in a `size`x`size` canvas. - function drawPencilIcon(ctx, size) { - ctx.save(); - ctx.translate(size / 2, size / 2); - ctx.rotate(-Math.PI / 4); - - const shaftW = size * 0.18; - const shaftH = size * 0.62; - - ctx.fillStyle = "#e0e0e0"; - ctx.fillRect(-shaftW / 2, shaftH * 0.28, shaftW, shaftH * 0.22); - - ctx.fillStyle = "#f0c419"; - ctx.fillRect(-shaftW / 2, -shaftH * 0.5, shaftW, shaftH * 0.78); - - ctx.fillStyle = "#8d6e63"; - ctx.beginPath(); - ctx.moveTo(-shaftW / 2, -shaftH * 0.5); - ctx.lineTo(shaftW / 2, -shaftH * 0.5); - ctx.lineTo(0, -shaftH * 0.5 - shaftW); - ctx.closePath(); - ctx.fill(); - - ctx.restore(); - } - - // Draws a small paint bucket icon centered in a `size`x`size` canvas. - function drawBucketIcon(ctx, size) { - ctx.save(); - ctx.translate(size / 2, size / 2); - - const w = size * 0.5, h = size * 0.34; - - ctx.strokeStyle = "#e0e0e0"; - ctx.lineWidth = Math.max(1, size * 0.06); - ctx.beginPath(); - ctx.arc(0, -h * 0.4, w * 0.4, Math.PI, 0); - ctx.stroke(); - - ctx.fillStyle = "#03a9f4"; - ctx.beginPath(); - ctx.moveTo(-w / 2, -h * 0.2); - ctx.lineTo(w / 2, -h * 0.2); - ctx.lineTo(w * 0.32, h * 0.6); - ctx.lineTo(-w * 0.32, h * 0.6); - ctx.closePath(); - ctx.fill(); - - ctx.beginPath(); - ctx.arc(-w * 0.55, h * 0.75, size * 0.06, 0, Math.PI * 2); - ctx.fill(); - - ctx.restore(); - } - - const TOOLS = [ - { id: "pencil", name: "Pencil", draw: drawPencilIcon }, - { id: "bucket", name: "Paint Bucket", draw: drawBucketIcon }, - ]; - - let coord = { x: 0, y: 0, z: 0 }; - let tiles = new Int32Array(ChunkTerrain.TILE_COUNT); - let meshes = []; - let chunkExists = false; - let currentZLevel = 0; - let selectedShape = ChunkTerrain.TILE_SHAPE_GROUND; - let zoomWorldH = 20; - let dirty = false; - let hoverTile = null; - let activeTool = "pencil"; - - let mapRenderer = null; - let terrainMesh = null; - let gridLinesMesh = null; - let terrainTexturePromise = null; - let modelIndex = null; - let neighborChunks = []; - const modelCache = new Map(); - - const UNDO_LIMIT = 100; - let undoStack = []; - - function markDirty() { - dirty = true; - } - - function snapshotState() { - return { - tiles: tiles.slice(), - meshes: meshes.map((m) => ({ file: m.file, pos: m.pos.slice() })), - }; - } - - function pushUndo() { - undoStack.push(snapshotState()); - if(undoStack.length > UNDO_LIMIT) undoStack.shift(); - } - - function undo() { - if(!undoStack.length) return; - const snap = undoStack.pop(); - tiles = snap.tiles; - meshes = snap.meshes; - dirty = true; - renderGrid(); - renderMeshList(); - renderPreview(); - updateStatus("Undid last change."); - } - - // Returns true if it's OK to proceed (no unsaved changes, or the user - // confirmed discarding them). - function confirmDiscardIfDirty() { - if(!dirty) return true; - return window.confirm("You have unsaved changes to this chunk. Discard them?"); - } - - function statusLine() { - return document.getElementById("statusLine"); - } - - function updateStatus(msg, isError) { - const el = statusLine(); - el.textContent = msg; - el.classList.toggle("text-danger", !!isError); - el.classList.toggle("text-muted", !isError); - } - - async function apiReadJson(path) { - const res = await fetch(`/api/read?path=${encodeURIComponent(path)}`); - const data = await res.json(); - return { ok: res.ok, data }; - } - - async function apiWrite(path, content) { - return fetch(`/api/write?path=${encodeURIComponent(path)}`, { - method: "POST", - body: JSON.stringify({ content }), - }); - } - - async function apiDelete(path) { - return fetch(`/api/delete?path=${encodeURIComponent(path)}`, { method: "POST" }); - } - - async function apiCompileChunk(x, y, z) { - const res = await fetch(`/api/compile-chunk?x=${x}&y=${y}&z=${z}`, { method: "POST" }); - return res.json(); - } - - async function apiLs(path) { - const res = await fetch(`/api/ls?path=${encodeURIComponent(path)}`); - return res.json(); - } - - async function apiFind(path, ext) { - const res = await fetch(`/api/find?path=${encodeURIComponent(path)}&ext=${encodeURIComponent(ext)}`); - return res.json(); - } - - function base64ToBuffer(base64) { - const bytes = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)); - return bytes.buffer; - } - - async function loadImageTexture(assetPath) { - const { ok, data } = await apiReadJson(assetPath); - if(!ok || data.error) return null; - const blob = new Blob([base64ToBuffer(data.content)], { type: "image/png" }); - const bitmap = await createImageBitmap(blob); - return mapRenderer.createTextureFromImage(bitmap); - } - - async function readDmfVertices(assetPath) { - const { ok, data } = await apiReadJson(assetPath); - if(!ok || data.error) throw new Error(`Failed to read ${assetPath}`); - return DMF.decode(base64ToBuffer(data.content)).floats; - } - - async function ensureModelIndex() { - if(modelIndex) return modelIndex; - const res = await apiFind("assets/models", ".json"); - modelIndex = new Map(); - for(const file of res.files || []) { - const base = file.split("/").pop().replace(/\.json$/, ""); - modelIndex.set(base, file); - } - return modelIndex; - } - - // Scales a mesh's stored [x, y, z] offset for preview, matching the - // Z scaling mapChunkLoaded() applies at runtime (chunk.meshOffsets[m][2] - // * WORLD_LAYER_HEIGHT) - x/y stay 1:1 since only Z is height-scaled. - function scaledMeshOffset(pos) { - return [pos[0], pos[1], pos[2] * ChunkTerrain.WORLD_LAYER_HEIGHT]; - } - - // Resolves a chunk mesh entry's bare filename (e.g. "house_5_3.dmf") to - // its model JSON by basename, mirroring find_model() in - // tools/asset/chunk/__main__.py - the chunk JSON only ever stores a bare - // filename, not a path. - async function resolveModelForMeshFile(file) { - await ensureModelIndex(); - const base = file.replace(/\.[^.]+$/, ""); - const rel = modelIndex.get(base); - if(!rel) return null; - - const modelPath = `assets/models/${rel}`; - if(modelCache.has(modelPath)) return modelCache.get(modelPath); - - const promise = (async () => { - const { ok, data } = await apiReadJson(modelPath); - if(!ok || data.error) throw new Error(`Failed to read model ${modelPath}`); - const modelDef = JSON.parse(data.content); - const meshFloats = await readDmfVertices(`assets/${modelDef.mesh}`); - const mesh = mapRenderer.createMesh(meshFloats); - const texture = modelDef.texture ? await loadImageTexture(`assets/${modelDef.texture}`) : null; - const colorBytes = modelDef.color || [255, 255, 255, 255]; - const color = colorBytes.map((c) => c / 255); - return { mesh, texture, color }; - })(); - modelCache.set(modelPath, promise); - return promise; - } - - function chunkPaths(x, y, z) { - return { - raw: `assetsraw/chunks/chunk_${x}_${y}_${z}.json`, - dcf: `assets/chunks/${x}_${y}_${z}.dcf`, - terrainDmf: `assets/meshes/chunks/chunk_${x}_${y}_${z}_0.dmf`, - terrainModel: `assets/models/chunks/chunk_${x}_${y}_${z}_0.json`, - }; - } - - // Loads the 8 same-Z neighbors around `coord` (read-only, for context in - // the 3D preview) and pre-builds their render data so renderPreview() - // doesn't have to rebuild GL buffers on every paint stroke. - async function loadNeighborChunks() { - const offsets = []; - for(let dy = -1; dy <= 1; dy++) { - for(let dx = -1; dx <= 1; dx++) { - if(dx || dy) offsets.push({ dx, dy }); - } - } - - const results = await Promise.all(offsets.map(async ({ dx, dy }) => { - const nx = coord.x + dx, ny = coord.y + dy, nz = coord.z; - const { ok, data } = await apiReadJson(chunkPaths(nx, ny, nz).raw); - if(!ok || data.error) return null; - - const json = JSON.parse(data.content); - const neighborTiles = new Int32Array(ChunkTerrain.TILE_COUNT); - for(const t of json.tiles || []) { - const [tx, ty, tz] = t.pos; - neighborTiles[ChunkTerrain.tileIndex(tx, ty, tz)] = t.type; - } - const neighborMeshes = (json.meshes || []).map((m) => ({ file: m.file, pos: m.pos || [0, 0, 0] })); - - const floats = ChunkTerrain.buildTerrainVerts(neighborTiles); - const terrain = floats.length ? { mesh: mapRenderer.createMesh(floats) } : null; - - const models = []; - for(const m of neighborMeshes) { - try { - const resolved = await resolveModelForMeshFile(m.file); - if(resolved) models.push({ ...resolved, offset: scaledMeshOffset(m.pos) }); - } catch(e) { - console.warn("Failed to load neighbor mesh preview", m.file, e); - } - } - - return { - offset: [dx * ChunkTerrain.CHUNK_WIDTH, dy * ChunkTerrain.CHUNK_HEIGHT, 0], - terrain, - models, - }; - })); - - neighborChunks = results.filter(Boolean); - } - - async function loadChunk(x, y, z) { - coord = { x, y, z }; - tiles = new Int32Array(ChunkTerrain.TILE_COUNT); - meshes = []; - chunkExists = false; - - const { ok, data } = await apiReadJson(chunkPaths(x, y, z).raw); - if(ok && !data.error) { - chunkExists = true; - const json = JSON.parse(data.content); - for(const t of json.tiles || []) { - const [tx, ty, tz] = t.pos; - tiles[ChunkTerrain.tileIndex(tx, ty, tz)] = t.type; - } - meshes = (json.meshes || []).map((m) => ({ file: m.file, pos: m.pos || [0, 0, 0] })); - } - - await loadNeighborChunks(); - dirty = false; - undoStack = []; - - renderGrid(); - renderMeshList(); - renderPreview(); - updateStatus(chunkExists - ? `Loaded chunk_${x}_${y}_${z}.json` - : `New (empty) chunk at ${x}, ${y}, ${z} - paint a tile and save to create it.`); - } - - async function saveChunk() { - const tilesArr = []; - for(let z = 0; z < ChunkTerrain.CHUNK_DEPTH; z++) { - for(let y = 0; y < ChunkTerrain.CHUNK_HEIGHT; y++) { - for(let x = 0; x < ChunkTerrain.CHUNK_WIDTH; x++) { - const type = tiles[ChunkTerrain.tileIndex(x, y, z)]; - if(type && type !== ChunkTerrain.TILE_SHAPE_NULL) { - tilesArr.push({ pos: [x, y, z], type, tile: 0 }); - } - } - } - } - - const paths = chunkPaths(coord.x, coord.y, coord.z); - - if(tilesArr.length === 0 && meshes.length === 0) { - await Promise.all(Object.values(paths).map((p) => apiDelete(p))); - chunkExists = false; - dirty = false; - updateStatus(`Chunk ${coord.x}, ${coord.y}, ${coord.z} is empty - deleted.`); - return; - } - - const json = { tiles: tilesArr, meshes: meshes.map((m) => ({ file: m.file, pos: m.pos })) }; - await apiWrite(paths.raw, JSON.stringify(json, null, 2)); - chunkExists = true; - dirty = false; - updateStatus("Saved. Compiling..."); - - const result = await apiCompileChunk(coord.x, coord.y, coord.z); - if(result.ok) { - updateStatus(`Compiled OK.\n${result.stdout}`); - } else { - updateStatus(`Compile FAILED (code ${result.returncode}):\n${result.stderr}`, true); - } - } - - function buildPalette() { - const el = document.getElementById("tilePalette"); - el.innerHTML = ""; - for(const s of SHAPES) { - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "tile-swatch" + (s.type === selectedShape ? " active" : ""); - btn.style.background = s.color; - btn.title = s.name; - btn.addEventListener("click", () => { - selectedShape = s.type; - buildPalette(); - }); - - if(SHAPE_DIRECTIONS[s.type]) { - const icon = document.createElement("canvas"); - icon.width = 32; - icon.height = 32; - icon.className = "tile-swatch-icon"; - drawShapeIcon(icon.getContext("2d"), 16, 16, 32, s.type); - btn.appendChild(icon); - } - - el.appendChild(btn); - } - } - - function buildToolPalette() { - const el = document.getElementById("toolPalette"); - el.innerHTML = ""; - for(const tool of TOOLS) { - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "tile-swatch" + (tool.id === activeTool ? " active" : ""); - btn.style.background = "#2a2d33"; - btn.title = tool.name; - btn.addEventListener("click", () => { - activeTool = tool.id; - buildToolPalette(); - }); - - const icon = document.createElement("canvas"); - icon.width = 32; - icon.height = 32; - icon.className = "tile-swatch-icon"; - tool.draw(icon.getContext("2d"), 32); - btn.appendChild(icon); - - el.appendChild(btn); - } - } - - function canvasToTile(e, canvas) { - const rect = canvas.getBoundingClientRect(); - const cell = canvas.width / ChunkTerrain.CHUNK_WIDTH; - const px = (e.clientX - rect.left) * (canvas.width / rect.width); - const py = (e.clientY - rect.top) * (canvas.height / rect.height); - const x = Math.floor(px / cell); - const yFromTop = Math.floor(py / cell); - const y = ChunkTerrain.CHUNK_HEIGHT - 1 - yFromTop; - if(x < 0 || x >= ChunkTerrain.CHUNK_WIDTH || y < 0 || y >= ChunkTerrain.CHUNK_HEIGHT) return null; - return { x, y }; - } - - function renderGrid() { - const canvas = document.getElementById("gridCanvas"); - const ctx = canvas.getContext("2d"); - const cell = canvas.width / ChunkTerrain.CHUNK_WIDTH; - - ctx.clearRect(0, 0, canvas.width, canvas.height); - for(let y = 0; y < ChunkTerrain.CHUNK_HEIGHT; y++) { - for(let x = 0; x < ChunkTerrain.CHUNK_WIDTH; x++) { - const type = tiles[ChunkTerrain.tileIndex(x, y, currentZLevel)]; - const sy = (ChunkTerrain.CHUNK_HEIGHT - 1 - y) * cell; - ctx.fillStyle = SHAPE_COLORS[type] || "#15171b"; - ctx.fillRect(x * cell, sy, cell, cell); - ctx.strokeStyle = "rgba(255, 255, 255, 0.25)"; - ctx.strokeRect(x * cell, sy, cell, cell); - - drawShapeIcon(ctx, x * cell + cell / 2, sy + cell / 2, cell, type); - } - } - - ctx.fillStyle = "#ffffff"; - for(const m of meshes) { - const [mx, my, mz] = m.pos; - if(Math.round(mz) !== currentZLevel) continue; - const sy = (ChunkTerrain.CHUNK_HEIGHT - 1 - my) * cell; - ctx.beginPath(); - ctx.arc(mx * cell + cell / 2, sy + cell / 2, cell * 0.3, 0, Math.PI * 2); - ctx.fill(); - } - - if(hoverTile) { - const sy = (ChunkTerrain.CHUNK_HEIGHT - 1 - hoverTile.y) * cell; - ctx.strokeStyle = "#ffeb3b"; - ctx.lineWidth = 2; - ctx.strokeRect(hoverTile.x * cell + 1, sy + 1, cell - 2, cell - 2); - } - } - - function hitTestMesh(e, canvas) { - const rect = canvas.getBoundingClientRect(); - const cell = canvas.width / ChunkTerrain.CHUNK_WIDTH; - const px = (e.clientX - rect.left) * (canvas.width / rect.width); - const py = (e.clientY - rect.top) * (canvas.height / rect.height); - - let closest = -1; - let closestDist = cell * 0.5; - meshes.forEach((m, i) => { - const [mx, my, mz] = m.pos; - if(Math.round(mz) !== currentZLevel) return; - const cx = mx * cell + cell / 2; - const cy = (ChunkTerrain.CHUNK_HEIGHT - 1 - my) * cell + cell / 2; - const dist = Math.hypot(px - cx, py - cy); - if(dist < closestDist) { closestDist = dist; closest = i; } - }); - return closest; - } - - function moveMeshTo(e, index) { - const canvas = document.getElementById("gridCanvas"); - const t = canvasToTile(e, canvas); - if(!t) return; - meshes[index].pos[0] = t.x; - meshes[index].pos[1] = t.y; - markDirty(); - renderGrid(); - renderMeshList(); - renderPreview(); - } - - function paintAt(e) { - const canvas = document.getElementById("gridCanvas"); - const t = canvasToTile(e, canvas); - if(!t) return; - tiles[ChunkTerrain.tileIndex(t.x, t.y, currentZLevel)] = selectedShape; - markDirty(); - renderGrid(); - renderPreview(); - } - - // 4-connected flood fill of same-type tiles at the current Z-level, - // starting from (startX, startY), replacing them with selectedShape. - function floodFill(startX, startY) { - const targetType = tiles[ChunkTerrain.tileIndex(startX, startY, currentZLevel)]; - if(targetType === selectedShape) return; - - const stack = [[startX, startY]]; - const visited = new Set(); - while(stack.length) { - const [x, y] = stack.pop(); - const key = `${x},${y}`; - if(visited.has(key)) continue; - if(x < 0 || x >= ChunkTerrain.CHUNK_WIDTH || y < 0 || y >= ChunkTerrain.CHUNK_HEIGHT) continue; - visited.add(key); - - const idx = ChunkTerrain.tileIndex(x, y, currentZLevel); - if(tiles[idx] !== targetType) continue; - tiles[idx] = selectedShape; - stack.push([x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]); - } - } - - function fillAt(e) { - const canvas = document.getElementById("gridCanvas"); - const t = canvasToTile(e, canvas); - if(!t) return; - pushUndo(); - floodFill(t.x, t.y); - markDirty(); - renderGrid(); - renderPreview(); - } - - function rebuildTerrainMesh() { - const floats = ChunkTerrain.buildTerrainVerts(tiles); - terrainMesh = floats.length ? mapRenderer.createMesh(floats) : null; - - const lineFloats = ChunkTerrain.buildGridLines(tiles); - gridLinesMesh = lineFloats.length ? mapRenderer.createMesh(lineFloats) : null; - } - - // Keeps the preview canvas's backing-store resolution matched to its - // actual displayed CSS size (times devicePixelRatio) - the canvas - // otherwise stays at its fixed width/height attributes (512x512) while - // CSS stretches it to fill the column, which upscales and blurs the - // WebGL output on wider or high-DPI screens. - function resizePreviewCanvas() { - const canvas = document.getElementById("previewCanvas"); - const dpr = window.devicePixelRatio || 1; - const displayWidth = Math.max(1, Math.round(canvas.clientWidth * dpr)); - const displayHeight = Math.max(1, Math.round(canvas.clientHeight * dpr)); - if(canvas.width !== displayWidth || canvas.height !== displayHeight) { - canvas.width = displayWidth; - canvas.height = displayHeight; - } - } - - async function renderPreview() { - if(!mapRenderer) return; - resizePreviewCanvas(); - rebuildTerrainMesh(); - - const models = []; - for(const m of meshes) { - try { - const resolved = await resolveModelForMeshFile(m.file); - if(resolved) models.push({ ...resolved, offset: scaledMeshOffset(m.pos) }); - } catch(e) { - console.warn("Failed to load mesh preview", m.file, e); - } - } - - let terrainTexture = null; - if(terrainMesh || neighborChunks.some((n) => n.terrain)) { - if(!terrainTexturePromise) terrainTexturePromise = loadImageTexture("assets/tiles.png"); - terrainTexture = await terrainTexturePromise; - } - - const neighbors = neighborChunks.map((n) => ({ - offset: n.offset, - terrain: n.terrain ? { mesh: n.terrain.mesh, texture: terrainTexture } : null, - models: n.models, - })); - - const zLevelHeight = currentZLevel * ChunkTerrain.WORLD_LAYER_HEIGHT; - mapRenderer.render({ - target: [ChunkTerrain.CHUNK_WIDTH / 2, ChunkTerrain.CHUNK_HEIGHT / 2, zLevelHeight], - worldH: zoomWorldH, - terrain: terrainMesh ? { mesh: terrainMesh, texture: terrainTexture } : null, - gridLines: gridLinesMesh ? { mesh: gridLinesMesh } : null, - models, - neighbors, - highlight: hoverTile ? { x: hoverTile.x, y: hoverTile.y, z: zLevelHeight } : null, - }); - } - - function renderMeshList() { - const ul = document.getElementById("meshList"); - ul.innerHTML = ""; - meshes.forEach((m, i) => { - const li = document.createElement("li"); - li.className = "list-group-item d-flex align-items-center gap-2 flex-wrap"; - - const label = document.createElement("span"); - label.className = "me-auto"; - label.textContent = m.file; - li.appendChild(label); - - ["X", "Y", "Z"].forEach((axis, axisIndex) => { - const input = document.createElement("input"); - input.type = "number"; - input.className = "form-control form-control-sm"; - input.style.width = "5rem"; - input.title = axis; - input.value = m.pos[axisIndex]; - input.addEventListener("change", () => { - pushUndo(); - m.pos[axisIndex] = parseFloat(input.value) || 0; - markDirty(); - renderGrid(); - renderPreview(); - }); - li.appendChild(input); - }); - - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "btn btn-sm btn-outline-danger"; - btn.textContent = "Remove"; - btn.addEventListener("click", () => { - pushUndo(); - meshes.splice(i, 1); - markDirty(); - renderMeshList(); - renderGrid(); - renderPreview(); - }); - - li.appendChild(btn); - ul.appendChild(li); - }); - } - - async function buildMeshPicker() { - await ensureModelIndex(); - const select = document.getElementById("meshPicker"); - select.innerHTML = ""; - for(const [base, rel] of [...modelIndex.entries()].sort()) { - const opt = document.createElement("option"); - opt.value = base; - opt.textContent = rel; - select.appendChild(opt); - } - } - - async function buildChunkBrowseList() { - const list = document.getElementById("chunkBrowseList"); - list.innerHTML = ""; - const res = await apiLs("assetsraw/chunks"); - for(const entry of res.entries || []) { - const m = entry.name.match(/^chunk_(-?\d+)_(-?\d+)_(-?\d+)\.json$/); - if(!m) continue; - const [, x, y, z] = m; - - const li = document.createElement("li"); - const a = document.createElement("a"); - a.className = "dropdown-item"; - a.href = "#"; - a.textContent = `${x}, ${y}, ${z}`; - a.addEventListener("click", (e) => { - e.preventDefault(); - goToChunk(parseInt(x, 10), parseInt(y, 10), parseInt(z, 10)); - }); - - li.appendChild(a); - list.appendChild(li); - } - } - - function setCoordInputs(x, y, z) { - document.getElementById("coordX").value = x; - document.getElementById("coordY").value = y; - document.getElementById("coordZ").value = z; - } - - function goToChunk(x, y, z) { - if(!confirmDiscardIfDirty()) return; - setCoordInputs(x, y, z); - loadChunk(x, y, z); - } - - function bindEvents() { - const gridCanvas = document.getElementById("gridCanvas"); - let painting = false; - let draggingMeshIndex = -1; - - gridCanvas.addEventListener("mousedown", (e) => { - if(activeTool === "bucket") { - fillAt(e); - return; - } - - const hit = hitTestMesh(e, gridCanvas); - pushUndo(); - if(hit !== -1) { - draggingMeshIndex = hit; - return; - } - painting = true; - paintAt(e); - }); - window.addEventListener("mouseup", () => { painting = false; draggingMeshIndex = -1; }); - gridCanvas.addEventListener("mousemove", (e) => { - hoverTile = canvasToTile(e, gridCanvas); - if(draggingMeshIndex !== -1) { moveMeshTo(e, draggingMeshIndex); return; } - if(painting) { paintAt(e); return; } - renderGrid(); - renderPreview(); - }); - gridCanvas.addEventListener("mouseleave", () => { - hoverTile = null; - renderGrid(); - renderPreview(); - }); - - function setZLevel(z) { - currentZLevel = Math.max(0, Math.min(ChunkTerrain.CHUNK_DEPTH - 1, z)); - document.getElementById("zLevel").value = currentZLevel; - document.getElementById("zLevelLabel").textContent = currentZLevel; - renderGrid(); - renderPreview(); - } - - document.getElementById("zLevel").addEventListener("input", (e) => { - setZLevel(parseInt(e.target.value, 10)); - }); - document.getElementById("zLevelDown").addEventListener("click", () => setZLevel(currentZLevel - 1)); - document.getElementById("zLevelUp").addEventListener("click", () => setZLevel(currentZLevel + 1)); - - document.getElementById("btnLoad").addEventListener("click", () => { - const x = parseInt(document.getElementById("coordX").value, 10) || 0; - const y = parseInt(document.getElementById("coordY").value, 10) || 0; - const z = parseInt(document.getElementById("coordZ").value, 10) || 0; - goToChunk(x, y, z); - }); - - // NORTH=+Y, EAST=+X (matches tile-shape convention used by the tile - // grid and tools/asset/chunk/__main__.py). - document.getElementById("navN").addEventListener("click", () => goToChunk(coord.x, coord.y + 1, coord.z)); - document.getElementById("navS").addEventListener("click", () => goToChunk(coord.x, coord.y - 1, coord.z)); - document.getElementById("navE").addEventListener("click", () => goToChunk(coord.x + 1, coord.y, coord.z)); - document.getElementById("navW").addEventListener("click", () => goToChunk(coord.x - 1, coord.y, coord.z)); - document.getElementById("navUp").addEventListener("click", () => goToChunk(coord.x, coord.y, coord.z + 1)); - document.getElementById("navDown").addEventListener("click", () => goToChunk(coord.x, coord.y, coord.z - 1)); - - function runSave() { - saveChunk().catch((e) => updateStatus(`Save failed: ${e.message}`, true)); - } - - document.getElementById("btnSave").addEventListener("click", runSave); - - document.getElementById("btnAddMesh").addEventListener("click", () => { - const base = document.getElementById("meshPicker").value; - if(!base) return; - const pos = [ - parseFloat(document.getElementById("meshX").value) || 0, - parseFloat(document.getElementById("meshY").value) || 0, - parseFloat(document.getElementById("meshZ").value) || 0, - ]; - pushUndo(); - meshes.push({ file: `${base}.dmf`, pos }); - markDirty(); - renderMeshList(); - renderGrid(); - renderPreview(); - }); - - document.getElementById("previewCanvas").addEventListener("wheel", (e) => { - e.preventDefault(); - zoomWorldH = Math.min(60, Math.max(4, zoomWorldH + Math.sign(e.deltaY))); - renderPreview(); - }, { passive: false }); - - window.addEventListener("resize", () => renderPreview()); - - window.addEventListener("keydown", (e) => { - if(!(e.ctrlKey || e.metaKey)) return; - const key = e.key.toLowerCase(); - if(key === "z") { - e.preventDefault(); - undo(); - } else if(key === "s") { - e.preventDefault(); - runSave(); - } - }); - } - - document.addEventListener("DOMContentLoaded", async () => { - buildPalette(); - buildToolPalette(); - mapRenderer = MapRenderer.create(document.getElementById("previewCanvas")); - bindEvents(); - await Promise.all([buildChunkBrowseList(), buildMeshPicker()]); - await loadChunk(coord.x, coord.y, coord.z); - }); -})(); diff --git a/editor/client/public/map/renderer.js b/editor/client/public/map/renderer.js deleted file mode 100644 index fc9c7470..00000000 --- a/editor/client/public/map/renderer.js +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (c) 2026 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -"use strict"; - -// MapRenderer - a minimal, dependency-free WebGL renderer for the chunk -// preview pane. The camera formula is ported 1:1 from -// src/dusk/scene/overworld/sceneoverworld.c (lines 62-81) so the preview -// approximates the game's own fixed-angle 3rd-person camera: the eye sits -// worldH units "behind" the target along Y and a proportional distance -// "above" along Z, always looking at the target, up = (0, 1, 0). -// -// The material model mirrors SHADER_UNLIT: a texture sampler multiplied by -// a flat RGBA tint, with a 1x1 white fallback texture standing in for -// untextured models. - -const MapRenderer = (() => { - const VERT_SRC = ` - attribute vec2 aUV; - attribute vec3 aPos; - uniform mat4 uModel; - uniform mat4 uView; - uniform mat4 uProjection; - varying vec2 vUV; - void main() { - vUV = aUV; - gl_Position = uProjection * uView * uModel * vec4(aPos, 1.0); - } - `; - - const FRAG_SRC = ` - precision mediump float; - varying vec2 vUV; - uniform sampler2D uTexture; - uniform vec4 uColor; - void main() { - gl_FragColor = texture2D(uTexture, vUV) * uColor; - } - `; - - function mat4Identity(out) { - out.fill(0); - out[0] = out[5] = out[10] = out[15] = 1; - return out; - } - - function mat4Translation(out, v) { - mat4Identity(out); - out[12] = v[0]; - out[13] = v[1]; - out[14] = v[2]; - return out; - } - - function mat4Perspective(out, fovy, aspect, near, far) { - const f = 1.0 / Math.tan(fovy / 2); - out.fill(0); - out[0] = f / aspect; - out[5] = f; - out[10] = (far + near) / (near - far); - out[11] = -1; - out[14] = (2 * far * near) / (near - far); - return out; - } - - function vec3Sub(a, b) { - return [a[0] - b[0], a[1] - b[1], a[2] - b[2]]; - } - - function vec3Cross(a, b) { - return [ - a[1] * b[2] - a[2] * b[1], - a[2] * b[0] - a[0] * b[2], - a[0] * b[1] - a[1] * b[0], - ]; - } - - function vec3Normalize(a) { - const len = Math.hypot(a[0], a[1], a[2]) || 1; - return [a[0] / len, a[1] / len, a[2] / len]; - } - - function mat4LookAt(out, eye, center, up) { - const zAxis = vec3Normalize(vec3Sub(eye, center)); - const xAxis = vec3Normalize(vec3Cross(up, zAxis)); - const yAxis = vec3Cross(zAxis, xAxis); - - out[0] = xAxis[0]; out[1] = yAxis[0]; out[2] = zAxis[0]; out[3] = 0; - out[4] = xAxis[1]; out[5] = yAxis[1]; out[6] = zAxis[1]; out[7] = 0; - out[8] = xAxis[2]; out[9] = yAxis[2]; out[10] = zAxis[2]; out[11] = 0; - out[12] = -(xAxis[0] * eye[0] + xAxis[1] * eye[1] + xAxis[2] * eye[2]); - out[13] = -(yAxis[0] * eye[0] + yAxis[1] * eye[1] + yAxis[2] * eye[2]); - out[14] = -(zAxis[0] * eye[0] + zAxis[1] * eye[1] + zAxis[2] * eye[2]); - out[15] = 1; - return out; - } - - // Ported from sceneoverworld.c:62-81. Returns { eye, view }. - function computeCamera(target, worldH) { - const fov = Math.PI / 4; // glm_rad(45.0f) - const zDist = (worldH * 0.5) / Math.tan(fov * 0.5); - const offset = -worldH; - - const eye = [target[0], target[1] + offset, target[2] + zDist]; - const view = mat4LookAt(new Float32Array(16), eye, target, [0, 1, 0]); - return { eye, view, fov }; - } - - function compileShader(gl, type, src) { - const shader = gl.createShader(type); - gl.shaderSource(shader, src); - gl.compileShader(shader); - if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - const info = gl.getShaderInfoLog(shader); - gl.deleteShader(shader); - throw new Error(`Shader compile failed: ${info}`); - } - return shader; - } - - function create(canvas) { - const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); - if(!gl) throw new Error("WebGL is not available in this browser"); - - const program = gl.createProgram(); - gl.attachShader(program, compileShader(gl, gl.VERTEX_SHADER, VERT_SRC)); - gl.attachShader(program, compileShader(gl, gl.FRAGMENT_SHADER, FRAG_SRC)); - gl.linkProgram(program); - if(!gl.getProgramParameter(program, gl.LINK_STATUS)) { - throw new Error(`Program link failed: ${gl.getProgramInfoLog(program)}`); - } - - const attribs = { - aUV: gl.getAttribLocation(program, "aUV"), - aPos: gl.getAttribLocation(program, "aPos"), - }; - const uniforms = { - uModel: gl.getUniformLocation(program, "uModel"), - uView: gl.getUniformLocation(program, "uView"), - uProjection: gl.getUniformLocation(program, "uProjection"), - uTexture: gl.getUniformLocation(program, "uTexture"), - uColor: gl.getUniformLocation(program, "uColor"), - }; - - const whiteTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, whiteTexture); - gl.texImage2D( - gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, - new Uint8Array([255, 255, 255, 255]), - ); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - - gl.enable(gl.DEPTH_TEST); - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - // Terrain/mesh winding isn't guaranteed consistent relative to this - // preview's fixed camera angle, so backface culling stays off - this - // is an authoring preview, not a performance-sensitive renderer, and - // an invisible mesh is a worse failure mode than a visible backface. - - // Uploads interleaved [u, v, x, y, z] float data (DMF/terrain layout) - // into a GL buffer. Returns { buffer, vertexCount }. - function createMesh(floats) { - const buffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, floats, gl.STATIC_DRAW); - return { buffer, vertexCount: floats.length / 5 }; - } - - function createTextureFromImage(image) { - const texture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - return texture; - } - - function drawMesh(mesh, model, texture, color, depthWrite, mode) { - gl.depthMask(depthWrite !== false); - gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffer); - gl.enableVertexAttribArray(attribs.aUV); - gl.vertexAttribPointer(attribs.aUV, 2, gl.FLOAT, false, 20, 0); - gl.enableVertexAttribArray(attribs.aPos); - gl.vertexAttribPointer(attribs.aPos, 3, gl.FLOAT, false, 20, 8); - - gl.uniformMatrix4fv(uniforms.uModel, false, model); - gl.uniform4f(uniforms.uColor, color[0], color[1], color[2], color[3]); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture || whiteTexture); - gl.uniform1i(uniforms.uTexture, 0); - - gl.drawArrays(mode || gl.TRIANGLES, 0, mesh.vertexCount); - } - - // Builds a 4-vertex outline of the tile at (x, y, z), lifted slightly - // to avoid z-fighting with the terrain surface beneath it. - function buildHighlightMesh(x, y, z) { - const eps = 0.02; - return createMesh(new Float32Array([ - 0, 0, x, y, z + eps, - 0, 0, x + 1, y, z + eps, - 0, 0, x + 1, y + 1, z + eps, - 0, 0, x, y + 1, z + eps, - ])); - } - - // Neighboring chunks are drawn dimmer and semi-transparent, so they - // read as context rather than part of the chunk being edited. - const NEIGHBOR_ALPHA = 0.35; - const NEIGHBOR_DARKEN = 0.5; - - // scene = { - // target: [x, y, z], worldH: number, - // terrain: { mesh, texture } | null, - // gridLines: { mesh } | null, - // models: [{ mesh, texture, color: [r,g,b,a in 0..1], offset: [x,y,z] }], - // neighbors: [{ - // offset: [x,y,z], - // terrain: { mesh, texture } | null, - // models: [{ mesh, texture, color, offset }], - // }], - // highlight: { x, y, z } | null, - // } - function render(scene) { - const width = canvas.width, height = canvas.height; - gl.viewport(0, 0, width, height); - gl.clearColor(0.16, 0.18, 0.22, 1); - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - gl.useProgram(program); - gl.depthMask(true); - - const { view, fov } = computeCamera(scene.target, scene.worldH); - const projection = mat4Perspective(new Float32Array(16), fov, width / height, 0.1, 1000); - gl.uniformMatrix4fv(uniforms.uProjection, false, projection); - gl.uniformMatrix4fv(uniforms.uView, false, view); - - const identity = mat4Identity(new Float32Array(16)); - - if(scene.terrain) { - drawMesh(scene.terrain.mesh, identity, scene.terrain.texture, [1, 1, 1, 1], true); - } - - if(scene.gridLines) { - drawMesh(scene.gridLines.mesh, identity, null, [0, 0, 0, 0.35], false, gl.LINES); - } - - for(const model of scene.models) { - const modelMatrix = mat4Translation(new Float32Array(16), model.offset); - drawMesh(model.mesh, modelMatrix, model.texture, model.color, true); - } - - for(const neighbor of scene.neighbors || []) { - if(neighbor.terrain) { - const modelMatrix = mat4Translation(new Float32Array(16), neighbor.offset); - drawMesh( - neighbor.terrain.mesh, modelMatrix, neighbor.terrain.texture, - [NEIGHBOR_DARKEN, NEIGHBOR_DARKEN, NEIGHBOR_DARKEN, NEIGHBOR_ALPHA], false, - ); - } - - for(const model of neighbor.models) { - const worldOffset = [ - neighbor.offset[0] + model.offset[0], - neighbor.offset[1] + model.offset[1], - neighbor.offset[2] + model.offset[2], - ]; - const modelMatrix = mat4Translation(new Float32Array(16), worldOffset); - const color = [ - model.color[0] * NEIGHBOR_DARKEN, - model.color[1] * NEIGHBOR_DARKEN, - model.color[2] * NEIGHBOR_DARKEN, - model.color[3] * NEIGHBOR_ALPHA, - ]; - drawMesh(model.mesh, modelMatrix, model.texture, color, false); - } - } - - if(scene.highlight) { - const { x, y, z } = scene.highlight; - const highlightMesh = buildHighlightMesh(x, y, z); - drawMesh(highlightMesh, identity, null, [1, 0.92, 0.23, 1], false, gl.LINE_LOOP); - } - } - - return { gl, createMesh, createTextureFromImage, render }; - } - - return Object.freeze({ create, computeCamera }); -})(); diff --git a/editor/client/public/template.html b/editor/client/public/template.html deleted file mode 100644 index 5ea9aba2..00000000 --- a/editor/client/public/template.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - Dusk Map Editor - - - - -
    - - - diff --git a/editor/server/server.py b/editor/server/server.py deleted file mode 100644 index fe6d68db..00000000 --- a/editor/server/server.py +++ /dev/null @@ -1,295 +0,0 @@ -""" -Map Editor HTTP Server - -Serves editor/client/public/ as static files with smart routing: - / -> index.html - /page -> page.html or page/index.html - /index -> index.html - -API endpoints (all paths relative to project root): - GET /api/ls?path= directory listing - GET /api/read?path= file contents - GET /api/find?path=&ext=<.json> recursive file listing by extension - POST /api/write?path= write file (JSON body: {"content":"..."}) - POST /api/mkdir?path= create directory - POST /api/delete?path= delete a file - POST /api/compile-chunk?x=&y=&z= recompile a chunk JSON to .dcf -""" - -import os -import re -import sys -import json -import mimetypes -import subprocess -from http.server import HTTPServer, BaseHTTPRequestHandler -from urllib.parse import urlparse, parse_qs, unquote -from pathlib import Path - -CHUNK_COORD_RE = re.compile(r"^-?\d+$") - -PORT = 3000 -SCRIPT_DIR = Path(__file__).parent.resolve() -PUBLIC_DIR = SCRIPT_DIR.parent / "client" / "public" -PROJECT_ROOT = SCRIPT_DIR.parent.parent.resolve() - - -class Handler(BaseHTTPRequestHandler): - def do_GET(self): - parsed = urlparse(self.path) - path = unquote(parsed.path) - if path.startswith("/api/"): - params = parse_qs(parsed.query) - if path == "/api/ls": - self.api_ls(params) - elif path == "/api/read": - self.api_read(params) - elif path == "/api/find": - self.api_find(params) - else: - self.send_error(404) - else: - self.serve_static(path) - - def do_POST(self): - parsed = urlparse(self.path) - params = parse_qs(parsed.query) - if parsed.path == "/api/write": - self.api_write(params) - elif parsed.path == "/api/mkdir": - self.api_mkdir(params) - elif parsed.path == "/api/delete": - self.api_delete(params) - elif parsed.path == "/api/compile-chunk": - self.api_compile_chunk(params) - else: - self.send_error(404) - - # ------------------------------------------------------------------ - # Helpers - # ------------------------------------------------------------------ - - def resolve_project_path(self, rel): - rel = rel.lstrip("/") - target = (PROJECT_ROOT / rel).resolve() - if not str(target).startswith(str(PROJECT_ROOT)): - return None - return target - - def send_json(self, data, code=200): - body = json.dumps(data, indent=2).encode("utf-8") - self.send_response(code) - self.send_header("Content-Type", "application/json") - self.send_header("Content-Length", len(body)) - self.end_headers() - self.wfile.write(body) - - def read_body(self): - length = int(self.headers.get("Content-Length", 0)) - return self.rfile.read(length) - - # ------------------------------------------------------------------ - # API handlers - # ------------------------------------------------------------------ - - def api_ls(self, params): - rel = params.get("path", [""])[0] - target = self.resolve_project_path(rel) - if target is None: - self.send_json({"error": "invalid path"}, 400) - return - if not target.exists(): - self.send_json({"error": "path not found"}, 404) - return - if not target.is_dir(): - self.send_json({"error": "not a directory"}, 400) - return - - entries = [] - for entry in sorted(target.iterdir(), key=lambda e: (e.is_file(), e.name)): - entries.append({ - "name": entry.name, - "type": "dir" if entry.is_dir() else "file", - "size": entry.stat().st_size if entry.is_file() else None, - }) - self.send_json({ - "path": str(target.relative_to(PROJECT_ROOT)), - "entries": entries, - }) - - def api_read(self, params): - rel = params.get("path", [""])[0] - target = self.resolve_project_path(rel) - if target is None: - self.send_json({"error": "invalid path"}, 400) - return - if not target.exists(): - self.send_json({"error": "file not found"}, 404) - return - if not target.is_file(): - self.send_json({"error": "not a file"}, 400) - return - - try: - content = target.read_text(encoding="utf-8") - self.send_json({ - "path": str(target.relative_to(PROJECT_ROOT)), - "content": content, - }) - except UnicodeDecodeError: - import base64 - content = base64.b64encode(target.read_bytes()).decode("ascii") - self.send_json({ - "path": str(target.relative_to(PROJECT_ROOT)), - "content": content, - "encoding": "base64", - }) - - def api_write(self, params): - rel = params.get("path", [""])[0] - target = self.resolve_project_path(rel) - if target is None: - self.send_json({"error": "invalid path"}, 400) - return - - body = self.read_body() - try: - data = json.loads(body) - content = data.get("content", "") - except (json.JSONDecodeError, UnicodeDecodeError): - content = body.decode("utf-8") - - target.parent.mkdir(parents=True, exist_ok=True) - target.write_text(content, encoding="utf-8") - self.send_json({"ok": True, "path": str(target.relative_to(PROJECT_ROOT))}) - - def api_mkdir(self, params): - rel = params.get("path", [""])[0] - target = self.resolve_project_path(rel) - if target is None: - self.send_json({"error": "invalid path"}, 400) - return - target.mkdir(parents=True, exist_ok=True) - self.send_json({"ok": True, "path": str(target.relative_to(PROJECT_ROOT))}) - - def api_delete(self, params): - rel = params.get("path", [""])[0] - target = self.resolve_project_path(rel) - if target is None: - self.send_json({"error": "invalid path"}, 400) - return - if target.is_file(): - target.unlink() - self.send_json({"ok": True, "path": str(target.relative_to(PROJECT_ROOT))}) - - def api_find(self, params): - rel = params.get("path", [""])[0] - ext = params.get("ext", [""])[0] - target = self.resolve_project_path(rel) - if target is None: - self.send_json({"error": "invalid path"}, 400) - return - if not target.is_dir(): - self.send_json({"error": "not a directory"}, 400) - return - - pattern = f"*{ext}" if ext else "*" - paths = sorted( - str(p.relative_to(target)).replace(os.sep, "/") - for p in target.rglob(pattern) - if p.is_file() - ) - self.send_json({"path": str(target.relative_to(PROJECT_ROOT)), "files": paths}) - - def api_compile_chunk(self, params): - x = params.get("x", [""])[0] - y = params.get("y", [""])[0] - z = params.get("z", [""])[0] - if not (CHUNK_COORD_RE.match(x) and CHUNK_COORD_RE.match(y) and CHUNK_COORD_RE.match(z)): - self.send_json({"error": "invalid chunk coordinates"}, 400) - return - - json_path = PROJECT_ROOT / "assetsraw" / "chunks" / f"chunk_{x}_{y}_{z}.json" - if not json_path.is_file(): - self.send_json({"error": "chunk json not found"}, 404) - return - - result = subprocess.run( - [sys.executable, "-m", "tools.asset.chunk", str(json_path)], - cwd=str(PROJECT_ROOT), - capture_output=True, - text=True, - ) - self.send_json({ - "ok": result.returncode == 0, - "returncode": result.returncode, - "stdout": result.stdout, - "stderr": result.stderr, - }) - - # ------------------------------------------------------------------ - # Static file serving - # ------------------------------------------------------------------ - - def serve_static(self, path): - clean = path.lstrip("/") - candidates = [] - - if clean == "" or clean == "index" or clean == "index.html": - candidates = ["index.html"] - else: - candidates.append(clean) - if "." not in Path(clean).name: - candidates.append(clean + ".html") - candidates.append(clean + "/index.html") - - for candidate in candidates: - file_path = PUBLIC_DIR / candidate - if file_path.is_file(): - self.serve_file(file_path) - return - - self.send_error(404) - - def serve_file(self, file_path): - mime, _ = mimetypes.guess_type(str(file_path)) - mime = mime or "application/octet-stream" - - template = PUBLIC_DIR / "template.html" - if ( - mime == "text/html" - and file_path.name != "template.html" - and template.is_file() - ): - fragment = file_path.read_text(encoding="utf-8") - shell = template.read_text(encoding="utf-8") - marker = shell.find('id="editor"') - if marker == -1: - content = shell.encode("utf-8") - else: - tag_end = shell.index(">", marker) + 1 - close_idx = shell.index("", tag_end) - content = (shell[:tag_end] + fragment + shell[close_idx:]).encode("utf-8") - else: - content = file_path.read_bytes() - - self.send_response(200) - self.send_header("Content-Type", mime) - self.send_header("Content-Length", len(content)) - self.end_headers() - self.wfile.write(content) - - def log_message(self, fmt, *args): - print(f" {self.address_string()} {fmt % args}") - - -if __name__ == "__main__": - print(f"Map Editor") - print(f" http://localhost:{PORT}") - print(f" public : {PUBLIC_DIR}") - print(f" project: {PROJECT_ROOT}") - server = HTTPServer(("", PORT), Handler) - try: - server.serve_forever() - except KeyboardInterrupt: - print("\nStopped.") diff --git a/editor/start.sh b/editor/start.sh deleted file mode 100755 index e1871d04..00000000 --- a/editor/start.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -e -cd "$(dirname "$0")" -python3 server/server.py diff --git a/src/dusk/CMakeLists.txt b/src/dusk/CMakeLists.txt index d99f093c..e802c9fc 100644 --- a/src/dusk/CMakeLists.txt +++ b/src/dusk/CMakeLists.txt @@ -53,7 +53,6 @@ target_sources(${DUSK_BINARY_TARGET_NAME} # Subdirs add_subdirectory(animation) -add_subdirectory(event) add_subdirectory(assert) add_subdirectory(asset) add_subdirectory(console) @@ -63,12 +62,10 @@ add_subdirectory(engine) add_subdirectory(error) add_subdirectory(input) add_subdirectory(locale) -add_subdirectory(rpg) add_subdirectory(scene) add_subdirectory(system) add_subdirectory(time) add_subdirectory(ui) add_subdirectory(network) -add_subdirectory(save) add_subdirectory(util) add_subdirectory(thread) \ No newline at end of file diff --git a/src/dusk/asset/CMakeLists.txt b/src/dusk/asset/CMakeLists.txt index 0e87c96f..39e32cab 100644 --- a/src/dusk/asset/CMakeLists.txt +++ b/src/dusk/asset/CMakeLists.txt @@ -7,7 +7,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC asset.c - assetbatch.c assetfile.c ) diff --git a/src/dusk/asset/asset.c b/src/dusk/asset/asset.c index 1a26fc16..314166d0 100644 --- a/src/dusk/asset/asset.c +++ b/src/dusk/asset/asset.c @@ -320,9 +320,7 @@ errorret_t assetUpdate(void) { "Loader did not set entry state to error on failed load." ); } else if(loading->entry->state == ASSET_ENTRY_STATE_LOADED) { - assetentry_t *loadedEntry = loading->entry; loading->entry = NULL; - eventInvoke(&loadedEntry->onLoaded, loadedEntry); } loading++; @@ -343,10 +341,8 @@ errorret_t assetUpdate(void) { break; case ASSET_ENTRY_STATE_ERROR: { - assetentry_t *errEntry = loading->entry; loading->entry = NULL; threadMutexUnlock(&loading->mutex); - eventInvoke(&errEntry->onError, errEntry); errorThrow("Failed to load asset asynchronously."); break; } diff --git a/src/dusk/asset/assetbatch.c b/src/dusk/asset/assetbatch.c deleted file mode 100644 index 3bb27927..00000000 --- a/src/dusk/asset/assetbatch.c +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "assetbatch.h" -#include "asset.h" -#include "assert/assert.h" -#include "util/memory.h" -#include - -void assetBatchInit( - assetbatch_t *batch, - const uint16_t count, - const assetbatchdesc_t *descs -) { - assertNotNull(batch, "Batch cannot be NULL."); - assertNotNull(descs, "Descs cannot be NULL."); - assertTrue(count > 0, "Count must be greater than 0."); - assertTrue( - count <= ASSET_BATCH_COUNT_MAX, "Count exceeds ASSET_BATCH_COUNT_MAX." - ); - - memoryZero(batch, sizeof(assetbatch_t)); - batch->count = count; - - eventInit( - &batch->onLoaded, - batch->onLoadedCallbacks, batch->onLoadedUsers, ASSET_BATCH_EVENT_MAX - ); - eventInit( - &batch->onEntryLoaded, - batch->onEntryLoadedCallbacks, - batch->onEntryLoadedUsers, - ASSET_BATCH_EVENT_MAX - ); - eventInit( - &batch->onError, - batch->onErrorCallbacks, batch->onErrorUsers, ASSET_BATCH_EVENT_MAX - ); - eventInit( - &batch->onEntryError, - batch->onEntryErrorCallbacks, - batch->onEntryErrorUsers, - ASSET_BATCH_EVENT_MAX - ); - - for(uint16_t i = 0; i < count; i++) { - batch->inputs[i] = descs[i].input; - batch->entries[i] = assetLock( - descs[i].path, descs[i].type, &batch->inputs[i] - ); - - if(batch->entries[i]->state == ASSET_ENTRY_STATE_LOADED) { - // Already loaded (cached) - count it now, no subscription needed. - batch->loadedCount++; - } else if(batch->entries[i]->state == ASSET_ENTRY_STATE_ERROR) { - batch->errorCount++; - } else { - eventSubscribe( - &batch->entries[i]->onLoaded, assetBatchEntryOnLoadedCb, batch - ); - eventSubscribe( - &batch->entries[i]->onError, assetBatchEntryOnErrorCb, batch - ); - } - } -} - -void assetBatchLock(assetbatch_t *batch) { - assertNotNull(batch, "Batch cannot be NULL."); - for(uint16_t i = 0; i < batch->count; i++) { - assetEntryLock(batch->entries[i]); - } -} - -void assetBatchUnlock(assetbatch_t *batch) { - assertNotNull(batch, "Batch cannot be NULL."); - for(uint16_t i = 0; i < batch->count; i++) { - assetEntryUnlock(batch->entries[i]); - } -} - -bool_t assetBatchIsLoaded(const assetbatch_t *batch) { - assertNotNull(batch, "Batch cannot be NULL."); - for(uint16_t i = 0; i < batch->count; i++) { - if(batch->entries[i]->state != ASSET_ENTRY_STATE_LOADED) return false; - } - return true; -} - -bool_t assetBatchHasError(const assetbatch_t *batch) { - assertNotNull(batch, "Batch cannot be NULL."); - for(uint16_t i = 0; i < batch->count; i++) { - if(batch->entries[i]->state == ASSET_ENTRY_STATE_ERROR) return true; - } - return false; -} - -errorret_t assetBatchRequireLoaded(assetbatch_t *batch) { - assertNotNull(batch, "Batch cannot be NULL."); - - bool_t allDone; - do { - allDone = true; - for(uint16_t i = 0; i < batch->count; i++) { - const assetentrystate_t state = batch->entries[i]->state; - if(state == ASSET_ENTRY_STATE_ERROR) { - errorThrow("Asset '%s' failed to load.", batch->entries[i]->name); - } - if(state != ASSET_ENTRY_STATE_LOADED) { - allDone = false; - } - } - if(!allDone) { - usleep(1000); - errorChain(assetUpdate()); - } - } while(!allDone); - - errorOk(); -} - -void assetBatchDispose(assetbatch_t *batch) { - assertNotNull(batch, "Batch cannot be NULL."); - for(uint16_t i = 0; i < batch->count; i++) { - if(batch->entries[i]) { - // Unsubscribe while we still hold a lock so the entry is live. - eventUnsubscribe(&batch->entries[i]->onLoaded, assetBatchEntryOnLoadedCb); - eventUnsubscribe(&batch->entries[i]->onError, assetBatchEntryOnErrorCb); - assetUnlockEntry(batch->entries[i]); - } - } - memoryZero(batch, sizeof(assetbatch_t)); -} - -void assetBatchEntryOnLoadedCb(void *params, void *user) { - assetentry_t *entry = (assetentry_t *)params; - assetbatch_t *batch = (assetbatch_t *)user; - - batch->loadedCount++; - eventInvoke(&batch->onEntryLoaded, entry); - - if((uint16_t)(batch->loadedCount + batch->errorCount) >= batch->count) { - if(batch->errorCount == 0) { - eventInvoke(&batch->onLoaded, batch); - } else { - eventInvoke(&batch->onError, batch); - } - } -} - -void assetBatchEntryOnErrorCb(void *params, void *user) { - assetentry_t *entry = (assetentry_t *)params; - assetbatch_t *batch = (assetbatch_t *)user; - - batch->errorCount++; - eventInvoke(&batch->onEntryError, entry); - - if((uint16_t)(batch->loadedCount + batch->errorCount) >= batch->count) { - eventInvoke(&batch->onError, batch); - } -} diff --git a/src/dusk/asset/assetbatch.h b/src/dusk/asset/assetbatch.h deleted file mode 100644 index 20aaac2e..00000000 --- a/src/dusk/asset/assetbatch.h +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "asset/loader/assetentry.h" -#include "asset/loader/assetloader.h" -#include "event/event.h" - -#define ASSET_BATCH_COUNT_MAX 64 -#define ASSET_BATCH_EVENT_MAX 4 - -typedef struct { - const char_t *path; - assetloadertype_t type; - assetloaderinput_t input; -} assetbatchdesc_t; - -typedef struct { - assetentry_t *entries[ASSET_BATCH_COUNT_MAX]; - assetloaderinput_t inputs[ASSET_BATCH_COUNT_MAX]; - uint16_t count; - uint16_t loadedCount; - uint16_t errorCount; - - /** Fires once when every entry loaded. params = assetbatch_t * */ - event_t onLoaded; - eventcallback_t onLoadedCallbacks[ASSET_BATCH_EVENT_MAX]; - void *onLoadedUsers[ASSET_BATCH_EVENT_MAX]; - - /** Fires each time a single entry loads. params = assetentry_t * */ - event_t onEntryLoaded; - eventcallback_t onEntryLoadedCallbacks[ASSET_BATCH_EVENT_MAX]; - void *onEntryLoadedUsers[ASSET_BATCH_EVENT_MAX]; - - /** Fires when all entries finish (any with errors). params: assetbatch_t * */ - event_t onError; - eventcallback_t onErrorCallbacks[ASSET_BATCH_EVENT_MAX]; - void *onErrorUsers[ASSET_BATCH_EVENT_MAX]; - - /** Fires each time a single entry errors. params = assetentry_t * */ - event_t onEntryError; - eventcallback_t onEntryErrorCallbacks[ASSET_BATCH_EVENT_MAX]; - void *onEntryErrorUsers[ASSET_BATCH_EVENT_MAX]; -} assetbatch_t; - -/** - * Initialises the batch from an array of descriptors. Each entry is locked - * and queued for loading immediately. - * - * @param batch Batch to initialise. - * @param descs Array of entry descriptors (need not outlive this call). - * @param count Number of descriptors (must be <= ASSET_BATCH_COUNT_MAX). - */ -void assetBatchInit( - assetbatch_t *batch, - uint16_t count, - const assetbatchdesc_t *descs -); - -/** - * Acquires one additional lock on every entry in the batch. - * - * @param batch Batch to lock. - */ -void assetBatchLock(assetbatch_t *batch); - -/** - * Releases one lock from every entry in the batch. When an entry's lock - * count reaches zero it will be reaped on the next assetUpdate. - * - * @param batch Batch to unlock. - */ -void assetBatchUnlock(assetbatch_t *batch); - -/** - * Returns true if every entry in the batch has finished loading. - * - * @param batch Batch to query. - */ -bool_t assetBatchIsLoaded(const assetbatch_t *batch); - -/** - * Returns true if any entry in the batch is in an error state. - * - * @param batch Batch to query. - */ -bool_t assetBatchHasError(const assetbatch_t *batch); - -/** - * Blocks until every entry is loaded. Returns an error if any entry fails. - * - * @param batch Batch to wait on. - */ -errorret_t assetBatchRequireLoaded(assetbatch_t *batch); - -/** - * Releases the batch's lock on every entry and clears the batch. After this - * call the batch struct may be reused with assetBatchInit. - * - * @param batch Batch to dispose. - */ -void assetBatchDispose(assetbatch_t *batch); - -/** - * Event trampoline invoked when a batch entry finishes loading. - * Increments the loaded counter and fires batch-level events. - * - * @param params The loaded assetentry_t pointer. - * @param user The owning assetbatch_t pointer. - */ -void assetBatchEntryOnLoadedCb(void *params, void *user); - -/** - * Event trampoline invoked when a batch entry fails to load. - * Increments the error counter and fires batch-level events. - * - * @param params The errored assetentry_t pointer. - * @param user The owning assetbatch_t pointer. - */ -void assetBatchEntryOnErrorCb(void *params, void *user); diff --git a/src/dusk/asset/loader/CMakeLists.txt b/src/dusk/asset/loader/CMakeLists.txt index 30f97bc1..44bb11b1 100644 --- a/src/dusk/asset/loader/CMakeLists.txt +++ b/src/dusk/asset/loader/CMakeLists.txt @@ -15,5 +15,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} add_subdirectory(display) add_subdirectory(locale) add_subdirectory(json) -add_subdirectory(chunk) add_subdirectory(dmf) \ No newline at end of file diff --git a/src/dusk/asset/loader/assetentry.c b/src/dusk/asset/loader/assetentry.c index 9e9ad477..9a86e6e6 100644 --- a/src/dusk/asset/loader/assetentry.c +++ b/src/dusk/asset/loader/assetentry.c @@ -35,22 +35,6 @@ void assetEntryInit( entry->input = NULL; } refInit(&entry->refs, entry, NULL, NULL, NULL); - - eventInit( - &entry->onLoaded, - entry->onLoadedCallbacks, entry->onLoadedUsers, - ASSET_ENTRY_EVENT_MAX - ); - eventInit( - &entry->onUnloaded, - entry->onUnloadedCallbacks, entry->onUnloadedUsers, - ASSET_ENTRY_EVENT_MAX - ); - eventInit( - &entry->onError, - entry->onErrorCallbacks, entry->onErrorUsers, - ASSET_ENTRY_EVENT_MAX - ); } void assetEntryLock(assetentry_t *entry) { @@ -97,7 +81,6 @@ errorret_t assetEntryDispose(assetentry_t *entry) { "Asset entry still refed at dispose time." ); - eventInvoke(&entry->onUnloaded, entry); errorChain(ASSET_LOADER_CALLBACKS[entry->type].dispose(entry)); memoryZero(entry, sizeof(assetentry_t)); errorOk(); diff --git a/src/dusk/asset/loader/assetentry.h b/src/dusk/asset/loader/assetentry.h index 94eff3fc..9f82b2c7 100644 --- a/src/dusk/asset/loader/assetentry.h +++ b/src/dusk/asset/loader/assetentry.h @@ -7,7 +7,6 @@ #pragma once #include "asset/loader/assetloading.h" -#include "event/event.h" #include "util/ref.h" typedef enum { @@ -20,9 +19,6 @@ typedef enum { ASSET_ENTRY_STATE_ERROR } assetentrystate_t; -/** Maximum number of subscribers for each per-entry event. */ -#define ASSET_ENTRY_EVENT_MAX 2 - typedef struct assetentry_s assetentry_t; struct assetentry_s { @@ -33,30 +29,6 @@ struct assetentry_s { ref_t refs; assetloaderinput_t *input; assetloaderinput_t inputData; - /** - * Fired once when loading completes successfully (params = assetentry_t *). - * Always invoked on the main thread. - */ - event_t onLoaded; - eventcallback_t onLoadedCallbacks[ASSET_ENTRY_EVENT_MAX]; - void *onLoadedUsers[ASSET_ENTRY_EVENT_MAX]; - - /** - * Fired once when the entry is disposed/reaped (params = assetentry_t *). - * The asset data is still accessible when the callback runs. - * Always invoked on the main thread. - */ - event_t onUnloaded; - eventcallback_t onUnloadedCallbacks[ASSET_ENTRY_EVENT_MAX]; - void *onUnloadedUsers[ASSET_ENTRY_EVENT_MAX]; - - /** - * Fired once when loading fails (params = assetentry_t *). - * Always invoked on the main thread. - */ - event_t onError; - eventcallback_t onErrorCallbacks[ASSET_ENTRY_EVENT_MAX]; - void *onErrorUsers[ASSET_ENTRY_EVENT_MAX]; }; /** @@ -104,7 +76,6 @@ void assetEntryStartLoading(assetentry_t *entry, assetloading_t *loading); /** * Disposes an asset entry, freeing any resources it holds. - * Fires the onUnloaded event before releasing asset data. * * @param entry The asset entry to dispose. * @return Any error that occurs during disposal. diff --git a/src/dusk/asset/loader/assetloader.c b/src/dusk/asset/loader/assetloader.c index ab1ba41b..6ce9494b 100644 --- a/src/dusk/asset/loader/assetloader.c +++ b/src/dusk/asset/loader/assetloader.c @@ -45,10 +45,4 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = { .loadAsync = assetJsonLoaderAsync, .dispose = assetJsonDispose }, - - [ASSET_LOADER_TYPE_CHUNK] = { - .loadSync = assetChunkLoaderSync, - .loadAsync = assetChunkLoaderAsync, - .dispose = assetChunkDispose - }, }; diff --git a/src/dusk/asset/loader/assetloader.h b/src/dusk/asset/loader/assetloader.h index a9edd1b1..5edae5ff 100644 --- a/src/dusk/asset/loader/assetloader.h +++ b/src/dusk/asset/loader/assetloader.h @@ -12,7 +12,6 @@ #include "asset/loader/display/assettilesetloader.h" #include "asset/loader/locale/assetlocaleloader.h" #include "asset/loader/json/assetjsonloader.h" -#include "asset/loader/chunk/assetchunkloader.h" typedef enum { ASSET_LOADER_TYPE_NULL, @@ -23,7 +22,6 @@ typedef enum { ASSET_LOADER_TYPE_TILESET, ASSET_LOADER_TYPE_LOCALE, ASSET_LOADER_TYPE_JSON, - ASSET_LOADER_TYPE_CHUNK, ASSET_LOADER_TYPE_COUNT } assetloadertype_t; @@ -35,7 +33,6 @@ typedef union { assettilesetloaderloading_t tileset; assetlocaleloaderloading_t locale; assetjsonloaderloading_t json; - assetchunkloaderloading_t chunk; } assetloaderloading_t; typedef union { @@ -45,7 +42,6 @@ typedef union { assettilesetoutput_t tileset; assetlocaleoutput_t locale; assetjsonoutput_t json; - assetchunkoutput_t chunk; } assetloaderoutput_t; typedef union { @@ -53,7 +49,6 @@ typedef union { assettilesetloaderinput_t tileset; assetlocaleloaderinput_t locale; assetjsonloaderinput_t json; - assetchunkloaderinput_t chunk; } assetloaderinput_t; typedef struct assetloading_s assetloading_t; diff --git a/src/dusk/asset/loader/chunk/CMakeLists.txt b/src/dusk/asset/loader/chunk/CMakeLists.txt deleted file mode 100644 index 64e16290..00000000 --- a/src/dusk/asset/loader/chunk/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - assetchunkloader.c -) diff --git a/src/dusk/asset/loader/chunk/assetchunkloader.c b/src/dusk/asset/loader/chunk/assetchunkloader.c deleted file mode 100644 index 4046ef12..00000000 --- a/src/dusk/asset/loader/chunk/assetchunkloader.c +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "assetchunkloader.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/endian.h" -#include "asset/loader/assetloading.h" -#include "asset/loader/assetentry.h" -#include "asset/loader/assetloader.h" -#include "asset/asset.h" - -errorret_t assetChunkLoaderAsync(assetloading_t *loading) { - assertNotNull(loading, "Loading cannot be NULL"); - assertNotMainThread("Should be called from an async thread."); - - if(loading->loading.chunk.state != ASSET_CHUNK_LOADING_STATE_READ_FILE) { - errorOk(); - } - - assertNull(loading->loading.chunk.data, "Data already defined?"); - - assetfile_t *file = &loading->loading.chunk.file; - assetLoaderErrorChain(loading, - assetFileInit(file, loading->entry->name, NULL, NULL) - ); - - uint8_t *data = memoryAllocate(file->size); - assetLoaderErrorChain(loading, assetFileOpen(file)); - assetLoaderErrorChain(loading, assetFileRead(file, data, file->size)); - assetLoaderErrorChain(loading, assetFileClose(file)); - assetLoaderErrorChain(loading, assetFileDispose(file)); - assertTrue( - file->lastRead == file->size, - "Failed to read entire chunk file." - ); - - loading->loading.chunk.data = data; - loading->loading.chunk.state = ASSET_CHUNK_LOADING_STATE_PARSE; - loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC; - errorOk(); -} - -errorret_t assetChunkLoaderSync(assetloading_t *loading) { - assertNotNull(loading, "Loading cannot be NULL"); - assertTrue(loading->type == ASSET_LOADER_TYPE_CHUNK, "Invalid type."); - assertIsMainThread("Must be called from the main thread."); - - assetchunkoutput_t *out = &loading->entry->data.chunk; - - switch(loading->loading.chunk.state) { - case ASSET_CHUNK_LOADING_STATE_INITIAL: - loading->loading.chunk.state = ASSET_CHUNK_LOADING_STATE_READ_FILE; - loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC; - errorOk(); - - case ASSET_CHUNK_LOADING_STATE_PARSE: - break; - - case ASSET_CHUNK_LOADING_STATE_LOAD_MODELS: - while(loading->loading.chunk.modelIndex < out->meshCount) { - uint8_t m = loading->loading.chunk.modelIndex; - if(out->modelEntries[m] == NULL) { - out->modelEntries[m] = assetLock( - out->modelNames[m], ASSET_LOADER_TYPE_MODEL, NULL - ); - assertNotNull( - out->modelEntries[m], "Failed to lock model." - ); - loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC; - errorOk(); - } - if(out->modelEntries[m]->state == ASSET_ENTRY_STATE_ERROR) { - assetLoaderErrorThrow( - loading, "Model failed to load: %s", out->modelNames[m] - ); - } - if(out->modelEntries[m]->state != ASSET_ENTRY_STATE_LOADED) { - loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC; - errorOk(); - } - loading->loading.chunk.modelIndex++; - } - loading->entry->state = ASSET_ENTRY_STATE_LOADED; - errorOk(); - - default: - errorOk(); - } - - uint8_t *data = loading->loading.chunk.data; - assertNotNull(data, "Chunk data should have been loaded by now."); - - if(data[0] != 'D' || data[1] != 'C' || data[2] != 'F') { - memoryFree(data); - assetLoaderErrorThrow(loading, "Invalid chunk file header"); - } - - uint32_t version = endianLittleToHost32(*(uint32_t *)(data + 4)); - if(version != ASSET_CHUNK_FILE_VERSION) { - memoryFree(data); - assetLoaderErrorThrow( - loading, "Unsupported chunk file version %u", version - ); - } - - size_t offset = 8; - - size_t tileSize = CHUNK_TILE_COUNT * sizeof(tile_t); - out->tiles = memoryAllocate(tileSize); - memoryCopy(out->tiles, data + offset, tileSize); - offset += tileSize; - - for(size_t t = 0; t < CHUNK_TILE_COUNT; t++) { - uint32_t *shape = (uint32_t *)&out->tiles[t].shape; - *shape = endianLittleToHost32(*shape); - } - - out->meshCount = data[offset]; - offset += sizeof(uint8_t); - assertTrue( - out->meshCount <= CHUNK_MESH_COUNT_MAX, - "Chunk mesh count exceeds maximum." - ); - - for(uint8_t m = 0; m < out->meshCount; m++) { - uint8_t nameLen = 0; - while( - data[offset + nameLen] != '\0' && - nameLen < CHUNK_MESH_NAME_MAX - 1 - ) { - nameLen++; - } - memoryCopy(out->modelNames[m], data + offset, nameLen); - out->modelNames[m][nameLen] = '\0'; - offset += nameLen + 1; - - memoryCopy(out->meshOffsets[m], data + offset, sizeof(vec3)); - offset += sizeof(vec3); - out->meshOffsets[m][0] = endianLittleToHostFloat(out->meshOffsets[m][0]); - out->meshOffsets[m][1] = endianLittleToHostFloat(out->meshOffsets[m][1]); - out->meshOffsets[m][2] = endianLittleToHostFloat(out->meshOffsets[m][2]); - } - - memoryFree(data); - loading->loading.chunk.data = NULL; - - if(out->meshCount == 0) { - loading->entry->state = ASSET_ENTRY_STATE_LOADED; - errorOk(); - } - - loading->loading.chunk.state = ASSET_CHUNK_LOADING_STATE_LOAD_MODELS; - loading->loading.chunk.modelIndex = 0; - loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC; - errorOk(); -} - -errorret_t assetChunkDispose(assetentry_t *entry) { - assertNotNull(entry, "Entry cannot be NULL"); - assertTrue(entry->type == ASSET_LOADER_TYPE_CHUNK, "Invalid type."); - assertIsMainThread("Must be called from the main thread."); - - assetchunkoutput_t *out = &entry->data.chunk; - - if(out->tiles != NULL) { - memoryFree(out->tiles); - out->tiles = NULL; - } - - for(uint8_t m = 0; m < out->meshCount; m++) { - if(out->modelEntries[m] == NULL) continue; - assetUnlockEntry(out->modelEntries[m]); - out->modelEntries[m] = NULL; - } - errorOk(); -} diff --git a/src/dusk/asset/loader/chunk/assetchunkloader.h b/src/dusk/asset/loader/chunk/assetchunkloader.h deleted file mode 100644 index db591a7f..00000000 --- a/src/dusk/asset/loader/chunk/assetchunkloader.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "asset/assetfile.h" -#include "rpg/overworld/chunk.h" - -#define ASSET_CHUNK_FILE_VERSION 4 - -typedef struct assetloading_s assetloading_t; -typedef struct assetentry_s assetentry_t; - -typedef struct { - void *nothing; -} assetchunkloaderinput_t; - -typedef enum { - ASSET_CHUNK_LOADING_STATE_INITIAL, - ASSET_CHUNK_LOADING_STATE_READ_FILE, - ASSET_CHUNK_LOADING_STATE_PARSE, - ASSET_CHUNK_LOADING_STATE_LOAD_MODELS, - ASSET_CHUNK_LOADING_STATE_DONE -} assetchunkloadingstate_t; - -typedef struct { - assetfile_t file; - assetchunkloadingstate_t state; - uint8_t *data; - uint8_t modelIndex; -} assetchunkloaderloading_t; - -typedef struct { - tile_t *tiles; - uint8_t meshCount; - char_t modelNames[CHUNK_MESH_COUNT_MAX][CHUNK_MESH_NAME_MAX]; - vec3 meshOffsets[CHUNK_MESH_COUNT_MAX]; - assetentry_t *modelEntries[CHUNK_MESH_COUNT_MAX]; -} assetchunkoutput_t; - -/** - * Asynchronous loader for chunk assets. Reads the raw DCF file bytes into - * the loading buffer so the sync phase can parse without blocking the - * main thread on I/O. - * - * @param loading Loading information for the asset being loaded. - * @return Error code indicating success or failure of the load operation. - */ -errorret_t assetChunkLoaderAsync(assetloading_t *loading); - -/** - * Synchronous loader for chunk assets. Validates the DCF binary previously - * read by the async phase and populates the output assetchunkoutput_t with - * tile data and model paths. - * - * @param loading Loading information for the asset being loaded. - * @return Error code indicating success or failure of the load operation. - */ -errorret_t assetChunkLoaderSync(assetloading_t *loading); - -/** - * Disposer for chunk assets. - * - * @param entry Asset entry containing the chunk data to dispose. - * @return Error code indicating success or failure of the dispose operation. - */ -errorret_t assetChunkDispose(assetentry_t *entry); diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index d969a7e6..d89f0357 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -10,7 +10,6 @@ #include "time/time.h" #include "input/input.h" #include "locale/localemanager.h" -#include "rpg/rpg.h" #include "display/display.h" #include "scene/scene.h" #include "asset/asset.h" @@ -19,7 +18,6 @@ #include "network/network.h" #include "system/system.h" #include "console/console.h" -#include "save/save.h" engine_t ENGINE; @@ -37,11 +35,9 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { errorChain(systemInit()); errorChain(inputInit()); errorChain(assetInit()); - // errorChain(saveInit()); errorChain(localeManagerInit()); errorChain(displayInit()); errorChain(uiInit()); - errorChain(rpgInit()); errorChain(networkInit()); errorChain(sceneInit()); @@ -53,9 +49,6 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { consolePrint("Assertions real"); #endif - sceneSet(SCENE_TYPE_OVERWORLD); - - errorOk(); } @@ -65,7 +58,6 @@ errorret_t engineUpdate(void) { timeUpdate(); inputUpdate(); consoleUpdate(); - errorChain(rpgUpdate()); errorChain(sceneUpdate()); errorChain(assetUpdate()); errorChain(uiUpdate()); @@ -83,12 +75,10 @@ void engineExit(void) { errorret_t engineDispose(void) { errorChain(sceneDispose()); errorChain(networkDispose()); - errorChain(rpgDispose()); localeManagerDispose(); errorChain(uiDispose()); consoleDispose(); errorChain(displayDispose()); - // errorChain(saveDispose()); errorChain(assetDispose()); errorOk(); diff --git a/src/dusk/event/CMakeLists.txt b/src/dusk/event/CMakeLists.txt deleted file mode 100644 index 69958ead..00000000 --- a/src/dusk/event/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - event.c -) diff --git a/src/dusk/event/event.c b/src/dusk/event/event.c deleted file mode 100644 index 1051fb51..00000000 --- a/src/dusk/event/event.c +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "event.h" -#include "assert/assert.h" -#include "util/memory.h" - -void eventInit( - event_t *event, - eventcallback_t *callbacks, - void **users, - size_t size -) { - assertNotNull(event, "event must not be NULL"); - assertNotNull((void *)callbacks, "callbacks must not be NULL"); - assertTrue(size > 0, "size must be greater than 0"); - - event->callbacks = callbacks; - event->users = users; - event->size = size; - event->count = 0; - memoryZero(callbacks, sizeof(eventcallback_t) * size); - if(users) memoryZero(users, sizeof(void *) * size); -} - -void eventSubscribe(event_t *event, eventcallback_t callback, void *user) { - assertNotNull(event, "event must not be NULL"); - assertNotNull(callback, "callback must not be NULL"); - - // Ensure callback isn't already susbcribed - for(uint32_t i = 0; i < event->count; i++) { - if(event->callbacks[i] != callback) continue; - assertUnreachable("Callback already registered, cannot subscribe twice."); - } - - assertTrue(event->count < event->size, "event subscriber capacity exceeded"); - - event->callbacks[event->count] = callback; - if(user) { - assertNotNull(event->users, "Cannot add user pointer."); - event->users[event->count] = user; - } - event->count++; -} - -void eventUnsubscribe(event_t *event, eventcallback_t callback) { - assertNotNull(event, "event must not be NULL"); - assertNotNull(callback, "callback must not be NULL"); - - for(uint32_t i = 0; i < event->count; i++) { - if(event->callbacks[i] != callback) continue; - - uint32_t last = event->count - 1; - if(i != last) { - event->callbacks[i] = event->callbacks[last]; - if(event->users) event->users[i] = event->users[last]; - } - event->callbacks[last] = NULL; - if(event->users) event->users[last] = NULL; - event->count--; - return; - } -} - -void eventInvoke(const event_t *event, void *params) { - assertNotNull(event, "event must not be NULL"); - - for(uint32_t i = 0; i < event->count; i++) { - void *u = event->users ? event->users[i] : NULL; - event->callbacks[i](params, u); - } -} diff --git a/src/dusk/event/event.h b/src/dusk/event/event.h deleted file mode 100644 index b94b3f59..00000000 --- a/src/dusk/event/event.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef void (*eventcallback_t)(void *params, void *user); - -typedef struct { - eventcallback_t *callbacks; - void **users; - size_t size; - uint32_t count; -} event_t; - -/** - * Initializes an event, binding it to the provided backing arrays and clearing - * all subscribers. May also be called to reset an event (re-clears subscribers - * without changing the backing arrays or size). - * - * @param event The event to initialize. - * @param callbacks Caller-owned array of at least `size` callback slots. - * @param users Array of user pointers, matching each callback, or NULL. - * @param size Capacity of both arrays, must match. - */ -void eventInit( - event_t *event, - eventcallback_t *callbacks, - void **users, - size_t size -); - -/** - * Subscribes a callback to an event. The callback is invoked with params and - * the provided user pointer each time the event fires. The same (callback, - * user) pair may only be subscribed once. - * - * @param event The event to subscribe to. - * @param callback The function to call when the event fires. - * @param user Arbitrary pointer forwarded to the callback unchanged. - */ -void eventSubscribe(event_t *event, eventcallback_t callback, void *user); - -/** - * Removes a previously subscribed (callback, user) pair. Does nothing if the - * pair is not currently subscribed. - * - * @param event The event to unsubscribe from. - * @param callback The callback that was passed to eventSubscribe. - */ -void eventUnsubscribe(event_t *event, eventcallback_t callback); - -/** - * Invokes all subscribed callbacks, passing params and each subscriber's user - * pointer. - * - * @param event The event to invoke. - * @param params Arbitrary pointer forwarded to every callback unchanged. - */ -void eventInvoke(const event_t *event, void *params); diff --git a/src/dusk/input/input.c b/src/dusk/input/input.c index 80a5d83d..421bec89 100644 --- a/src/dusk/input/input.c +++ b/src/dusk/input/input.c @@ -11,7 +11,6 @@ #include "util/string.h" #include "util/math.h" #include "time/time.h" -#include "event/event.h" input_t INPUT; @@ -23,20 +22,6 @@ errorret_t inputInit(void) { INPUT.actions[i].action = (inputaction_t)i; INPUT.actions[i].lastValue = 0.0f; INPUT.actions[i].currentValue = 0.0f; - - eventInit( - &INPUT.actions[i].onPressed, - INPUT.actions[i].onPressedCallbacks, - INPUT.actions[i].onPressedUsers, - INPUT_ACTION_CALLBACK_COUNT_MAX - ); - - eventInit( - &INPUT.actions[i].onReleased, - INPUT.actions[i].onReleasedCallbacks, - INPUT.actions[i].onReleasedUsers, - INPUT_ACTION_CALLBACK_COUNT_MAX - ); } #ifdef inputInitPlatform @@ -103,13 +88,6 @@ void inputUpdate(void) { if(TIME.dynamicUpdate) return; #endif - for(uint8_t i = INPUT_ACTION_NULL + 1; i < INPUT_ACTION_COUNT; i++) { - inputactiondata_t *act = &INPUT.actions[i]; - bool_t isDown = act->currentValue > 0.0f; - bool_t wasDown = act->lastValue > 0.0f; - if(isDown && !wasDown) eventInvoke(&act->onPressed, act); - if(!isDown && wasDown) eventInvoke(&act->onReleased, act); - } } float_t inputGetCurrentValue(const inputaction_t action) { diff --git a/src/dusk/input/inputaction.h b/src/dusk/input/inputaction.h index f094a42a..5398465f 100644 --- a/src/dusk/input/inputaction.h +++ b/src/dusk/input/inputaction.h @@ -8,9 +8,6 @@ #pragma once #include "time/time.h" #include "input/inputactiondefs.h" -#include "event/event.h" - -#define INPUT_ACTION_CALLBACK_COUNT_MAX 4 typedef struct { inputaction_t action; @@ -21,13 +18,6 @@ typedef struct { float_t lastDynamicValue; float_t currentDynamicValue; #endif - - eventcallback_t onPressedCallbacks[INPUT_ACTION_CALLBACK_COUNT_MAX]; - void *onPressedUsers[INPUT_ACTION_CALLBACK_COUNT_MAX]; - event_t onPressed; - eventcallback_t onReleasedCallbacks[INPUT_ACTION_CALLBACK_COUNT_MAX]; - void *onReleasedUsers[INPUT_ACTION_CALLBACK_COUNT_MAX]; - event_t onReleased; } inputactiondata_t; /** diff --git a/src/dusk/locale/localeinfo.h b/src/dusk/locale/localeinfo.h index 5f9d36ed..e42cb248 100644 --- a/src/dusk/locale/localeinfo.h +++ b/src/dusk/locale/localeinfo.h @@ -11,19 +11,23 @@ typedef struct { const char_t *name; const char_t *file; + bool_t available; } localeinfo_t; static const localeinfo_t LOCALE_EN_US = { .name = "en-US", .file = "locale/en_US.po", + .available = true, }; static const localeinfo_t LOCALE_JP_JP = { .name = "ja-JP", .file = "locale/jp_JP.po", + .available = false }; static const localeinfo_t LOCALE_ES_MX = { .name = "es-MX", .file = "locale/es_MX.po", + .available = false, }; \ No newline at end of file diff --git a/src/dusk/rpg/CMakeLists.txt b/src/dusk/rpg/CMakeLists.txt deleted file mode 100644 index 51db8064..00000000 --- a/src/dusk/rpg/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - rpg.c - rpgcamera.c -) - -# Subdirs -add_subdirectory(battle) -add_subdirectory(cutscene) -add_subdirectory(entity) -add_subdirectory(overworld) - -add_subdirectory(story) -add_subdirectory(item) \ No newline at end of file diff --git a/src/dusk/rpg/battle/CMakeLists.txt b/src/dusk/rpg/battle/CMakeLists.txt deleted file mode 100644 index 5b0a546c..00000000 --- a/src/dusk/rpg/battle/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - battle.c - battlefighter.c - party.c -) diff --git a/src/dusk/rpg/battle/battle.c b/src/dusk/rpg/battle/battle.c deleted file mode 100644 index cdba1b95..00000000 --- a/src/dusk/rpg/battle/battle.c +++ /dev/null @@ -1,223 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "battle.h" -#include "assert/assert.h" -#include "util/memory.h" - -battle_t BATTLE; - -void battleInit(void) { - memoryZero(&BATTLE, sizeof(battle_t)); - for(uint8_t i = 0; i < BATTLE_FIGHTER_COUNT_MAX; i++) { - BATTLE.fighters[i].id = i; - } -} - -uint8_t battleGetAvailableFighter(void) { - for(uint8_t i = 0; i < BATTLE_FIGHTER_COUNT_MAX; i++) { - if(BATTLE.fighters[i].status == BATTLE_FIGHTER_STATUS_NULL) return i; - } - - return 0xFF; -} - -battlefighter_t *battleAddFighter( - const battlefighterteam_t team, - const battlefightercontroller_t controller, - const battlefighterstats_t stats, - const uint16_t healthMax, - const uint16_t mpMax -) { - const uint8_t index = battleGetAvailableFighter(); - if(index == 0xFF) return NULL; - - battlefighter_t *fighter = &BATTLE.fighters[index]; - battleFighterInit(fighter, team, controller, stats, healthMax, mpMax); - return fighter; -} - -void battleStart( - const battleencountertype_t encounterType, - const bool_t fleeAvailable -) { - assertTrue(encounterType < BATTLE_ENCOUNTER_COUNT, "Invalid encounter type"); - - BATTLE.encounterType = encounterType; - BATTLE.fleeAvailable = fleeAvailable; - BATTLE.result = BATTLE_RESULT_NONE; - BATTLE.round = 1; - BATTLE.turnIndex = 0; - battleBuildTurnOrder(true); - - BATTLE.active = true; -} - -void battleDispose(void) { - battleInit(); -} - -battlefighter_t *battleGetCurrentFighter(void) { - if(!BATTLE.active) return NULL; - if(BATTLE.turnIndex >= BATTLE.turnCount) return NULL; - return &BATTLE.fighters[BATTLE.turnOrder[BATTLE.turnIndex]]; -} - -uint8_t battleGetAliveCount(const battlefighterteam_t team) { - uint8_t count = 0; - for(uint8_t i = 0; i < BATTLE_FIGHTER_COUNT_MAX; i++) { - if(BATTLE.fighters[i].team != team) continue; - if(!battleFighterIsAlive(&BATTLE.fighters[i])) continue; - count++; - } - return count; -} - -void battleResolveAttack( - battlefighter_t *attacker, - battlefighter_t *defender -) { - assertNotNull(attacker, "Attacker cannot be NULL"); - assertNotNull(defender, "Defender cannot be NULL"); - - const int32_t rawDamage = - (int32_t)attacker->stats.attack - (int32_t)defender->stats.defense; - const uint16_t damage = rawDamage > 0 ? (uint16_t)rawDamage : 1; - - defender->health = damage >= defender->health ? 0 : defender->health - damage; - if(defender->health == 0) defender->status = BATTLE_FIGHTER_STATUS_DEAD; -} - -void battleNextTurn(void) { - BATTLE.turnIndex++; - if(BATTLE.turnIndex < BATTLE.turnCount) return; - - BATTLE.round++; - BATTLE.turnIndex = 0; - battleBuildTurnOrder(false); -} - -battleresult_t battleCheckResult(void) { - if(BATTLE.result != BATTLE_RESULT_NONE) return BATTLE.result; - - if(battleGetAliveCount(BATTLE_FIGHTER_TEAM_ALLY) == 0) { - BATTLE.result = BATTLE_RESULT_LOSS; - } else if(battleGetAliveCount(BATTLE_FIGHTER_TEAM_ENEMY) == 0) { - BATTLE.result = BATTLE_RESULT_WIN; - } - - return BATTLE.result; -} - -void battlePlayerAttack(const uint8_t targetIndex) { - battlefighter_t *attacker = battleGetCurrentFighter(); - if(attacker == NULL) return; - if(attacker->controller != BATTLE_FIGHTER_CONTROLLER_PLAYER) return; - if(targetIndex >= BATTLE_FIGHTER_COUNT_MAX) return; - - battlefighter_t *defender = &BATTLE.fighters[targetIndex]; - if(!battleFighterIsAlive(defender)) return; - - battleResolveAttack(attacker, defender); - battleCheckResult(); - if(BATTLE.result == BATTLE_RESULT_NONE) battleNextTurn(); -} - -void battlePlayerFlee(void) { - battlefighter_t *fighter = battleGetCurrentFighter(); - if(fighter == NULL) return; - if(fighter->controller != BATTLE_FIGHTER_CONTROLLER_PLAYER) return; - if(!BATTLE.fleeAvailable) return; - - BATTLE.result = BATTLE_RESULT_FLED; -} - -void battleUpdate(void) { - if(!BATTLE.active) return; - if(BATTLE.result != BATTLE_RESULT_NONE) return; - - battlefighter_t *current = battleGetCurrentFighter(); - if(current == NULL) return; - - if(!battleFighterIsAlive(current)) { - battleNextTurn(); - return; - } - - if(current->controller != BATTLE_FIGHTER_CONTROLLER_AI) return; - - battlefighter_t *target = battleAIChooseTarget(current); - if(target != NULL) battleResolveAttack(current, target); - - battleCheckResult(); - if(BATTLE.result == BATTLE_RESULT_NONE) battleNextTurn(); -} - -void battleBuildTurnOrder(const bool_t applyEncounterBias) { - BATTLE.turnCount = 0; - for(uint8_t i = 0; i < BATTLE_FIGHTER_COUNT_MAX; i++) { - if(!battleFighterIsAlive(&BATTLE.fighters[i])) continue; - BATTLE.turnOrder[BATTLE.turnCount++] = i; - } - - // Insertion sort by speed descending -- fine for BATTLE_FIGHTER_COUNT_MAX. - for(uint8_t i = 1; i < BATTLE.turnCount; i++) { - const uint8_t key = BATTLE.turnOrder[i]; - const uint16_t keySpeed = BATTLE.fighters[key].stats.speed; - - int8_t j = (int8_t)i - 1; - while( - j >= 0 && BATTLE.fighters[BATTLE.turnOrder[j]].stats.speed < keySpeed - ) { - BATTLE.turnOrder[j + 1] = BATTLE.turnOrder[j]; - j--; - } - BATTLE.turnOrder[j + 1] = key; - } - - if(!applyEncounterBias) return; - - if(BATTLE.encounterType == BATTLE_ENCOUNTER_PLAYER_ADVANTAGE) { - battleMoveTeamFirst(BATTLE_FIGHTER_TEAM_ALLY); - } else if(BATTLE.encounterType == BATTLE_ENCOUNTER_BACK_ATTACK) { - battleMoveTeamFirst(BATTLE_FIGHTER_TEAM_ENEMY); - } -} - -void battleMoveTeamFirst(const battlefighterteam_t team) { - uint8_t sorted[BATTLE_FIGHTER_COUNT_MAX]; - uint8_t count = 0; - - for(uint8_t i = 0; i < BATTLE.turnCount; i++) { - if(BATTLE.fighters[BATTLE.turnOrder[i]].team != team) continue; - sorted[count++] = BATTLE.turnOrder[i]; - } - for(uint8_t i = 0; i < BATTLE.turnCount; i++) { - if(BATTLE.fighters[BATTLE.turnOrder[i]].team == team) continue; - sorted[count++] = BATTLE.turnOrder[i]; - } - - memoryCopy(BATTLE.turnOrder, sorted, sizeof(uint8_t) * BATTLE.turnCount); -} - -battlefighter_t *battleAIChooseTarget(const battlefighter_t *fighter) { - const battlefighterteam_t enemyTeam = - fighter->team == BATTLE_FIGHTER_TEAM_ALLY ? - BATTLE_FIGHTER_TEAM_ENEMY : BATTLE_FIGHTER_TEAM_ALLY; - - battlefighter_t *weakest = NULL; - for(uint8_t i = 0; i < BATTLE_FIGHTER_COUNT_MAX; i++) { - battlefighter_t *candidate = &BATTLE.fighters[i]; - if(candidate->team != enemyTeam) continue; - if(!battleFighterIsAlive(candidate)) continue; - if(weakest == NULL || candidate->health < weakest->health) { - weakest = candidate; - } - } - - return weakest; -} diff --git a/src/dusk/rpg/battle/battle.h b/src/dusk/rpg/battle/battle.h deleted file mode 100644 index 786a874e..00000000 --- a/src/dusk/rpg/battle/battle.h +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "battlefighter.h" - -#define BATTLE_FIGHTER_COUNT_MAX 8 - -typedef enum { - BATTLE_ENCOUNTER_REGULAR, - BATTLE_ENCOUNTER_PLAYER_ADVANTAGE, - BATTLE_ENCOUNTER_BACK_ATTACK, - - BATTLE_ENCOUNTER_COUNT -} battleencountertype_t; - -typedef enum { - BATTLE_RESULT_NONE, - BATTLE_RESULT_WIN, - BATTLE_RESULT_LOSS, - BATTLE_RESULT_FLED, - - BATTLE_RESULT_COUNT -} battleresult_t; - -typedef struct { - bool_t active; - battlefighter_t fighters[BATTLE_FIGHTER_COUNT_MAX]; - - battleencountertype_t encounterType; - bool_t fleeAvailable; - battleresult_t result; - - // Fighter indices (into fighters[]), sorted for the current round. - uint8_t turnOrder[BATTLE_FIGHTER_COUNT_MAX]; - uint8_t turnCount; - uint8_t turnIndex; - uint16_t round; -} battle_t; - -extern battle_t BATTLE; - -/** - * Initializes the battle system. Marks it as inactive with no fighters. - */ -void battleInit(void); - -/** - * Gets an available (unused) fighter slot index. - * - * @return The index of an available fighter slot, or 0xFF if none are - * available. - */ -uint8_t battleGetAvailableFighter(void); - -/** - * Adds a fighter to the battle in the next available slot. - * - * @param team The team the fighter belongs to. - * @param controller Who makes decisions for the fighter. - * @param stats The fighter's base combat stats. - * @param healthMax The fighter's maximum health. - * @param mpMax The fighter's maximum mp. - * @return Pointer to the newly added fighter, or NULL if the battle is - * already full. - */ -battlefighter_t *battleAddFighter( - const battlefighterteam_t team, - const battlefightercontroller_t controller, - const battlefighterstats_t stats, - const uint16_t healthMax, - const uint16_t mpMax -); - -/** - * Starts the battle: builds the opening turn order (biased by - * encounterType for the first round only) and marks the battle active. - * Call once every fighter has been added via battleAddFighter. - * - * @param encounterType Determines the opening round's turn order. - * @param fleeAvailable Whether the party may attempt to flee this battle. - */ -void battleStart( - const battleencountertype_t encounterType, - const bool_t fleeAvailable -); - -/** - * Disposes of the battle, clearing all fighters and marking it inactive. - */ -void battleDispose(void); - -/** - * Returns the fighter whose turn it currently is. - * - * @return Pointer to the active fighter, or NULL if the battle isn't - * active or has no living fighters left to act. - */ -battlefighter_t *battleGetCurrentFighter(void); - -/** - * Returns the number of living fighters on a team. - * - * @param team The team to count. - * @return Count of living fighters on that team. - */ -uint8_t battleGetAliveCount(const battlefighterteam_t team); - -/** - * Resolves a physical attack from attacker onto defender: damage is the - * attacker's attack stat minus the defender's defense stat (minimum 1), - * subtracted from the defender's health. The defender is marked dead - * once health reaches 0. - * - * @param attacker The attacking fighter. - * @param defender The defending fighter. - */ -void battleResolveAttack( - battlefighter_t *attacker, - battlefighter_t *defender -); - -/** - * Ends the current fighter's turn and advances to the next fighter in - * the turn order, starting a new round (rebuilding turn order purely by - * speed) once every fighter in the current round has acted. - */ -void battleNextTurn(void); - -/** - * Checks whether the battle has been won or lost, updating and - * returning BATTLE.result. Does nothing if a result has already been - * set (e.g. by a successful flee). - * - * @return The battle's current result. - */ -battleresult_t battleCheckResult(void); - -/** - * Submits the current fighter's attack against a target, if it is - * currently a player-controlled fighter's turn. Resolves the attack, - * checks for a battle result, and advances the turn. - * - * @param targetIndex Index into BATTLE.fighters of the target. - */ -void battlePlayerAttack(const uint8_t targetIndex); - -/** - * Submits a flee attempt for the current fighter's turn, if it is - * currently a player-controlled fighter's turn and fleeing is - * available for this battle. Always succeeds, ending the battle with - * BATTLE_RESULT_FLED. - */ -void battlePlayerFlee(void); - -/** - * Updates the battle simulation for one frame: resolves the current - * fighter's turn automatically if AI-controlled, otherwise waits for a - * player action via battlePlayerAttack/battlePlayerFlee. No-op if the - * battle isn't active or already has a result. - */ -void battleUpdate(void); - -/** - * Rebuilds BATTLE.turnOrder/turnCount from every currently living - * fighter, sorted by speed descending. - * - * @param applyEncounterBias If true, reorders the freshly speed-sorted - * queue so BATTLE.encounterType's favoured team goes first (used only - * for the opening round). - */ -void battleBuildTurnOrder(const bool_t applyEncounterBias); - -/** - * Stably partitions BATTLE.turnOrder so every fighter on the given team - * comes first, preserving each side's relative (speed-sorted) order. - * - * @param team The team to move to the front of the turn order. - */ -void battleMoveTeamFirst(const battlefighterteam_t team); - -/** - * Picks an AI target for fighter: the lowest-health living fighter on - * the opposing team. - * - * @param fighter The AI-controlled fighter choosing a target. - * @return The chosen target, or NULL if the opposing team has no - * living fighters. - */ -battlefighter_t *battleAIChooseTarget(const battlefighter_t *fighter); diff --git a/src/dusk/rpg/battle/battlefighter.c b/src/dusk/rpg/battle/battlefighter.c deleted file mode 100644 index 8d72d552..00000000 --- a/src/dusk/rpg/battle/battlefighter.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "battlefighter.h" -#include "assert/assert.h" -#include "util/memory.h" - -void battleFighterInit( - battlefighter_t *fighter, - const battlefighterteam_t team, - const battlefightercontroller_t controller, - const battlefighterstats_t stats, - const uint16_t healthMax, - const uint16_t mpMax -) { - assertNotNull(fighter, "Fighter pointer cannot be NULL"); - assertTrue(team < BATTLE_FIGHTER_TEAM_COUNT, "Invalid fighter team"); - assertTrue( - controller < BATTLE_FIGHTER_CONTROLLER_COUNT, - "Invalid fighter controller" - ); - - const uint8_t id = fighter->id; - memoryZero(fighter, sizeof(battlefighter_t)); - fighter->id = id; - fighter->status = BATTLE_FIGHTER_STATUS_NORMAL; - fighter->team = team; - fighter->controller = controller; - fighter->stats = stats; - fighter->healthMax = healthMax; - fighter->health = healthMax; - fighter->mpMax = mpMax; - fighter->mp = mpMax; -} - -bool_t battleFighterIsAlive(const battlefighter_t *fighter) { - assertNotNull(fighter, "Fighter pointer cannot be NULL"); - return fighter->status == BATTLE_FIGHTER_STATUS_NORMAL; -} diff --git a/src/dusk/rpg/battle/battlefighter.h b/src/dusk/rpg/battle/battlefighter.h deleted file mode 100644 index af032331..00000000 --- a/src/dusk/rpg/battle/battlefighter.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" - -// An empty status means the slot in BATTLE.fighters is unused. -typedef enum { - BATTLE_FIGHTER_STATUS_NULL, - - BATTLE_FIGHTER_STATUS_NORMAL, - BATTLE_FIGHTER_STATUS_DEAD, - - BATTLE_FIGHTER_STATUS_COUNT -} battlefighterstatus_t; - -typedef enum { - BATTLE_FIGHTER_TEAM_ALLY, - BATTLE_FIGHTER_TEAM_ENEMY, - - BATTLE_FIGHTER_TEAM_COUNT -} battlefighterteam_t; - -typedef enum { - BATTLE_FIGHTER_CONTROLLER_PLAYER, - BATTLE_FIGHTER_CONTROLLER_AI, - - BATTLE_FIGHTER_CONTROLLER_COUNT -} battlefightercontroller_t; - -// Base combat stats, kept separate from the resource pools (health/mp) on -// battlefighter_t so that equipment/buffs can later modify them without -// touching current health/mp state. -typedef struct { - uint16_t attack; - uint16_t defense; - uint16_t magic; - uint16_t speed; - uint16_t luck; -} battlefighterstats_t; - -typedef struct { - uint8_t id; - battlefighterstatus_t status; - battlefighterteam_t team; - battlefightercontroller_t controller; - - uint16_t health; - uint16_t healthMax; - uint16_t mp; - uint16_t mpMax; - - battlefighterstats_t stats; -} battlefighter_t; - -/** - * Initializes a battle fighter in place, filling health/mp to their maximum - * values and setting its status to normal. - * - * @param fighter Pointer to the fighter to initialize. - * @param team The team the fighter belongs to. - * @param controller Who makes decisions for the fighter. - * @param stats The fighter's base combat stats. - * @param healthMax The fighter's maximum health. - * @param mpMax The fighter's maximum mp. - */ -void battleFighterInit( - battlefighter_t *fighter, - const battlefighterteam_t team, - const battlefightercontroller_t controller, - const battlefighterstats_t stats, - const uint16_t healthMax, - const uint16_t mpMax -); - -/** - * Returns true if the fighter is in a state where it can still act (i.e. - * is not dead). - * - * @param fighter Pointer to the fighter to check. - * @returns True if the fighter can act. - */ -bool_t battleFighterIsAlive(const battlefighter_t *fighter); diff --git a/src/dusk/rpg/battle/party.c b/src/dusk/rpg/battle/party.c deleted file mode 100644 index 0350949d..00000000 --- a/src/dusk/rpg/battle/party.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "party.h" -#include "assert/assert.h" -#include "util/memory.h" - -party_t PARTY; - -void partyInit(void) { - memoryZero(&PARTY, sizeof(party_t)); - for(uint8_t i = 0; i < PARTY_MEMBER_COUNT_MAX; i++) { - PARTY.members[i].id = i; - } - for(uint8_t i = 0; i < PARTY_ACTIVE_SIZE_MAX; i++) { - PARTY.order[i] = PARTY_ORDER_EMPTY; - } -} - -uint8_t partyGetAvailableMember(void) { - for(uint8_t i = 0; i < PARTY_MEMBER_COUNT_MAX; i++) { - if(PARTY.members[i].status == BATTLE_FIGHTER_STATUS_NULL) return i; - } - - return 0xFF; -} - -battlefighter_t *partyAddMember( - const battlefighterstats_t stats, - const uint16_t healthMax, - const uint16_t mpMax -) { - const uint8_t index = partyGetAvailableMember(); - if(index == 0xFF) return NULL; - - battlefighter_t *member = &PARTY.members[index]; - battleFighterInit( - member, BATTLE_FIGHTER_TEAM_ALLY, BATTLE_FIGHTER_CONTROLLER_PLAYER, - stats, healthMax, mpMax - ); - - for(uint8_t i = 0; i < PARTY_ACTIVE_SIZE_MAX; i++) { - if(PARTY.order[i] != PARTY_ORDER_EMPTY) continue; - PARTY.order[i] = index; - break; - } - - return member; -} - -battlefighter_t *partyGetOrderMember(const uint8_t slot) { - assertTrue(slot < PARTY_ACTIVE_SIZE_MAX, "Invalid party order slot"); - - const uint8_t index = PARTY.order[slot]; - if(index == PARTY_ORDER_EMPTY) return NULL; - return &PARTY.members[index]; -} - -void partySetOrder(const uint8_t slot, const uint8_t memberIndex) { - assertTrue(slot < PARTY_ACTIVE_SIZE_MAX, "Invalid party order slot"); - assertTrue( - memberIndex == PARTY_ORDER_EMPTY || memberIndex < PARTY_MEMBER_COUNT_MAX, - "Invalid party member index" - ); - - PARTY.order[slot] = memberIndex; -} diff --git a/src/dusk/rpg/battle/party.h b/src/dusk/rpg/battle/party.h deleted file mode 100644 index 5f958169..00000000 --- a/src/dusk/rpg/battle/party.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "battlefighter.h" - -#define PARTY_MEMBER_COUNT_MAX 4 -#define PARTY_ACTIVE_SIZE_MAX 3 -#define PARTY_ORDER_EMPTY 0xFF - -typedef struct { - battlefighter_t members[PARTY_MEMBER_COUNT_MAX]; - - // Maps an active battle slot to the roster member filling it, or - // PARTY_ORDER_EMPTY if the slot is unfilled. Only the first - // PARTY_ACTIVE_SIZE_MAX of the PARTY_MEMBER_COUNT_MAX roster members - // can be in the active lineup at once. - uint8_t order[PARTY_ACTIVE_SIZE_MAX]; -} party_t; - -extern party_t PARTY; - -/** - * Initializes the party system with an empty roster and order. - */ -void partyInit(void); - -/** - * Gets an available (unused) party member slot index. - * - * @return The index of an available slot, or 0xFF if the party is full. - */ -uint8_t partyGetAvailableMember(void); - -/** - * Adds a member to the party roster in the next available slot. Party - * members are always allies controlled by the player. If there is a - * free active order slot, the new member is placed into it. - * - * @param stats The member's base combat stats. - * @param healthMax The member's maximum health. - * @param mpMax The member's maximum mp. - * @return Pointer to the newly added party member, or NULL if the party is - * already full. - */ -battlefighter_t *partyAddMember( - const battlefighterstats_t stats, - const uint16_t healthMax, - const uint16_t mpMax -); - -/** - * Gets the roster member currently occupying an active order slot. - * - * @param slot The active order slot to query. - * @return Pointer to the member in that slot, or NULL if the slot is - * empty. - */ -battlefighter_t *partyGetOrderMember(const uint8_t slot); - -/** - * Assigns a roster member to an active order slot, replacing whatever - * was there. Use PARTY_ORDER_EMPTY to clear a slot. - * - * @param slot The active order slot to assign. - * @param memberIndex The roster member index to place there, or - * PARTY_ORDER_EMPTY to clear the slot. - */ -void partySetOrder(const uint8_t slot, const uint8_t memberIndex); diff --git a/src/dusk/rpg/cutscene/CMakeLists.txt b/src/dusk/rpg/cutscene/CMakeLists.txt deleted file mode 100644 index ccecedc5..00000000 --- a/src/dusk/rpg/cutscene/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutscenesystem.c -) - -# Subdirs -add_subdirectory(item) \ No newline at end of file diff --git a/src/dusk/rpg/cutscene/cutscene.h b/src/dusk/rpg/cutscene/cutscene.h deleted file mode 100644 index f954455e..00000000 --- a/src/dusk/rpg/cutscene/cutscene.h +++ /dev/null @@ -1,232 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenepause.h" - -typedef struct cutscene_s { - const cutsceneitem_t *items; - uint8_t itemCount; - cutscenepause_t pause; - - // Size in bytes of this cutscene's custom user data, carved out of - // CUTSCENE_SYSTEM.data while the cutscene is running. - size_t dataSize; -} cutscene_t; - -#define CUTSCENE(NAME, SIZE, PAUSE_TYPE, ...) \ - static const cutsceneitem_t CUTSCENE_##NAME##_ITEMS[] = { __VA_ARGS__ }; \ - static const cutscene_t CUTSCENE_##NAME = { \ - .items = CUTSCENE_##NAME##_ITEMS, \ - .itemCount = sizeof(CUTSCENE_##NAME##_ITEMS) / sizeof(cutsceneitem_t), \ - .pause = CUTSCENE_PAUSE_##PAUSE_TYPE, \ - .dataSize = SIZE \ - }; - -#define CUTSCENE_REFERENCE(CUTSCENE) \ - &CUTSCENE_##CUTSCENE - -#define CUTSCENE_TEXT(TEXT) \ - { .type = CUTSCENE_ITEM_TYPE_TEXT, .text = { .text = TEXT } } - -#define CUTSCENE_TEXT_MINI(TEXT, X, Y, Z, DURATION) \ - { \ - .type = CUTSCENE_ITEM_TYPE_TEXT_MINI, \ - .textMini = { \ - .text = TEXT, \ - .position = { X, Y, Z }, \ - .duration = DURATION \ - } \ - } - -#define CUTSCENE_TEXT_MINI_HIDE(INDEX) \ - { \ - .type = CUTSCENE_ITEM_TYPE_TEXT_MINI_HIDE, \ - .textMiniHide = { .index = INDEX } \ - } - -#define CUTSCENE_WAIT(WAIT) \ - { .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = WAIT } - -#define CUTSCENE_CUTSCENE(CUTSCENE) \ - { \ - .type = CUTSCENE_ITEM_TYPE_CUTSCENE, \ - .cutscene = CUTSCENE_REFERENCE(CUTSCENE) \ - } - -#define CUTSCENE_CALLBACK(CALLBACK) \ - { .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = CALLBACK } - -#define CUTSCENE_ENTITY_WALK_TO(ENTITY_INDEX, X, Y, Z) \ - { \ - .type = CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO, \ - .entityWalkTo = { \ - .entityIndex = ENTITY_INDEX, \ - .positions = (const worldpos_t[]){ { X, Y, Z } }, \ - .count = 1, \ - .walkAround = true \ - } \ - } - -#define CUTSCENE_ENTITY_WALK_PATH(NAME, ENTITY_INDEX, ...) \ - static const worldpos_t CUTSCENE_##NAME##_POSITIONS[] = { __VA_ARGS__ }; \ - static const cutsceneitem_t CUTSCENE_##NAME = { \ - .type = CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO, \ - .entityWalkTo = { \ - .entityIndex = ENTITY_INDEX, \ - .positions = CUTSCENE_##NAME##_POSITIONS, \ - .count = sizeof(CUTSCENE_##NAME##_POSITIONS) / sizeof(worldpos_t), \ - .walkAround = true \ - } \ - } - -#define CUTSCENE_ENTITY_REMOVE(ENTITY_INDEX) \ - { \ - .type = CUTSCENE_ITEM_TYPE_ENTITY_REMOVE, \ - .entityRemove = { .entityIndex = ENTITY_INDEX } \ - } - -#define CUTSCENE_ENTITY_ADD(TYPE, X, Y, Z) \ - { \ - .type = CUTSCENE_ITEM_TYPE_ENTITY_ADD, \ - .entityAdd = { .entityType = TYPE, .position = { X, Y, Z } } \ - } - -#define CUTSCENE_ENTITY_TURN(ENTITY_INDEX, DIRECTION) \ - { \ - .type = CUTSCENE_ITEM_TYPE_ENTITY_TURN, \ - .entityTurn = { .entityIndex = ENTITY_INDEX, .direction = DIRECTION } \ - } - -// Walks ENTITY_INDEX to stand beside TARGET_ENTITY_INDEX, offset by -// (OFFSET_X, OFFSET_Y) on the 2D plane. The destination Z is resolved -// from nearby terrain each frame, so ramps between the two entities are -// accounted for automatically. -#define CUTSCENE_ENTITY_WALK_TO_ENTITY( \ - ENTITY_INDEX, TARGET_ENTITY_INDEX, OFFSET_X, OFFSET_Y \ -) \ - { \ - .type = CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO_ENTITY, \ - .entityWalkToEntity = { \ - .entityIndex = ENTITY_INDEX, \ - .targetEntityIndex = TARGET_ENTITY_INDEX, \ - .offsetX = OFFSET_X, \ - .offsetY = OFFSET_Y \ - } \ - } - -#define CUTSCENE_ENTITY_TELEPORT(ENTITY_INDEX, X, Y, Z) \ - { \ - .type = CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT, \ - .entityTeleport = { .entityIndex = ENTITY_INDEX, .target = { X, Y, Z } } \ - } - -#define CUTSCENE_FADE(FROM, TO, DURATION, EASING) \ - { \ - .type = CUTSCENE_ITEM_TYPE_FADE, \ - .fade = { .from = FROM, .to = TO, .duration = DURATION, .easing = EASING } \ - } - -#define CUTSCENE_FADE_TO_BLACK(DURATION) \ - CUTSCENE_FADE(COLOR_TRANSPARENT_BLACK, COLOR_BLACK, DURATION, EASING_LINEAR) - -#define CUTSCENE_FADE_FROM_BLACK(DURATION) \ - CUTSCENE_FADE(COLOR_BLACK, COLOR_TRANSPARENT_BLACK, DURATION, EASING_LINEAR) - -#define CUTSCENE_FADE_TO_WHITE(DURATION) \ - CUTSCENE_FADE(COLOR_TRANSPARENT_WHITE, COLOR_WHITE, DURATION, EASING_LINEAR) - -#define CUTSCENE_FADE_FROM_WHITE(DURATION) \ - CUTSCENE_FADE(COLOR_WHITE, COLOR_TRANSPARENT_WHITE, DURATION, EASING_LINEAR) - -#define CUTSCENE_EMOJI(ENTITY_INDEX, EMOJI_TYPE, DURATION) \ - { \ - .type = CUTSCENE_ITEM_TYPE_EMOJI, \ - .emoji = { \ - .entityIndex = ENTITY_INDEX, \ - .emojiType = EMOJI_TYPE, \ - .duration = DURATION \ - } \ - } - -// AMOUNT ranges 0 (no shake) to 4 (three tiles): 1 is half a tile, 2 is -// a full tile, 3 is two tiles, and 4 is three tiles. -#define CUTSCENE_SHAKE(AMOUNT, DURATION) \ - { \ - .type = CUTSCENE_ITEM_TYPE_SHAKE, \ - .shake = { .amount = AMOUNT, .duration = DURATION } \ - } - -#define CUTSCENE_SET_PAUSE(FLAGS) \ - { .type = CUTSCENE_ITEM_TYPE_SET_PAUSE, .setPause = (FLAGS) } - -#define CUTSCENE_ITEM_GIVE(ITEM_ID, QUANTITY) \ - { \ - .type = CUTSCENE_ITEM_TYPE_ITEM_GIVE, \ - .itemGive = { .item = ITEM_ID, .quantity = QUANTITY } \ - } - -// Runs all listed items simultaneously and waits until all are done. -// Concurrent items cannot be nested inside another CUTSCENE_CONCURRENT. -#define CUTSCENE_CONCURRENT(...) \ - { \ - .type = CUTSCENE_ITEM_TYPE_CONCURRENT, \ - .concurrent = { \ - .items = (const cutsceneitem_t[]){ __VA_ARGS__ }, \ - .count = (uint8_t)( \ - sizeof((cutsceneitem_t[]){ __VA_ARGS__ }) / \ - sizeof(cutsceneitem_t) \ - ) \ - } \ - } - -#define CUTSCENE_MAP_AREA_ADD( \ - MIN_X, MIN_Y, MIN_Z, MAX_X, MAX_Y, MAX_Z, CALLBACK, NOTIFY, TRIGGER \ -) \ - { \ - .type = CUTSCENE_ITEM_TYPE_MAP_AREA_ADD, \ - .mapAreaAdd = { \ - .min = { MIN_X, MIN_Y, MIN_Z }, \ - .max = { MAX_X, MAX_Y, MAX_Z }, \ - .callback = CALLBACK, \ - .notify = NOTIFY, \ - .trigger = TRIGGER \ - } \ - } - -#define CUTSCENE_MAP_AREA_REMOVE(AREA_ID) \ - { \ - .type = CUTSCENE_ITEM_TYPE_MAP_AREA_REMOVE, \ - .mapAreaRemove = { .areaId = AREA_ID } \ - } - -// Waits until any one of the given map area IDs has its callback invoked. -// Accepts CUTSCENE_AREA_LAST_CREATED in place of a literal area ID. -#define CUTSCENE_MAP_AREA_WAIT(...) \ - { \ - .type = CUTSCENE_ITEM_TYPE_MAP_AREA_WAIT, \ - .mapAreaWait = { \ - .areaIds = (const uint8_t[]){ __VA_ARGS__ }, \ - .count = (uint8_t)( \ - sizeof((const uint8_t[]){ __VA_ARGS__ }) / sizeof(uint8_t) \ - ) \ - } \ - } - -// Adds a map area, waits for it to be triggered once, then removes it -// before the cutscene continues. Uses a no-op callback since the wait is -// driven by the area's trigger count rather than callback logic. -#define CUTSCENE_MAP_AREA_TRIGGER_ONCE( \ - MIN_X, MIN_Y, MIN_Z, MAX_X, MAX_Y, MAX_Z, NOTIFY, TRIGGER \ -) \ - CUTSCENE_MAP_AREA_ADD( \ - MIN_X, MIN_Y, MIN_Z, MAX_X, MAX_Y, MAX_Z, \ - mapAreaNoopCallback, NOTIFY, TRIGGER \ - ), \ - CUTSCENE_MAP_AREA_WAIT(CUTSCENE_AREA_LAST_CREATED), \ - CUTSCENE_MAP_AREA_REMOVE(CUTSCENE_AREA_LAST_CREATED) diff --git a/src/dusk/rpg/cutscene/cutscenepause.h b/src/dusk/rpg/cutscene/cutscenepause.h deleted file mode 100644 index 222d28c0..00000000 --- a/src/dusk/rpg/cutscene/cutscenepause.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef uint8_t cutscenepause_t; - -#define CUTSCENE_PAUSE_NONE ((cutscenepause_t)0) -#define CUTSCENE_PAUSE_NPC ((cutscenepause_t)(1 << 0)) -#define CUTSCENE_PAUSE_PLAYER ((cutscenepause_t)(1 << 1)) -#define CUTSCENE_PAUSE_WORLD ((cutscenepause_t)(1 << 2)) - -#define CUTSCENE_PAUSE_DEFAULT ((cutscenepause_t)( \ - CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_PLAYER \ -)) - -#define CUTSCENE_PAUSE_ALL ((cutscenepause_t)( \ - CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_PLAYER | CUTSCENE_PAUSE_WORLD \ -)) diff --git a/src/dusk/rpg/cutscene/cutscenesystem.c b/src/dusk/rpg/cutscene/cutscenesystem.c deleted file mode 100644 index 933dbc0b..00000000 --- a/src/dusk/rpg/cutscene/cutscenesystem.c +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "cutscenesystem.h" -#include "rpg/entity/entity.h" -#include "util/memory.h" -#include "assert/assert.h" - -cutscenesystem_t CUTSCENE_SYSTEM; - -void cutsceneSystemInit() { - memoryZero(&CUTSCENE_SYSTEM, sizeof(cutscenesystem_t)); -} - -void cutsceneSystemStartCutscene(const cutscene_t *cutscene) { - cutsceneSystemStartCutsceneWith(cutscene, NULL, NULL); -} - -void cutsceneSystemStartCutsceneWith( - const cutscene_t *cutscene, - entity_t *interact, - entity_t *interacted -) { - assertTrue( - cutscene->dataSize < CUTSCENE_SYSTEM_SIZE_MAX, - "Cutscene data size exceeds CUTSCENE_SYSTEM_SIZE_MAX" - ); - - CUTSCENE_SYSTEM.scene = cutscene; - CUTSCENE_SYSTEM.pause = cutscene->pause; - CUTSCENE_SYSTEM.entityInteract = interact; - CUTSCENE_SYSTEM.entityInteracted = interacted; - CUTSCENE_SYSTEM.entityLastCreated = NULL; - CUTSCENE_SYSTEM.entityLastRef = NULL; - CUTSCENE_SYSTEM.areaLastCreated = CUTSCENE_AREA_LAST_CREATED; - CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED; - CUTSCENE_SYSTEM.currentItem = 0xFF;// Set to 0xFF so Next wraps to 0. - cutsceneSystemNext(); -} - -void cutsceneSystemUpdate() { - if(CUTSCENE_SYSTEM.scene == NULL) return; - - const cutsceneitem_t *item = cutsceneSystemGetCurrentItem(); - if(cutsceneItemUpdate(item, &CUTSCENE_SYSTEM.data)) cutsceneSystemNext(); -} - -void cutsceneSystemNext() { - if(CUTSCENE_SYSTEM.scene == NULL) return; - - CUTSCENE_SYSTEM.currentItem++; - - // End of the cutscene? - if( - CUTSCENE_SYSTEM.currentItem >= CUTSCENE_SYSTEM.scene->itemCount - ) { - CUTSCENE_SYSTEM.scene = NULL; - CUTSCENE_SYSTEM.currentItem = 0xFF; - CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE; - CUTSCENE_SYSTEM.entityInteract = NULL; - CUTSCENE_SYSTEM.entityInteracted = NULL; - CUTSCENE_SYSTEM.entityLastCreated = NULL; - CUTSCENE_SYSTEM.entityLastRef = NULL; - CUTSCENE_SYSTEM.areaLastCreated = CUTSCENE_AREA_LAST_CREATED; - CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED; - return; - } - - // Start item. - const cutsceneitem_t *item = cutsceneSystemGetCurrentItem(); - memset(&CUTSCENE_SYSTEM.data, 0, sizeof(CUTSCENE_SYSTEM.data)); - cutsceneItemStart(item, &CUTSCENE_SYSTEM.data); -} - -const cutsceneitem_t * cutsceneSystemGetCurrentItem() { - if(CUTSCENE_SYSTEM.scene == NULL) return NULL; - - return &CUTSCENE_SYSTEM.scene->items[CUTSCENE_SYSTEM.currentItem]; -} - -entity_t * cutsceneSystemGetEntity(const uint8_t entityIndex) { - entity_t *entity; - - if(entityIndex == CUTSCENE_ENTITY_INTERACT) { - assertNotNull( - CUTSCENE_SYSTEM.entityInteract, - "CUTSCENE_ENTITY_INTERACT used but no interact entity is set" - ); - entity = CUTSCENE_SYSTEM.entityInteract; - } else if(entityIndex == CUTSCENE_ENTITY_INTERACTED) { - assertNotNull( - CUTSCENE_SYSTEM.entityInteracted, - "CUTSCENE_ENTITY_INTERACTED used but no interacted entity is set" - ); - entity = CUTSCENE_SYSTEM.entityInteracted; - } else if(entityIndex == CUTSCENE_ENTITY_LAST_CREATED) { - assertNotNull( - CUTSCENE_SYSTEM.entityLastCreated, - "CUTSCENE_ENTITY_LAST_CREATED used but no entity has been created" - ); - entity = CUTSCENE_SYSTEM.entityLastCreated; - } else if(entityIndex == CUTSCENE_ENTITY_LAST_REF) { - assertNotNull( - CUTSCENE_SYSTEM.entityLastRef, - "CUTSCENE_ENTITY_LAST_REF used but no entity has been referenced" - ); - entity = CUTSCENE_SYSTEM.entityLastRef; - } else { - assertTrue( - entityIndex < ENTITY_COUNT, - "Entity index is out of range" - ); - entity = &ENTITIES[entityIndex]; - } - - CUTSCENE_SYSTEM.entityLastRef = entity; - return entity; -} - -uint8_t cutsceneSystemGetAreaId(const uint8_t areaId) { - if(areaId == CUTSCENE_AREA_LAST_CREATED) { - assertTrue( - CUTSCENE_SYSTEM.areaLastCreated != CUTSCENE_AREA_LAST_CREATED, - "CUTSCENE_AREA_LAST_CREATED used but no map area has been created" - ); - return CUTSCENE_SYSTEM.areaLastCreated; - } - return areaId; -} - -uint8_t cutsceneSystemGetTextMiniId(const uint8_t index) { - if(index == CUTSCENE_TEXT_MINI_LAST_CREATED) { - assertTrue( - CUTSCENE_SYSTEM.textMiniLastCreated != CUTSCENE_TEXT_MINI_LAST_CREATED, - "CUTSCENE_TEXT_MINI_LAST_CREATED used but no mini textbox has been " - "shown" - ); - return CUTSCENE_SYSTEM.textMiniLastCreated; - } - return index; -} - -void cutsceneSystemDispose() { - CUTSCENE_SYSTEM.scene = NULL; - CUTSCENE_SYSTEM.currentItem = 0xFF; - CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE; - CUTSCENE_SYSTEM.entityInteract = NULL; - CUTSCENE_SYSTEM.entityInteracted = NULL; - CUTSCENE_SYSTEM.entityLastCreated = NULL; - CUTSCENE_SYSTEM.entityLastRef = NULL; - CUTSCENE_SYSTEM.areaLastCreated = CUTSCENE_AREA_LAST_CREATED; - CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED; -} diff --git a/src/dusk/rpg/cutscene/cutscenesystem.h b/src/dusk/rpg/cutscene/cutscenesystem.h deleted file mode 100644 index 6f95a2a7..00000000 --- a/src/dusk/rpg/cutscene/cutscenesystem.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "cutscene.h" - -typedef struct entity_s entity_t; - -#define CUTSCENE_ENTITY_INTERACT ((uint8_t)0xFE) -#define CUTSCENE_ENTITY_INTERACTED ((uint8_t)0xFD) -#define CUTSCENE_ENTITY_LAST_CREATED ((uint8_t)0xFC) -#define CUTSCENE_ENTITY_LAST_REF ((uint8_t)0xFB) -#define CUTSCENE_AREA_LAST_CREATED ((uint8_t)0xFF) -#define CUTSCENE_TEXT_MINI_LAST_CREATED ((uint8_t)0xFA) - -// Maximum number of bytes a running cutscene may request via -// cutscene_t.dataSize. -#define CUTSCENE_SYSTEM_SIZE_MAX 8192 - -typedef struct { - const cutscene_t *scene; - uint8_t currentItem; - cutscenepause_t pause; - entity_t *entityInteract; - entity_t *entityInteracted; - entity_t *entityLastCreated; - entity_t *entityLastRef; - uint8_t areaLastCreated; - uint8_t textMiniLastCreated; - - // Data (used by the current item). - cutsceneitemdata_t data; - - // Custom user data for the running cutscene, sized per-scene by - // cutscene_t.dataSize. - uint8_t userData[CUTSCENE_SYSTEM_SIZE_MAX]; -} cutscenesystem_t; - -extern cutscenesystem_t CUTSCENE_SYSTEM; - -/** - * Initialize the cutscene system. - */ -void cutsceneSystemInit(); - -/** - * Start a cutscene with no bound entities. - * - * @param cutscene Pointer to the cutscene to start. - */ -void cutsceneSystemStartCutscene(const cutscene_t *cutscene); - -/** - * Start a cutscene with the two entities that triggered it. - * - * @param cutscene Pointer to the cutscene to start. - * @param interact The entity that initiated the interaction (player). - * @param interacted The entity that was interacted with (NPC). - */ -void cutsceneSystemStartCutsceneWith( - const cutscene_t *cutscene, - entity_t *interact, - entity_t *interacted -); - -/** - * Resolves a raw entity index (or sentinel) to an entity pointer. - * Handles CUTSCENE_ENTITY_INTERACT, CUTSCENE_ENTITY_INTERACTED, - * CUTSCENE_ENTITY_LAST_CREATED and CUTSCENE_ENTITY_LAST_REF. - * Updates CUTSCENE_SYSTEM.entityLastRef to the resolved entity. - * Asserts the resolved entity is within bounds. - * - * @param entityIndex Raw entity index or sentinel value. - * @returns Pointer to the resolved entity. - */ -entity_t * cutsceneSystemGetEntity(const uint8_t entityIndex); - -/** - * Resolves a raw map area ID (or CUTSCENE_AREA_LAST_CREATED sentinel) to - * a concrete map area ID. - * - * @param areaId Raw map area ID or sentinel value. - * @returns The resolved map area ID. - */ -uint8_t cutsceneSystemGetAreaId(const uint8_t areaId); - -/** - * Resolves a raw mini textbox slot index (or CUTSCENE_TEXT_MINI_LAST_CREATED - * sentinel) to a concrete UI_TEXTBOX_MINI_LIST slot index. - * - * @param index Raw slot index or sentinel value. - * @returns The resolved slot index. - */ -uint8_t cutsceneSystemGetTextMiniId(const uint8_t index); - -/** - * Advance to the next item in the cutscene. - */ -void cutsceneSystemNext(); - -/** - * Update the cutscene system for one frame. - */ -void cutsceneSystemUpdate(); - -/** - * Get the current cutscene item. - * - * @return Pointer to the current cutscene item. - */ -const cutsceneitem_t * cutsceneSystemGetCurrentItem(); - -/** - * Disposes of the cutscene system, stopping any active cutscene. - */ -void cutsceneSystemDispose(); \ No newline at end of file diff --git a/src/dusk/rpg/cutscene/item/CMakeLists.txt b/src/dusk/rpg/cutscene/item/CMakeLists.txt deleted file mode 100755 index 5a0f884f..00000000 --- a/src/dusk/rpg/cutscene/item/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutsceneitem.c - cutscenecallback.c -) - -add_subdirectory(control) -add_subdirectory(entity) -add_subdirectory(item) -add_subdirectory(maparea) -add_subdirectory(ui) -add_subdirectory(battle) diff --git a/src/dusk/rpg/cutscene/item/battle/CMakeLists.txt b/src/dusk/rpg/cutscene/item/battle/CMakeLists.txt deleted file mode 100644 index 8c48be10..00000000 --- a/src/dusk/rpg/cutscene/item/battle/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutscenestartbattle.c -) diff --git a/src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.c b/src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.c deleted file mode 100644 index 8d8aab55..00000000 --- a/src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/battle/party.h" -#include "scene/scene.h" - -void cutsceneStartBattleStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - const cutscenestartbattle_t *config = &item->startBattle; - - battleInit(); - - for(uint8_t i = 0; i < PARTY_ACTIVE_SIZE_MAX; i++) { - battlefighter_t *member = partyGetOrderMember(i); - if(member == NULL) continue; - - battlefighter_t *fighter = battleAddFighter( - BATTLE_FIGHTER_TEAM_ALLY, BATTLE_FIGHTER_CONTROLLER_PLAYER, - member->stats, member->healthMax, member->mpMax - ); - if(fighter == NULL) continue; - - fighter->health = member->health; - fighter->mp = member->mp; - fighter->status = member->status; - } - - for(uint8_t i = 0; i < config->enemyCount; i++) { - const cutscenestartbattleenemy_t *enemy = &config->enemies[i]; - battleAddFighter( - BATTLE_FIGHTER_TEAM_ENEMY, BATTLE_FIGHTER_CONTROLLER_AI, - enemy->stats, enemy->healthMax, enemy->mpMax - ); - } - - battleStart(config->encounterType, config->fleeAvailable); - sceneSet(SCENE_TYPE_BATTLE); -} - -bool_t cutsceneStartBattleUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - if(BATTLE.result == BATTLE_RESULT_NONE) return false; - - // Sync ally HP/MP back to the persistent party roster. Relies on - // ally fighters having been added to BATTLE.fighters in the same - // order partyGetOrderMember() iterates, starting at index 0 (see - // cutsceneStartBattleStart). - uint8_t allySlot = 0; - for(uint8_t i = 0; i < PARTY_ACTIVE_SIZE_MAX; i++) { - battlefighter_t *member = partyGetOrderMember(i); - if(member == NULL) continue; - - battlefighter_t *fighter = &BATTLE.fighters[allySlot++]; - member->health = fighter->health; - member->mp = fighter->mp; - member->status = fighter->status; - } - - sceneSet(SCENE_TYPE_OVERWORLD); - battleDispose(); - return true; -} diff --git a/src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.h b/src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.h deleted file mode 100644 index 770d1690..00000000 --- a/src/dusk/rpg/cutscene/item/battle/cutscenestartbattle.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/battle/battle.h" - -#define CUTSCENE_START_BATTLE_ENEMY_COUNT_MAX 4 - -typedef struct { - battlefighterstats_t stats; - uint16_t healthMax; - uint16_t mpMax; -} cutscenestartbattleenemy_t; - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - battleencountertype_t encounterType; - bool_t fleeAvailable; - uint8_t enemyCount; - cutscenestartbattleenemy_t enemies[CUTSCENE_START_BATTLE_ENEMY_COUNT_MAX]; -} cutscenestartbattle_t; - -/** - * Starts a battle: seeds BATTLE with the party's active order members - * and the item's configured enemies, then switches to the battle - * scene. - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneStartBattleStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Waits for the battle to produce a result, syncs ally HP/MP back to - * the party roster, then returns to the overworld scene. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once the battle has ended. - */ -bool_t cutsceneStartBattleUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/control/CMakeLists.txt b/src/dusk/rpg/cutscene/item/control/CMakeLists.txt deleted file mode 100644 index d0e492d6..00000000 --- a/src/dusk/rpg/cutscene/item/control/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutscenewait.c - cutscenesetpause.c - cutsceneconcurrent.c -) diff --git a/src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.c b/src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.c deleted file mode 100644 index 7145b383..00000000 --- a/src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.c +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "assert/assert.h" - -void cutsceneConcurrentStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - assertTrue( - item->concurrent.count <= CUTSCENE_CONCURRENT_MAX, - "Too many items in CUTSCENE_CONCURRENT" - ); - for(uint8_t i = 0; i < item->concurrent.count; i++) { - assertTrue( - item->concurrent.items[i].type != CUTSCENE_ITEM_TYPE_CONCURRENT, - "Concurrent items cannot be nested" - ); - cutsceneItemStart( - &item->concurrent.items[i], - (cutsceneitemdata_t *)&data->concurrent.childData[i] - ); - } -} - -bool_t cutsceneConcurrentUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - for(uint8_t i = 0; i < item->concurrent.count; i++) { - if(data->concurrent.doneMask & (1u << i)) continue; - if(cutsceneItemUpdate( - &item->concurrent.items[i], - (cutsceneitemdata_t *)&data->concurrent.childData[i] - )) { - data->concurrent.doneMask |= (uint8_t)(1u << i); - } - } - uint8_t allDone = (uint8_t)((1u << item->concurrent.count) - 1u); - return data->concurrent.doneMask == allDone; -} diff --git a/src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.h b/src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.h deleted file mode 100644 index c61b8d2e..00000000 --- a/src/dusk/rpg/cutscene/item/control/cutsceneconcurrent.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "cutscenewait.h" -#include "rpg/cutscene/item/entity/cutsceneentitywalkto.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -/** Maximum number of items that may run inside a CUTSCENE_CONCURRENT. */ -#define CUTSCENE_CONCURRENT_MAX 8 - -/** - * Static (const) data for a concurrent cutscene item. - */ -typedef struct { - const cutsceneitem_t *items; - uint8_t count; -} cutsceneconcurrent_t; - -/** - * Runtime data for one non-concurrent child item. - * Concurrent items cannot be nested. - */ -typedef union { - cutscenewaitdata_t wait; - cutsceneentitywalktodata_t entityWalkTo; -} cutsceneconcurrentchilddata_t; - -/** Runtime data for a running concurrent item. */ -typedef struct { - cutsceneconcurrentchilddata_t childData[CUTSCENE_CONCURRENT_MAX]; - uint8_t doneMask; -} cutsceneconcurrentdata_t; - -/** - * Starts a concurrent item (starts all child items simultaneously). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneConcurrentStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a concurrent item (ticks all unfinished children). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once every child has completed. - */ -bool_t cutsceneConcurrentUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/control/cutscenesetpause.c b/src/dusk/rpg/cutscene/item/control/cutscenesetpause.c deleted file mode 100644 index 1a22b47a..00000000 --- a/src/dusk/rpg/cutscene/item/control/cutscenesetpause.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" - -void cutsceneSetPauseStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - CUTSCENE_SYSTEM.pause = item->setPause; -} - -bool_t cutsceneSetPauseUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/control/cutscenesetpause.h b/src/dusk/rpg/cutscene/item/control/cutscenesetpause.h deleted file mode 100644 index bb04cf6a..00000000 --- a/src/dusk/rpg/cutscene/item/control/cutscenesetpause.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/cutscene/cutscenepause.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -/** - * Starts a set-pause item (applies the new pause flags immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneSetPauseStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a set-pause item (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneSetPauseUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/control/cutscenewait.c b/src/dusk/rpg/cutscene/item/control/cutscenewait.c deleted file mode 100644 index f85f1d2c..00000000 --- a/src/dusk/rpg/cutscene/item/control/cutscenewait.c +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "time/time.h" - -void cutsceneWaitStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - data->wait = item->wait; -} - -bool_t cutsceneWaitUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - data->wait -= TIME.delta; - return data->wait <= 0; -} diff --git a/src/dusk/rpg/cutscene/item/control/cutscenewait.h b/src/dusk/rpg/cutscene/item/control/cutscenewait.h deleted file mode 100644 index 985dca67..00000000 --- a/src/dusk/rpg/cutscene/item/control/cutscenewait.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef float_t cutscenewait_t; -typedef float_t cutscenewaitdata_t; - -/** - * Starts a wait item (stores the duration in data). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneWaitStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a wait item. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true when the wait has elapsed. - */ -bool_t cutsceneWaitUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); \ No newline at end of file diff --git a/src/dusk/rpg/cutscene/item/cutscenecallback.c b/src/dusk/rpg/cutscene/item/cutscenecallback.c deleted file mode 100644 index 29ee598f..00000000 --- a/src/dusk/rpg/cutscene/item/cutscenecallback.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" - -void cutsceneCallbackStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - if(item->callback != NULL) item->callback(CUTSCENE_SYSTEM.userData); -} - -bool_t cutsceneCallbackUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/cutscenecallback.h b/src/dusk/rpg/cutscene/item/cutscenecallback.h deleted file mode 100644 index ab65d68a..00000000 --- a/src/dusk/rpg/cutscene/item/cutscenecallback.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef void (*cutscenecallback_t)(void *userData); - -/** - * Starts a callback item (invokes the callback immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneCallbackStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a callback item (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneCallbackUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); \ No newline at end of file diff --git a/src/dusk/rpg/cutscene/item/cutsceneitem.c b/src/dusk/rpg/cutscene/item/cutsceneitem.c deleted file mode 100644 index 348de65f..00000000 --- a/src/dusk/rpg/cutscene/item/cutsceneitem.c +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/cutscenesystem.h" - -cutsceneitemcallbacks_t CUTSCENE_ITEM_CALLBACKS[CUTSCENE_ITEM_TYPE_COUNT] = { - [CUTSCENE_ITEM_TYPE_NULL] = { 0 }, - - [CUTSCENE_ITEM_TYPE_TEXT] = { - .init = cutsceneTextStart, - .update = cutsceneTextUpdate - }, - - [CUTSCENE_ITEM_TYPE_TEXT_MINI] = { - .init = cutsceneTextMiniStart, - .update = cutsceneTextMiniUpdate - }, - - [CUTSCENE_ITEM_TYPE_TEXT_MINI_HIDE] = { - .init = cutsceneTextMiniHideStart, - .update = cutsceneTextMiniHideUpdate - }, - - [CUTSCENE_ITEM_TYPE_CALLBACK] = { - .init = cutsceneCallbackStart, - .update = cutsceneCallbackUpdate - }, - - [CUTSCENE_ITEM_TYPE_WAIT] = { - .init = cutsceneWaitStart, - .update = cutsceneWaitUpdate - }, - - [CUTSCENE_ITEM_TYPE_CUTSCENE] = { - .init = cutsceneCutsceneStart, - .update = cutsceneCutsceneUpdate - }, - - [CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT] = { - .init = cutsceneEntityTeleportStart, - .update = cutsceneEntityTeleportUpdate - }, - - [CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO] = { - .init = cutsceneEntityWalkToStart, - .update = cutsceneEntityWalkToUpdate - }, - - [CUTSCENE_ITEM_TYPE_FADE] = { - .init = cutsceneFadeStart, - .update = cutsceneFadeUpdate - }, - - [CUTSCENE_ITEM_TYPE_SET_PAUSE] = { - .init = cutsceneSetPauseStart, - .update = cutsceneSetPauseUpdate - }, - - [CUTSCENE_ITEM_TYPE_CONCURRENT] = { - .init = cutsceneConcurrentStart, - .update = cutsceneConcurrentUpdate - }, - - [CUTSCENE_ITEM_TYPE_ITEM_GIVE] = { - .init = cutsceneItemGiveStart, - .update = cutsceneItemGiveUpdate - }, - - [CUTSCENE_ITEM_TYPE_ENTITY_REMOVE] = { - .init = cutsceneEntityRemoveStart, - .update = cutsceneEntityRemoveUpdate - }, - - [CUTSCENE_ITEM_TYPE_ENTITY_ADD] = { - .init = cutsceneEntityAddStart, - .update = cutsceneEntityAddUpdate - }, - - [CUTSCENE_ITEM_TYPE_ENTITY_TURN] = { - .init = cutsceneEntityTurnStart, - .update = cutsceneEntityTurnUpdate - }, - - [CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO_ENTITY] = { - .init = cutsceneEntityWalkToEntityStart, - .update = cutsceneEntityWalkToEntityUpdate - }, - - [CUTSCENE_ITEM_TYPE_MAP_AREA_ADD] = { - .init = cutsceneMapAreaAddStart, - .update = cutsceneMapAreaAddUpdate - }, - - [CUTSCENE_ITEM_TYPE_MAP_AREA_REMOVE] = { - .init = cutsceneMapAreaRemoveStart, - .update = cutsceneMapAreaRemoveUpdate - }, - - [CUTSCENE_ITEM_TYPE_MAP_AREA_WAIT] = { - .init = cutsceneMapAreaWaitStart, - .update = cutsceneMapAreaWaitUpdate - }, - - [CUTSCENE_ITEM_TYPE_START_BATTLE] = { - .init = cutsceneStartBattleStart, - .update = cutsceneStartBattleUpdate - }, - - [CUTSCENE_ITEM_TYPE_EMOJI] = { - .init = cutsceneEmojiStart, - .update = cutsceneEmojiUpdate - }, - - [CUTSCENE_ITEM_TYPE_SHAKE] = { - .init = cutsceneShakeStart, - .update = cutsceneShakeUpdate - } -}; - -void cutsceneItemStart(const cutsceneitem_t *item, cutsceneitemdata_t *data) { - cutsceneiteminitcallback_t *init = CUTSCENE_ITEM_CALLBACKS[item->type].init; - if(init != NULL) init(item, data); -} - -bool_t cutsceneItemUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - cutsceneitemupdatecallback_t *update = - CUTSCENE_ITEM_CALLBACKS[item->type].update; - if(update == NULL) return false; - - return update(item, data); -} - -void cutsceneCutsceneStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - if(item->cutscene != NULL) cutsceneSystemStartCutscene(item->cutscene); -} - -bool_t cutsceneCutsceneUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return false; -} diff --git a/src/dusk/rpg/cutscene/item/cutsceneitem.h b/src/dusk/rpg/cutscene/item/cutsceneitem.h deleted file mode 100644 index 46ee3be1..00000000 --- a/src/dusk/rpg/cutscene/item/cutsceneitem.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "cutscenecallback.h" -#include "control/cutscenewait.h" -#include "control/cutscenesetpause.h" -#include "control/cutsceneconcurrent.h" -#include "entity/cutsceneentityteleport.h" -#include "entity/cutsceneentitywalkto.h" -#include "entity/cutsceneentityremove.h" -#include "entity/cutsceneentityadd.h" -#include "entity/cutsceneentityturn.h" -#include "entity/cutsceneentitywalktoentity.h" -#include "ui/cutscenetext.h" -#include "ui/cutscenetextmini.h" -#include "ui/cutscenetextminihide.h" -#include "ui/cutscenefade.h" -#include "ui/cutsceneemoji.h" -#include "ui/cutsceneshake.h" -#include "item/cutsceneitemgive.h" -#include "maparea/cutscenemapareaadd.h" -#include "maparea/cutscenemaparearemove.h" -#include "maparea/cutscenemapareawait.h" -#include "battle/cutscenestartbattle.h" - -typedef struct cutscene_s cutscene_t; - -typedef enum { - CUTSCENE_ITEM_TYPE_NULL, - - CUTSCENE_ITEM_TYPE_TEXT, - CUTSCENE_ITEM_TYPE_TEXT_MINI, - CUTSCENE_ITEM_TYPE_TEXT_MINI_HIDE, - CUTSCENE_ITEM_TYPE_CALLBACK, - CUTSCENE_ITEM_TYPE_WAIT, - CUTSCENE_ITEM_TYPE_CUTSCENE, - CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT, - CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO, - CUTSCENE_ITEM_TYPE_FADE, - CUTSCENE_ITEM_TYPE_SET_PAUSE, - CUTSCENE_ITEM_TYPE_CONCURRENT, - CUTSCENE_ITEM_TYPE_ITEM_GIVE, - CUTSCENE_ITEM_TYPE_ENTITY_REMOVE, - CUTSCENE_ITEM_TYPE_ENTITY_ADD, - CUTSCENE_ITEM_TYPE_ENTITY_TURN, - CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO_ENTITY, - CUTSCENE_ITEM_TYPE_MAP_AREA_ADD, - CUTSCENE_ITEM_TYPE_MAP_AREA_REMOVE, - CUTSCENE_ITEM_TYPE_MAP_AREA_WAIT, - CUTSCENE_ITEM_TYPE_START_BATTLE, - CUTSCENE_ITEM_TYPE_EMOJI, - CUTSCENE_ITEM_TYPE_SHAKE, - - CUTSCENE_ITEM_TYPE_COUNT -} cutsceneitemtype_t; - -struct cutsceneitem_s { - cutsceneitemtype_t type; - - union { - cutscenetext_t text; - cutscenetextmini_t textMini; - cutscenetextminihide_t textMiniHide; - cutscenecallback_t callback; - cutscenewait_t wait; - const cutscene_t *cutscene; - cutsceneentityteleport_t entityTeleport; - cutsceneentitywalkto_t entityWalkTo; - cutscenefade_t fade; - cutscenepause_t setPause; - cutsceneconcurrent_t concurrent; - cutsceneitemgive_t itemGive; - cutsceneentityremove_t entityRemove; - cutsceneentityadd_t entityAdd; - cutsceneentityturn_t entityTurn; - cutsceneentitywalktoentity_t entityWalkToEntity; - cutscenemapareaadd_t mapAreaAdd; - cutscenemaparearemove_t mapAreaRemove; - cutscenemapareawait_t mapAreaWait; - cutscenestartbattle_t startBattle; - cutsceneemoji_t emoji; - cutsceneshake_t shake; - }; -}; - -typedef union cutsceneitemdata_u { - cutscenewaitdata_t wait; - cutsceneentitywalktodata_t entityWalkTo; - cutsceneconcurrentdata_t concurrent; - cutscenemapareawaitdata_t mapAreaWait; -} cutsceneitemdata_t; - -typedef void (cutsceneiteminitcallback_t)( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -typedef bool_t (cutsceneitemupdatecallback_t)( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -typedef struct { - cutsceneiteminitcallback_t *init; - cutsceneitemupdatecallback_t *update; -} cutsceneitemcallbacks_t; - -extern cutsceneitemcallbacks_t - CUTSCENE_ITEM_CALLBACKS[CUTSCENE_ITEM_TYPE_COUNT]; - -/** - * Start the given cutscene item. - * - * @param item The cutscene item to start. - * @param data Runtime data storage (pre-zeroed by caller). - */ -void cutsceneItemStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Tick the given cutscene item (one frame). - * - * @param item The cutscene item to tick. - * @param data Runtime data storage. - * @returns true if the item is complete and the cutscene should advance. - */ -bool_t cutsceneItemUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Starts a nested-cutscene item, handing control over to the - * referenced cutscene. - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneCutsceneStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a nested-cutscene item. By the time this would run, control - * has already moved on to the referenced cutscene, so this always - * reports incomplete. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns false always. - */ -bool_t cutsceneCutsceneUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/entity/CMakeLists.txt b/src/dusk/rpg/cutscene/item/entity/CMakeLists.txt deleted file mode 100644 index e6dfbd2d..00000000 --- a/src/dusk/rpg/cutscene/item/entity/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutsceneentityteleport.c - cutsceneentitywalkto.c - cutsceneentityremove.c - cutsceneentityadd.c - cutsceneentityturn.c - cutsceneentitywalktoentity.c -) diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.c b/src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.c deleted file mode 100644 index 0ab8c36e..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.c +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/entity/entity.h" -#include "assert/assert.h" - -void cutsceneEntityAddStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - uint8_t entIndex = entityGetAvailable(); - assertTrue(entIndex != 0xFF, "No available entity slots for CUTSCENE_ENTITY_ADD"); - - entity_t *entity = &ENTITIES[entIndex]; - entityInit(entity, item->entityAdd.entityType); - entityPositionSet(entity, item->entityAdd.position);// Also assigns chunk. - - CUTSCENE_SYSTEM.entityLastCreated = entity; - CUTSCENE_SYSTEM.entityLastRef = entity; -} - -bool_t cutsceneEntityAddUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.h b/src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.h deleted file mode 100644 index 5e0944b1..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityadd.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/entity/entitytype.h" -#include "rpg/overworld/worldpos.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - entitytype_t entityType; - worldpos_t position; -} cutsceneentityadd_t; - -/** - * Starts an entity add step (spawns the entity into the world immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneEntityAddStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates an entity add step (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneEntityAddUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.c b/src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.c deleted file mode 100644 index a358fb91..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.c +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/entity/entity.h" - -void cutsceneEntityRemoveStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - cutsceneSystemGetEntity(item->entityRemove.entityIndex)->type = \ - ENTITY_TYPE_NULL; -} - -bool_t cutsceneEntityRemoveUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.h b/src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.h deleted file mode 100644 index 2c7c4950..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityremove.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t entityIndex; -} cutsceneentityremove_t; - -/** - * Starts an entity remove step (removes the entity from the world immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneEntityRemoveStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates an entity remove step (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneEntityRemoveUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.c b/src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.c deleted file mode 100644 index 789e9e37..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.c +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/entity/entity.h" - -void cutsceneEntityTeleportStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - entityPositionSet( - cutsceneSystemGetEntity(item->entityTeleport.entityIndex), - item->entityTeleport.target - ); -} - -bool_t cutsceneEntityTeleportUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.h b/src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.h deleted file mode 100644 index 3237f89e..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityteleport.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/overworld/worldpos.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t entityIndex; - worldpos_t target; -} cutsceneentityteleport_t; - -/** - * Starts an entity teleport item (teleports the entity immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneEntityTeleportStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates an entity teleport item (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneEntityTeleportUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.c b/src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.c deleted file mode 100644 index 707389b4..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.c +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/entity/entity.h" - -void cutsceneEntityTurnStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { -} - -bool_t cutsceneEntityTurnUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - entity_t *entity = cutsceneSystemGetEntity(item->entityTurn.entityIndex); - if( - entity->direction == item->entityTurn.direction && - entity->animation == ENTITY_ANIM_IDLE - ) return true; - - entityTurn(entity, item->entityTurn.direction); - return false; -} diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.h b/src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.h deleted file mode 100644 index a14bb31b..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentityturn.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/entity/entitydir.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t entityIndex; - entitydir_t direction; -} cutsceneentityturn_t; - -/** - * Starts an entity turn step. The turn itself is driven from Update, since - * the entity may still be finishing a previous action. - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneEntityTurnStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates an entity turn step, retrying entityTurn until it takes effect - * and its animation completes. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once the entity is idle and facing the target direction. - */ -bool_t cutsceneEntityTurnUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.c b/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.c deleted file mode 100644 index d629df15..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/entity/entitypathstep.h" - -void cutsceneEntityWalkToStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - data->entityWalkTo.currentIndex = 0; -} - -bool_t cutsceneEntityWalkToUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - uint8_t i = data->entityWalkTo.currentIndex; - entity_t *e = cutsceneSystemGetEntity(item->entityWalkTo.entityIndex); - if(!entityPathStep( - e, - item->entityWalkTo.positions[i], - item->entityWalkTo.walkAround - )) return false; - i++; - if(i < item->entityWalkTo.count) { - data->entityWalkTo.currentIndex = i; - return false; - } - return true; -} diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.h b/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.h deleted file mode 100644 index ecf4677c..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalkto.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/overworld/worldpos.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t entityIndex; - const worldpos_t *positions; - uint8_t count; - bool_t walkAround; -} cutsceneentitywalkto_t; - -typedef struct { - uint8_t currentIndex; -} cutsceneentitywalktodata_t; - -/** - * Starts an entity walk-to item (resets the waypoint index). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneEntityWalkToStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates an entity walk-to item (steps the entity toward the next waypoint). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once all waypoints have been reached. - */ -bool_t cutsceneEntityWalkToUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.c b/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.c deleted file mode 100644 index 2b695545..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.c +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/entity/entity.h" -#include "rpg/entity/entitypathstep.h" -#include "rpg/overworld/map.h" - -void cutsceneEntityWalkToEntityStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { -} - -bool_t cutsceneEntityWalkToEntityUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - entity_t *entity = cutsceneSystemGetEntity( - item->entityWalkToEntity.entityIndex - ); - entity_t *target = cutsceneSystemGetEntity( - item->entityWalkToEntity.targetEntityIndex - ); - - worldpos_t dest = { - .x = (worldunit_t)(target->position.x + item->entityWalkToEntity.offsetX), - .y = (worldunit_t)(target->position.y + item->entityWalkToEntity.offsetY), - .z = target->position.z - }; - - worldunit_t z; - if(mapGetWalkableZNear(dest.x, dest.y, target->position.z, &z)) dest.z = z; - - return entityPathStep(entity, dest, true); -} diff --git a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.h b/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.h deleted file mode 100644 index 0014ed4b..00000000 --- a/src/dusk/rpg/cutscene/item/entity/cutsceneentitywalktoentity.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/overworld/worldpos.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t entityIndex; - uint8_t targetEntityIndex; - worldunit_t offsetX; - worldunit_t offsetY; -} cutsceneentitywalktoentity_t; - -/** - * Starts an entity walk-to-entity item. No setup is needed, the destination - * is recomputed from the target's live position every Update. - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneEntityWalkToEntityStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates an entity walk-to-entity item. Re-reads the target entity's - * current position each frame, applies the X/Y offset, resolves the - * destination Z from nearby terrain (to account for ramps), and steps - * the entity toward it. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once the entity has reached the target's side. - */ -bool_t cutsceneEntityWalkToEntityUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/item/CMakeLists.txt b/src/dusk/rpg/cutscene/item/item/CMakeLists.txt deleted file mode 100644 index df5ebc21..00000000 --- a/src/dusk/rpg/cutscene/item/item/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutsceneitemgive.c -) diff --git a/src/dusk/rpg/cutscene/item/item/cutsceneitemgive.c b/src/dusk/rpg/cutscene/item/item/cutsceneitemgive.c deleted file mode 100644 index 69c27136..00000000 --- a/src/dusk/rpg/cutscene/item/item/cutsceneitemgive.c +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/item/itemgive.h" -#include "ui/rpg/textbox/uitextboxmain.h" - -void cutsceneItemGiveStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - itemGive(item->itemGive.item, item->itemGive.quantity); -} - -bool_t cutsceneItemGiveUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return !uiTextboxMainIsActive(); -} diff --git a/src/dusk/rpg/cutscene/item/item/cutsceneitemgive.h b/src/dusk/rpg/cutscene/item/item/cutsceneitemgive.h deleted file mode 100644 index 12a53c01..00000000 --- a/src/dusk/rpg/cutscene/item/item/cutsceneitemgive.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/item/item.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - itemid_t item; - uint8_t quantity; -} cutsceneitemgive_t; - -/** - * Starts a give-item step (adds the item to the player's backpack immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneItemGiveStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a give-item step (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneItemGiveUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/maparea/CMakeLists.txt b/src/dusk/rpg/cutscene/item/maparea/CMakeLists.txt deleted file mode 100644 index cd32d7f6..00000000 --- a/src/dusk/rpg/cutscene/item/maparea/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutscenemapareaadd.c - cutscenemaparearemove.c - cutscenemapareawait.c -) diff --git a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.c b/src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.c deleted file mode 100644 index 7cbd2f19..00000000 --- a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.c +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" - -void cutsceneMapAreaAddStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - CUTSCENE_SYSTEM.areaLastCreated = mapAreaAdd( - item->mapAreaAdd.min, - item->mapAreaAdd.max, - item->mapAreaAdd.callback, - item->mapAreaAdd.notify, - item->mapAreaAdd.trigger - ); -} - -bool_t cutsceneMapAreaAddUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.h b/src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.h deleted file mode 100644 index b1614335..00000000 --- a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareaadd.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/overworld/maparea.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - worldpos_t min; - worldpos_t max; - mapareacallback_t callback; - uint8_t notify; - uint8_t trigger; -} cutscenemapareaadd_t; - -/** - * Starts a map area add step (adds the area immediately, storing its ID - * in CUTSCENE_SYSTEM.areaLastCreated). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneMapAreaAddStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a map area add step (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneMapAreaAddUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.c b/src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.c deleted file mode 100644 index 58045ba9..00000000 --- a/src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.c +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/overworld/maparea.h" - -void cutsceneMapAreaRemoveStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - mapAreaRemove(cutsceneSystemGetAreaId(item->mapAreaRemove.areaId)); -} - -bool_t cutsceneMapAreaRemoveUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.h b/src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.h deleted file mode 100644 index 3d1550dd..00000000 --- a/src/dusk/rpg/cutscene/item/maparea/cutscenemaparearemove.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t areaId; -} cutscenemaparearemove_t; - -/** - * Starts a map area remove step (removes the area immediately). Accepts - * CUTSCENE_AREA_LAST_CREATED in place of a literal area ID. - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneMapAreaRemoveStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a map area remove step (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneMapAreaRemoveUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.c b/src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.c deleted file mode 100644 index 7b0e3f2e..00000000 --- a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.c +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/overworld/maparea.h" -#include "assert/assert.h" - -void cutsceneMapAreaWaitStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - assertTrue( - item->mapAreaWait.count <= CUTSCENE_MAP_AREA_WAIT_MAX, - "Too many areas in CUTSCENE_MAP_AREA_WAIT" - ); - - for(uint8_t i = 0; i < item->mapAreaWait.count; i++) { - uint8_t areaId = cutsceneSystemGetAreaId(item->mapAreaWait.areaIds[i]); - data->mapAreaWait.baseline[i] = MAP_AREAS[areaId].triggerCount; - } -} - -bool_t cutsceneMapAreaWaitUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - for(uint8_t i = 0; i < item->mapAreaWait.count; i++) { - uint8_t areaId = cutsceneSystemGetAreaId(item->mapAreaWait.areaIds[i]); - if(MAP_AREAS[areaId].triggerCount != data->mapAreaWait.baseline[i]) { - return true; - } - } - - return false; -} diff --git a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.h b/src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.h deleted file mode 100644 index 039b4b76..00000000 --- a/src/dusk/rpg/cutscene/item/maparea/cutscenemapareawait.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -/** Maximum number of areas a single CUTSCENE_MAP_AREA_WAIT may watch. */ -#define CUTSCENE_MAP_AREA_WAIT_MAX 4 - -typedef struct { - const uint8_t *areaIds; - uint8_t count; -} cutscenemapareawait_t; - -typedef struct { - uint32_t baseline[CUTSCENE_MAP_AREA_WAIT_MAX]; -} cutscenemapareawaitdata_t; - -/** - * Starts a map area wait step, snapshotting each watched area's current - * trigger count. - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneMapAreaWaitStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a map area wait step, completing once any watched area's - * trigger count has changed since Start (i.e. its callback fired). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once any watched area has been triggered. - */ -bool_t cutsceneMapAreaWaitUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/ui/CMakeLists.txt b/src/dusk/rpg/cutscene/item/ui/CMakeLists.txt deleted file mode 100644 index 8f2e44fc..00000000 --- a/src/dusk/rpg/cutscene/item/ui/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - cutscenetext.c - cutscenetextmini.c - cutscenetextminihide.c - cutscenefade.c - cutsceneemoji.c - cutsceneshake.c -) diff --git a/src/dusk/rpg/cutscene/item/ui/cutsceneemoji.c b/src/dusk/rpg/cutscene/item/ui/cutsceneemoji.c deleted file mode 100644 index 2cd52bb7..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutsceneemoji.c +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/entity/entity.h" - -void cutsceneEmojiStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - entity_t *entity = cutsceneSystemGetEntity(item->emoji.entityIndex); - uiEmojiAdd(entity->id, item->emoji.duration, item->emoji.emojiType); -} - -bool_t cutsceneEmojiUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/ui/cutsceneemoji.h b/src/dusk/rpg/cutscene/item/ui/cutsceneemoji.h deleted file mode 100644 index 1c9deeca..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutsceneemoji.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "ui/rpg/uiemoji.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t entityIndex; - float_t duration; - uiemojitype_t emojiType; -} cutsceneemoji_t; - -/** - * Starts an emoji step (shows an emoji above the entity for the given - * duration, then completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneEmojiStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates an emoji step (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneEmojiUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenefade.c b/src/dusk/rpg/cutscene/item/ui/cutscenefade.c deleted file mode 100644 index 8ffa4656..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenefade.c +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "ui/overlay/uifullbox.h" - -void cutsceneFadeStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - uiFullboxTransition( - &UI_FULLBOX_OVER, - item->fade.from, - item->fade.to, - item->fade.duration, - item->fade.easing - ); -} - -bool_t cutsceneFadeUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return !( - UI_FULLBOX_OVER.duration > 0.0f && - UI_FULLBOX_OVER.time < UI_FULLBOX_OVER.duration - ); -} diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenefade.h b/src/dusk/rpg/cutscene/item/ui/cutscenefade.h deleted file mode 100644 index c23b12f9..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenefade.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "display/color.h" -#include "animation/easing.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - color_t from; - color_t to; - float_t duration; - easingtype_t easing; -} cutscenefade_t; - -/** - * Starts a fade item (begins the overlay transition). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneFadeStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a fade item. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once the overlay transition has completed. - */ -bool_t cutsceneFadeUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/ui/cutsceneshake.c b/src/dusk/rpg/cutscene/item/ui/cutsceneshake.c deleted file mode 100644 index eb1eca92..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutsceneshake.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/rpgcamera.h" - -void cutsceneShakeStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - rpgCameraShake(item->shake.amount, item->shake.duration); -} - -bool_t cutsceneShakeUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/ui/cutsceneshake.h b/src/dusk/rpg/cutscene/item/ui/cutsceneshake.h deleted file mode 100644 index cc0c0f24..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutsceneshake.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t amount; - float_t duration; -} cutsceneshake_t; - -/** - * Starts a camera shake item (kicks off the shake on the RPG camera). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneShakeStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a camera shake item. The shake itself runs asynchronously on - * the RPG camera, so this always completes immediately. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneShakeUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenetext.c b/src/dusk/rpg/cutscene/item/ui/cutscenetext.c deleted file mode 100644 index 9ad60c75..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenetext.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "ui/rpg/textbox/uitextboxmain.h" - -void cutsceneTextStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - uiTextboxMainSetText(item->text.text); -} - -bool_t cutsceneTextUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return !uiTextboxMainIsActive(); -} diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenetext.h b/src/dusk/rpg/cutscene/item/ui/cutscenetext.h deleted file mode 100644 index 61017806..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenetext.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -#define CUTSCENE_TEXT_MAX_CHARS 256 - -typedef struct { - char_t text[CUTSCENE_TEXT_MAX_CHARS]; -} cutscenetext_t; - -/** - * Starts a text item (shows the textbox with the item's text). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneTextStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a text item. - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true once the textbox has been dismissed. - */ -bool_t cutsceneTextUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); \ No newline at end of file diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenetextmini.c b/src/dusk/rpg/cutscene/item/ui/cutscenetextmini.c deleted file mode 100644 index f4d7f750..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenetextmini.c +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "ui/rpg/textbox/uitextboxminilist.h" - -void cutsceneTextMiniStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - uint8_t index = uiTextboxMiniListGetNext(); - uiTextboxMiniShow( - &UI_TEXTBOX_MINI_LIST[index], - item->textMini.text, - item->textMini.position, - item->textMini.duration, - NULL, - NULL - ); - CUTSCENE_SYSTEM.textMiniLastCreated = index; -} - -bool_t cutsceneTextMiniUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenetextmini.h b/src/dusk/rpg/cutscene/item/ui/cutscenetextmini.h deleted file mode 100644 index fb2628e7..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenetextmini.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -#define CUTSCENE_TEXT_MINI_MAX_CHARS 128 - -typedef struct { - char_t text[CUTSCENE_TEXT_MINI_MAX_CHARS]; - vec3 position; - float_t duration; -} cutscenetextmini_t; - -/** - * Starts a mini text item (shows a mini textbox at the given world - * position for the given duration, then completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneTextMiniStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a mini text item (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneTextMiniUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.c b/src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.c deleted file mode 100644 index c02da2be..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.c +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/cutscene/item/cutsceneitem.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "ui/rpg/textbox/uitextboxminilist.h" - -void cutsceneTextMiniHideStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - uint8_t index = cutsceneSystemGetTextMiniId(item->textMiniHide.index); - uiTextboxMiniClose(&UI_TEXTBOX_MINI_LIST[index]); -} - -bool_t cutsceneTextMiniHideUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -) { - return true; -} diff --git a/src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.h b/src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.h deleted file mode 100644 index 9dbd7f8e..00000000 --- a/src/dusk/rpg/cutscene/item/ui/cutscenetextminihide.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct cutsceneitem_s cutsceneitem_t; -typedef union cutsceneitemdata_u cutsceneitemdata_t; - -typedef struct { - uint8_t index; -} cutscenetextminihide_t; - -/** - * Starts a mini text hide step (closes the mini textbox immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - */ -void cutsceneTextMiniHideStart( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); - -/** - * Updates a mini text hide step (always completes immediately). - * - * @param item The cutscene item. - * @param data Runtime data storage. - * @returns true always. - */ -bool_t cutsceneTextMiniHideUpdate( - const cutsceneitem_t *item, - cutsceneitemdata_t *data -); diff --git a/src/dusk/rpg/cutscene/scene/testcutscene.h b/src/dusk/rpg/cutscene/scene/testcutscene.h deleted file mode 100755 index 10f7ba5f..00000000 --- a/src/dusk/rpg/cutscene/scene/testcutscene.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/cutscene/cutscene.h" -#include "rpg/cutscene/cutscenesystem.h" - -CUTSCENE(TEST_ONE, 0, DEFAULT, - CUTSCENE_TEXT("Test One."), -); - -CUTSCENE(TEST_TWO, 0, DEFAULT, - CUTSCENE_TEXT("Test Two."), - CUTSCENE_ENTITY_ADD(ENTITY_TYPE_NPC, 4, 4, 0), - CUTSCENE_TEXT_MINI("Hello!", 4, 4, 0, 3.0f), - CUTSCENE_EMOJI( - CUTSCENE_ENTITY_LAST_CREATED, UI_EMOJI_EXCLAMATION_MARK, 2.0f - ), - CUTSCENE_ENTITY_WALK_TO(CUTSCENE_ENTITY_LAST_CREATED, 8, 2, 0), - // CUTSCENE_CONCURRENT( - // CUTSCENE_ENTITY_WALK_TO(CUTSCENE_ENTITY_INTERACT, 4, 4, 0), - // CUTSCENE_ENTITY_WALK_TO(CUTSCENE_ENTITY_INTERACTED, 8, 2, 0), - // ), - // CUTSCENE_ITEM_GIVE(ITEM_ID_POTATO, 3), - // CUTSCENE_ENTITY_REMOVE(CUTSCENE_ENTITY_INTERACT), - CUTSCENE_TEXT("Done."), -); \ No newline at end of file diff --git a/src/dusk/rpg/entity/CMakeLists.txt b/src/dusk/rpg/entity/CMakeLists.txt deleted file mode 100644 index da55a228..00000000 --- a/src/dusk/rpg/entity/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - entity.c - entitydir.c - entitypathstep.c - player.c -) - -add_subdirectory(anim) -add_subdirectory(interact) -add_subdirectory(npc) -add_subdirectory(item) -add_subdirectory(global) \ No newline at end of file diff --git a/src/dusk/rpg/entity/anim/CMakeLists.txt b/src/dusk/rpg/entity/anim/CMakeLists.txt deleted file mode 100644 index 54c1015e..00000000 --- a/src/dusk/rpg/entity/anim/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - entityanim.c - entityanimidle.c - entityanimturn.c - entityanimwalk.c - entityanimrun.c -) diff --git a/src/dusk/rpg/entity/anim/entityanim.c b/src/dusk/rpg/entity/anim/entityanim.c deleted file mode 100644 index fa98628f..00000000 --- a/src/dusk/rpg/entity/anim/entityanim.c +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/entity/entity.h" -#include "rpg/overworld/map.h" -#include "rpg/overworld/tile.h" -#include "time/time.h" -#include "entityanimwalk.h" - -const entityanimcallback_t ENTITY_ANIM_CALLBACKS[ENTITY_ANIM_COUNT] = { - [ENTITY_ANIM_IDLE] = { entityAnimIdleUpdate }, - [ENTITY_ANIM_TURN] = { entityAnimTurnUpdate }, - [ENTITY_ANIM_WALK] = { entityAnimWalkUpdate }, - [ENTITY_ANIM_RUN] = { entityAnimRunUpdate }, -}; - -float_t entityAnimTileZOffset(const worldpos_t pos) { - return tileShapeIsRamp(mapGetTile(pos).shape) ? 0.5f : 0.0f; -} - -void entityAnimUpdate(entity_t *entity) { - if(entity->animation != ENTITY_ANIM_IDLE) { - entity->animTime -= TIME.delta; - if(entity->animTime <= 0) { - if( - entity->animation == ENTITY_ANIM_WALK || - entity->animation == ENTITY_ANIM_RUN - ) { - entity->walkEndCooldown = ENTITY_ANIM_WALK_TURN_COOLDOWN; - } - entity->animation = ENTITY_ANIM_IDLE; - entity->animTime = 0; - } - } - if(entity->walkEndCooldown > 0) { - entity->walkEndCooldown -= TIME.delta; - if(entity->walkEndCooldown < 0) entity->walkEndCooldown = 0; - } - ENTITY_ANIM_CALLBACKS[entity->animation].update(entity); -} diff --git a/src/dusk/rpg/entity/anim/entityanim.h b/src/dusk/rpg/entity/anim/entityanim.h deleted file mode 100644 index ff4cde20..00000000 --- a/src/dusk/rpg/entity/anim/entityanim.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "entityanimidle.h" -#include "entityanimturn.h" -#include "entityanimwalk.h" -#include "entityanimrun.h" - -typedef struct entity_s entity_t; - -typedef enum { - ENTITY_ANIM_IDLE, - ENTITY_ANIM_TURN, - ENTITY_ANIM_WALK, - ENTITY_ANIM_RUN, - ENTITY_ANIM_COUNT -} entityanim_t; - -typedef struct { - /** Updates the render position for this animation state. */ - void (*update)(entity_t *entity); -} entityanimcallback_t; - -extern const entityanimcallback_t ENTITY_ANIM_CALLBACKS[ENTITY_ANIM_COUNT]; - -/** - * Updates the entity animation timer and render position. - * - * @param entity Pointer to the entity to update. - */ -void entityAnimUpdate(entity_t *entity); - -/** - * Returns 0.5 if the tile at pos is a ramp, 0.0 otherwise. - * Used to lift entity render position to mid-ramp height. - * - * @param pos World position to sample. - * @returns float_t The Z offset to apply. - */ -float_t entityAnimTileZOffset(const worldpos_t pos); diff --git a/src/dusk/rpg/entity/anim/entityanimidle.c b/src/dusk/rpg/entity/anim/entityanimidle.c deleted file mode 100644 index fb9f5d4a..00000000 --- a/src/dusk/rpg/entity/anim/entityanimidle.c +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/entity/entity.h" -#include "entityanim.h" - -void entityAnimIdleUpdate(entity_t *entity) { - entity->renderPosition[0] = (float_t)entity->position.x; - entity->renderPosition[1] = (float_t)entity->position.y; - entity->renderPosition[2] = ( - (float_t)entity->position.z + entityAnimTileZOffset(entity->position) - ) * WORLD_LAYER_HEIGHT; -} diff --git a/src/dusk/rpg/entity/anim/entityanimidle.h b/src/dusk/rpg/entity/anim/entityanimidle.h deleted file mode 100644 index b7bd9a53..00000000 --- a/src/dusk/rpg/entity/anim/entityanimidle.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct entity_s entity_t; - -/** - * Updates render position for the idle animation state. - * - * @param entity Pointer to the entity to update. - */ -void entityAnimIdleUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/anim/entityanimrun.c b/src/dusk/rpg/entity/anim/entityanimrun.c deleted file mode 100644 index 27a32c2c..00000000 --- a/src/dusk/rpg/entity/anim/entityanimrun.c +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/entity/entity.h" -#include "entityanim.h" - -void entityAnimRunUpdate(entity_t *entity) { - float_t t = 1.0f - (entity->animTime / ENTITY_ANIM_RUN_DURATION); - float_t zFrom = (float_t)entity->lastPosition.z - + entityAnimTileZOffset(entity->lastPosition); - float_t zTo = (float_t)entity->position.z - + entityAnimTileZOffset(entity->position); - entity->renderPosition[0] = (float_t)entity->lastPosition.x + t * ( - (float_t)entity->position.x - (float_t)entity->lastPosition.x - ); - entity->renderPosition[1] = (float_t)entity->lastPosition.y + t * ( - (float_t)entity->position.y - (float_t)entity->lastPosition.y - ); - entity->renderPosition[2] = (zFrom + t * (zTo - zFrom)) * WORLD_LAYER_HEIGHT; -} diff --git a/src/dusk/rpg/entity/anim/entityanimrun.h b/src/dusk/rpg/entity/anim/entityanimrun.h deleted file mode 100644 index ecace434..00000000 --- a/src/dusk/rpg/entity/anim/entityanimrun.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "time/time.h" - -typedef struct entity_s entity_t; - -#define ENTITY_ANIM_RUN_DURATION TIME_TICKS_TO_TIME(6) - -/** - * Updates render position for the run animation state. - * - * @param entity Pointer to the entity to update. - */ -void entityAnimRunUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/anim/entityanimturn.c b/src/dusk/rpg/entity/anim/entityanimturn.c deleted file mode 100644 index d31ad814..00000000 --- a/src/dusk/rpg/entity/anim/entityanimturn.c +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/entity/entity.h" -#include "entityanim.h" - -void entityAnimTurnUpdate(entity_t *entity) { - entity->renderPosition[0] = (float_t)entity->position.x; - entity->renderPosition[1] = (float_t)entity->position.y; - entity->renderPosition[2] = ( - (float_t)entity->position.z + entityAnimTileZOffset(entity->position) - ) * WORLD_LAYER_HEIGHT; -} diff --git a/src/dusk/rpg/entity/anim/entityanimturn.h b/src/dusk/rpg/entity/anim/entityanimturn.h deleted file mode 100644 index 33368d52..00000000 --- a/src/dusk/rpg/entity/anim/entityanimturn.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "time/time.h" - -typedef struct entity_s entity_t; - -#define ENTITY_ANIM_TURN_DURATION TIME_TICKS_TO_TIME(4) - -/** - * Updates render position for the turn animation state. - * - * @param entity Pointer to the entity to update. - */ -void entityAnimTurnUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/anim/entityanimwalk.c b/src/dusk/rpg/entity/anim/entityanimwalk.c deleted file mode 100644 index e8aa2833..00000000 --- a/src/dusk/rpg/entity/anim/entityanimwalk.c +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/entity/entity.h" -#include "entityanim.h" - -void entityAnimWalkUpdate(entity_t *entity) { - float_t t = 1.0f - (entity->animTime / ENTITY_ANIM_WALK_DURATION); - float_t zFrom = (float_t)entity->lastPosition.z - + entityAnimTileZOffset(entity->lastPosition); - float_t zTo = (float_t)entity->position.z - + entityAnimTileZOffset(entity->position); - entity->renderPosition[0] = (float_t)entity->lastPosition.x + t * ( - (float_t)entity->position.x - (float_t)entity->lastPosition.x - ); - entity->renderPosition[1] = (float_t)entity->lastPosition.y + t * ( - (float_t)entity->position.y - (float_t)entity->lastPosition.y - ); - entity->renderPosition[2] = (zFrom + t * (zTo - zFrom)) * WORLD_LAYER_HEIGHT; -} diff --git a/src/dusk/rpg/entity/anim/entityanimwalk.h b/src/dusk/rpg/entity/anim/entityanimwalk.h deleted file mode 100644 index 5ab12585..00000000 --- a/src/dusk/rpg/entity/anim/entityanimwalk.h +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "time/time.h" - -typedef struct entity_s entity_t; - -#define ENTITY_ANIM_WALK_DURATION TIME_TICKS_TO_TIME(12) -#define ENTITY_ANIM_WALK_TURN_COOLDOWN TIME_TICKS_TO_TIME(4) - -/** - * Updates render position for the walk animation state. - * - * @param entity Pointer to the entity to update. - */ -void entityAnimWalkUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/entity.c b/src/dusk/rpg/entity/entity.c deleted file mode 100644 index 4b2b4a65..00000000 --- a/src/dusk/rpg/entity/entity.c +++ /dev/null @@ -1,316 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entity.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "time/time.h" -#include "util/math.h" -#include "rpg/overworld/map.h" -#include "rpg/overworld/maparea.h" -#include "rpg/overworld/chunk.h" -#include "rpg/overworld/tile.h" - -entity_t ENTITIES[ENTITY_COUNT]; - -void entityInit(entity_t *entity, const entitytype_t type) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - assertTrue(type < ENTITY_TYPE_COUNT, "Invalid entity type"); - assertTrue(type != ENTITY_TYPE_NULL, "Cannot have NULL entity type"); - assertTrue( - entity >= ENTITIES && entity < ENTITIES + ENTITY_COUNT, - "Entity pointer is out of bounds" - ); - - memoryZero(entity, sizeof(entity_t)); - entity->id = (uint8_t)(entity - ENTITIES); - entity->globalId = ENTITY_GLOBAL_ID_NULL; - entity->type = type; - entity->chunkIndex = 0xFF; - - if(ENTITY_CALLBACKS[type].init != NULL) ENTITY_CALLBACKS[type].init(entity); -} - -void entityUpdate(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type"); - assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL entity type"); - - // What state is the entity in? - entityAnimUpdate(entity); - - // Movement code. - if(ENTITY_CALLBACKS[entity->type].movement != NULL) { - ENTITY_CALLBACKS[entity->type].movement(entity); - } -} - -bool_t entityCanTurn(entity_t *entity) { - return entity->animation == ENTITY_ANIM_IDLE && - entity->walkEndCooldown <= 0; -} - -bool_t entityCanWalk(entity_t *entity) { - return entity->animation == ENTITY_ANIM_IDLE; -} - -bool_t entityCanRun(entity_t *entity) { - return entity->animation == ENTITY_ANIM_IDLE; -} - -bool_t entityCanUnload(entity_t *entity) { - return entity->globalId < ENTITY_GLOBAL_ID_START; -} - -void entityTurn(entity_t *entity, const entitydir_t direction) { - if(!entityCanTurn(entity)) return; - entity->direction = direction; - entity->animation = ENTITY_ANIM_TURN; - entity->animTime = ENTITY_ANIM_TURN_DURATION; -} - -void entityWalk(entity_t *entity, const entitydir_t direction) { - if(!entityCanWalk(entity)) return; - // TODO: Animation, delay, etc. - entity->direction = direction; - - // Where are we moving? - worldpos_t newPos = entity->position; - worldunits_t relX, relY; - { - entityDirGetRelative(direction, &relX, &relY); - newPos.x += relX; - newPos.y += relY; - } - - // Get tile under foot - tile_t tileCurrent = mapGetTile(entity->position); - tile_t tileNew = mapGetTile(newPos); - bool_t fall = false; - bool_t raise = false; - - // Are we walking up a ramp? - if( - tileShapeIsRamp(tileCurrent.shape) && - ( - // Can only walk UP the direction the ramp faces. - (direction+TILE_SHAPE_RAMP_NORTH) == tileCurrent.shape || - // If diagonal ramp, can go up one of two ways only. Inner ramps - // share the same allowed directions as their outer counterparts. - ( - ( - ( - tileCurrent.shape == TILE_SHAPE_RAMP_SOUTHEAST || - tileCurrent.shape == TILE_SHAPE_RAMP_SOUTHEAST_INNER - ) && - (direction == ENTITY_DIR_SOUTH || direction == ENTITY_DIR_EAST) - ) || - ( - ( - tileCurrent.shape == TILE_SHAPE_RAMP_SOUTHWEST || - tileCurrent.shape == TILE_SHAPE_RAMP_SOUTHWEST_INNER - ) && - (direction == ENTITY_DIR_SOUTH || direction == ENTITY_DIR_WEST) - ) || - ( - ( - tileCurrent.shape == TILE_SHAPE_RAMP_NORTHEAST || - tileCurrent.shape == TILE_SHAPE_RAMP_NORTHEAST_INNER - ) && - (direction == ENTITY_DIR_NORTH || direction == ENTITY_DIR_EAST) - ) || - ( - ( - tileCurrent.shape == TILE_SHAPE_RAMP_NORTHWEST || - tileCurrent.shape == TILE_SHAPE_RAMP_NORTHWEST_INNER - ) && - (direction == ENTITY_DIR_NORTH || direction == ENTITY_DIR_WEST) - ) - ) - // Must be able to walk up. - ) - ) { - tile_t tileNewSaved = tileNew; - tileNew = TILE_NULL; - worldpos_t abovePos = newPos; - abovePos.z += 1; - tile_t tileAbove = mapGetTile(abovePos); - - if( - tileAbove.shape != TILE_SHAPE_NULL && - tileShapeIsWalkable(tileAbove.shape) - ) { - raise = true; - } else { - tileNew = tileNewSaved; - } - } else if(tileNew.shape == TILE_SHAPE_NULL && newPos.z > 0) { - // Falling down? - worldpos_t belowPos = newPos; - belowPos.z -= 1; - tile_t tileBelow = mapGetTile(belowPos); - if( - tileBelow.shape != TILE_SHAPE_NULL && - tileShapeIsRamp(tileBelow.shape) && - ( - // This handles regular cardinal ramps - ( - entityDirGetOpposite(direction)+TILE_SHAPE_RAMP_NORTH - ) == tileBelow.shape || - // This handles diagonal ramps. Inner ramps share the same - // allowed directions as their outer counterparts. - ( - ( - ( - tileBelow.shape == TILE_SHAPE_RAMP_SOUTHEAST || - tileBelow.shape == TILE_SHAPE_RAMP_SOUTHEAST_INNER - ) && - (direction == ENTITY_DIR_NORTH || direction == ENTITY_DIR_WEST) - ) || - ( - ( - tileBelow.shape == TILE_SHAPE_RAMP_SOUTHWEST || - tileBelow.shape == TILE_SHAPE_RAMP_SOUTHWEST_INNER - ) && - (direction == ENTITY_DIR_NORTH || direction == ENTITY_DIR_EAST) - ) || - ( - ( - tileBelow.shape == TILE_SHAPE_RAMP_NORTHEAST || - tileBelow.shape == TILE_SHAPE_RAMP_NORTHEAST_INNER - ) && - (direction == ENTITY_DIR_SOUTH || direction == ENTITY_DIR_WEST) - ) || - ( - ( - tileBelow.shape == TILE_SHAPE_RAMP_NORTHWEST || - tileBelow.shape == TILE_SHAPE_RAMP_NORTHWEST_INNER - ) && - (direction == ENTITY_DIR_SOUTH || direction == ENTITY_DIR_EAST) - ) - ) - ) - ) { - // We will fall to this tile. - fall = true; - } - } - - // Can we walk here? - if(!raise && !fall && !tileShapeIsWalkable(tileNew.shape)) return;// Blocked - - // Raise/fall must be applied before checking for blocking entities, - // otherwise the check compares against the wrong z-level. - if(raise) { - newPos.z += 1; - } else if(fall) { - newPos.z -= 1; - } - - // Entity in way? - entity_t *other = ENTITIES; - do { - if(other == entity) continue; - if(other->type == ENTITY_TYPE_NULL) continue; - if(!worldPosIsEqual(other->position, newPos)) continue; - return;// Blocked - } while(++other, other < &ENTITIES[ENTITY_COUNT]); - - entity->lastPosition = entity->position; - entity->position = newPos; - entity->animation = ENTITY_ANIM_WALK; - entity->animTime = ENTITY_ANIM_WALK_DURATION;// TODO: Running vs walking - entityUpdateChunk(entity); - mapAreaCheckEntity(entity); -} - -void entityRun(entity_t *entity, const entitydir_t direction) { - if(!entityCanRun(entity)) return; - entityWalk(entity, direction); - if(entity->animation == ENTITY_ANIM_WALK) { - entity->animation = ENTITY_ANIM_RUN; - entity->animTime = ENTITY_ANIM_RUN_DURATION; - } -} - -entity_t * entityGetAt(const worldpos_t position) { - entity_t *ent = ENTITIES; - do { - if(ent->type == ENTITY_TYPE_NULL) continue; - if(!worldPosIsEqual(ent->position, position)) continue; - return ent; - } while(++ent, ent < &ENTITIES[ENTITY_COUNT]); - - return NULL; -} - -entity_t * entityGetByGlobalId(const entityglobalid_t globalId) { - entity_t *ent = ENTITIES; - do { - if(ent->type == ENTITY_TYPE_NULL) continue; - if(ent->globalId != globalId) continue; - return ent; - } while(++ent, ent < &ENTITIES[ENTITY_COUNT]); - - return NULL; -} - -uint8_t entityGetAvailable() { - entity_t *ent = ENTITIES; - do { - if(ent->type == ENTITY_TYPE_NULL) return ent - ENTITIES; - } while(++ent, ent < &ENTITIES[ENTITY_COUNT]); - - return 0xFF; -} - -void entityPositionSet(entity_t *entity, const worldpos_t pos) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - entity->lastPosition = pos; - entity->position = pos; - entity->animation = ENTITY_ANIM_IDLE; - entity->animTime = 0; - entity->walkEndCooldown = 0; - entityUpdateChunk(entity); -} - -void entitySetChunk(entity_t *entity, const uint8_t chunkIndex) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - - if(entity->chunkIndex != 0xFF) { - chunk_t *old = mapGetChunk(entity->chunkIndex); - if(old != NULL) { - for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { - if(old->entities[i] != entity->id) continue; - old->entities[i] = 0xFF; - break; - } - } - } - - entity->chunkIndex = chunkIndex; - - if(chunkIndex != 0xFF) { - chunk_t *next = mapGetChunk(chunkIndex); - if(next != NULL) { - for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { - if(next->entities[i] != 0xFF) continue; - next->entities[i] = entity->id; - break; - } - } - } -} - -void entityUpdateChunk(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - - chunkpos_t cp; - worldPosToChunkPos(&entity->position, &cp); - chunkindex_t ci = mapGetChunkIndexAt(cp); - if(ci != -1) entitySetChunk(entity, (uint8_t)ci); -} \ No newline at end of file diff --git a/src/dusk/rpg/entity/entity.h b/src/dusk/rpg/entity/entity.h deleted file mode 100644 index e184b3b3..00000000 --- a/src/dusk/rpg/entity/entity.h +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "entitydir.h" -#include "anim/entityanim.h" -#include "interact/entityinteract.h" -#include "entitytype.h" -#include "npc/npc.h" - -typedef struct map_s map_t; - -typedef uint16_t entityglobalid_t; - -#define ENTITY_GLOBAL_ID_NULL 0 -#define ENTITY_GLOBAL_ID_START 1 -#define ENTITY_GLOBAL_ID_PLAYER 1 - -typedef struct entity_s { - uint8_t id; - entityglobalid_t globalId; - entitytype_t type; - entitytypedata_t data; - - // Movement - entitydir_t direction; - worldpos_t position; - worldpos_t lastPosition; - vec3 renderPosition; - - entityanim_t animation; - float_t animTime; - float_t walkEndCooldown; - - entityinteract_t interact; - - uint8_t chunkIndex; -} entity_t; - -extern entity_t ENTITIES[ENTITY_COUNT]; - -/** - * Initializes an entity structure. - * - * @param entity Pointer to the entity structure to initialize. - * @param type The type of the entity. - */ -void entityInit(entity_t *entity, const entitytype_t type); - -/** - * Updates an entity. - * - * @param entity Pointer to the entity structure to update. - */ -void entityUpdate(entity_t *entity); - -/** - * Returns true if the entity is in a state where it can turn. - * - * @param entity Pointer to the entity to check. - * @returns True if the entity can turn. - */ -bool_t entityCanTurn(entity_t *entity); - -/** - * Returns true if the entity is in a state where it can walk. - * - * @param entity Pointer to the entity to check. - * @returns True if the entity can walk. - */ -bool_t entityCanWalk(entity_t *entity); - -/** - * Returns true if the entity is in a state where it can run. - * - * @param entity Pointer to the entity to check. - * @returns True if the entity can run. - */ -bool_t entityCanRun(entity_t *entity); - -/** - * Returns true if the entity is allowed to be unloaded. By default this is - * true for entities whose global ID falls within the randomly assigned - * range below ENTITY_GLOBAL_ID_START. - * - * @param entity Pointer to the entity to check. - * @returns True if the entity can be unloaded. - */ -bool_t entityCanUnload(entity_t *entity); - -/** - * Turn an entity to face a new direction. - * - * @param entity Pointer to the entity to turn. - * @param direction The direction to face. - */ -void entityTurn(entity_t *entity, const entitydir_t direction); - -/** - * Make an entity walk in a direction. - * - * @param entity Pointer to the entity to make walk. - * @param direction The direction to walk in. - */ -void entityWalk(entity_t *entity, const entitydir_t direction); - -/** - * Make an entity run in a direction. - * - * @param entity Pointer to the entity to make run. - * @param direction The direction to run in. - */ -void entityRun(entity_t *entity, const entitydir_t direction); - -/** - * Gets the entity at a specific world position. - * - * @param map Pointer to the map to check. - * @param pos The world position to check. - * @return Pointer to the entity at the position, or NULL if none. - */ -entity_t *entityGetAt(const worldpos_t pos); - -/** - * Gets the entity with the given global ID, if one is currently loaded. - * - * @param globalId The global ID to search for. - * @return Pointer to the matching entity, or NULL if none is loaded. - */ -entity_t *entityGetByGlobalId(const entityglobalid_t globalId); - -/** - * Gets an available entity index. - * - * @return The index of an available entity, or 0xFF if none are available. - */ -uint8_t entityGetAvailable(); - -/** - * Assigns an entity to a chunk, removing it from its current chunk first. - * Pass 0xFF as chunkIndex to detach the entity from any chunk. - * - * @param entity Pointer to the entity. - * @param chunkIndex Index of the chunk to assign to, or 0xFF for none. - */ -void entitySetChunk(entity_t *entity, const uint8_t chunkIndex); - -/** - * Resolves the chunk that an entity's current position falls into and - * assigns the entity to it via entitySetChunk. Leaves the entity's chunk - * unchanged if its position doesn't fall within any loaded chunk. - * - * @param entity Pointer to the entity to update. - */ -void entityUpdateChunk(entity_t *entity); - -/** - * Instantly moves an entity to a world position, resetting movement state. - * - * @param entity Pointer to the entity to move. - * @param pos The world position to place the entity at. - */ -void entityPositionSet(entity_t *entity, const worldpos_t pos); \ No newline at end of file diff --git a/src/dusk/rpg/entity/entitydir.c b/src/dusk/rpg/entity/entitydir.c deleted file mode 100644 index bf75e7c7..00000000 --- a/src/dusk/rpg/entity/entitydir.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entitydir.h" -#include "assert/assert.h" - -entitydir_t entityDirGetOpposite(const entitydir_t dir) { - switch(dir) { - case ENTITY_DIR_NORTH: return ENTITY_DIR_SOUTH; - case ENTITY_DIR_SOUTH: return ENTITY_DIR_NORTH; - case ENTITY_DIR_EAST: return ENTITY_DIR_WEST; - case ENTITY_DIR_WEST: return ENTITY_DIR_EAST; - default: return dir; - } -} - -void entityDirGetRelative( - const entitydir_t from, - worldunits_t *outX, - worldunits_t *outY -) { - assertValidEntityDir(from, "Invalid direction provided"); - assertNotNull(outX, "Output X pointer cannot be NULL"); - assertNotNull(outY, "Output Y pointer cannot be NULL"); - - switch(from) { - case ENTITY_DIR_NORTH: - *outX = 0; - *outY = 1; - break; - - case ENTITY_DIR_EAST: - *outX = 1; - *outY = 0; - break; - - case ENTITY_DIR_SOUTH: - *outX = 0; - *outY = -1; - break; - - case ENTITY_DIR_WEST: - *outX = -1; - *outY = 0; - break; - } -} \ No newline at end of file diff --git a/src/dusk/rpg/entity/entitydir.h b/src/dusk/rpg/entity/entitydir.h deleted file mode 100644 index 2eefab88..00000000 --- a/src/dusk/rpg/entity/entitydir.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/overworld/worldpos.h" - -typedef enum { - ENTITY_DIR_NORTH, - ENTITY_DIR_EAST, - ENTITY_DIR_SOUTH, - ENTITY_DIR_WEST, - ENTITY_DIR_UP = ENTITY_DIR_NORTH, - ENTITY_DIR_DOWN = ENTITY_DIR_SOUTH, - ENTITY_DIR_LEFT = ENTITY_DIR_WEST, - ENTITY_DIR_RIGHT = ENTITY_DIR_EAST, -} entitydir_t; - -/** - * Gets the opposite direction of a given direction. - * - * @param dir The direction to get the opposite of. - * @return entitydir_t The opposite direction. - */ -entitydir_t entityDirGetOpposite(const entitydir_t dir); - -/** - * Asserts a given direction is valid. - * - * @param dir The direction to validate. - * @param msg The message to display if the assertion fails. - */ -#define assertValidEntityDir(dir, msg) \ - assertTrue( \ - (dir) == ENTITY_DIR_NORTH || \ - (dir) == ENTITY_DIR_EAST || \ - (dir) == ENTITY_DIR_SOUTH || \ - (dir) == ENTITY_DIR_WEST, \ - msg \ - ) - -/** - * Gets the relative x and y offsets for a given direction. - * - * @param dir The direction to get offsets for. - * @param relX Pointer to store the relative x offset. - * @param relY Pointer to store the relative y offset. - */ -void entityDirGetRelative( - const entitydir_t dir, worldunits_t *relX, worldunits_t *relY -); \ No newline at end of file diff --git a/src/dusk/rpg/entity/entitypathstep.c b/src/dusk/rpg/entity/entitypathstep.c deleted file mode 100644 index bd474415..00000000 --- a/src/dusk/rpg/entity/entitypathstep.c +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entitypathstep.h" -#include "entitydir.h" -#include "assert/assert.h" - -bool_t entityPathStep( - entity_t *entity, - const worldpos_t target, - bool_t walkAround -) { - assertNotNull(entity, "Entity must not be NULL"); - assertTrue( - entity->type != ENTITY_TYPE_NULL, - "Cannot path step a NULL entity type" - ); - assertTrue( - entity >= ENTITIES && entity < ENTITIES + ENTITY_COUNT, - "Entity pointer is out of bounds" - ); - - if(worldPosIsEqual(entity->position, target) && entityCanWalk(entity)) { - return true; - } - if(!entityCanWalk(entity)) return false; - - entitydir_t dir; - if(entity->position.x != target.x) { - dir = entity->position.x < target.x ? ENTITY_DIR_EAST : ENTITY_DIR_WEST; - } else if(entity->position.y != target.y) { - dir = entity->position.y < target.y ? ENTITY_DIR_NORTH : ENTITY_DIR_SOUTH; - } else { - dir = entity->position.z < target.z ? ENTITY_DIR_NORTH : ENTITY_DIR_SOUTH; - } - - entityWalk(entity, dir); - - if(walkAround && entity->animation == ENTITY_ANIM_IDLE) { - // Primary direction blocked - try perpendicular axes. - entitydir_t alt, altOpp; - if(dir == ENTITY_DIR_EAST || dir == ENTITY_DIR_WEST) { - alt = entity->position.y <= target.y - ? ENTITY_DIR_NORTH : ENTITY_DIR_SOUTH; - } else { - alt = entity->position.x <= target.x - ? ENTITY_DIR_EAST : ENTITY_DIR_WEST; - } - altOpp = entityDirGetOpposite(alt); - entityWalk(entity, alt); - if(entity->animation == ENTITY_ANIM_IDLE) entityWalk(entity, altOpp); - } - - return false; -} diff --git a/src/dusk/rpg/entity/entitypathstep.h b/src/dusk/rpg/entity/entitypathstep.h deleted file mode 100644 index 1608cae8..00000000 --- a/src/dusk/rpg/entity/entitypathstep.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "entity.h" - -/** - * Attempts to walk the entity one tile toward target. Prefers resolving X - * first, then Y, then Z. Does nothing if the entity cannot currently walk. - * When walkAround is true and the preferred direction is blocked by an entity, - * tries perpendicular directions to navigate around it. - * - * @param entity Pointer to the entity to move. - * @param target The world position to move toward. - * @param walkAround Whether to try perpendicular directions when blocked. - * @returns true if the entity is already at target, false otherwise. - */ -bool_t entityPathStep( - entity_t *entity, - const worldpos_t target, - bool_t walkAround -); diff --git a/src/dusk/rpg/entity/entitytype.h b/src/dusk/rpg/entity/entitytype.h deleted file mode 100644 index 6b7d2769..00000000 --- a/src/dusk/rpg/entity/entitytype.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/entity/player.h" -#include "npc/npc.h" -#include "item/entityitem.h" - -typedef enum { - ENTITY_TYPE_NULL, - - ENTITY_TYPE_PLAYER, - ENTITY_TYPE_NPC, - ENTITY_TYPE_ITEM, - - ENTITY_TYPE_COUNT -} entitytype_enum_t; - -typedef uint8_t entitytype_t; - -typedef union { - player_t player; - npc_t npc; - entityitem_t item; -} entitytypedata_t; - -typedef struct { - /** - * Initialization callback for the entity type. - * @param entity Pointer to the entity to initialize. - */ - void (*init)(entity_t *entity); - - /** - * Movement callback for the entity type. Gated by cutscene input. - * @param entity Pointer to the entity to move. - */ - void (*movement)(entity_t *entity); -} entitycallback_t; - -static const entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { - [ENTITY_TYPE_NULL] = { NULL }, - - [ENTITY_TYPE_PLAYER] = { - .init = playerInit, - .movement = playerInput - }, - - [ENTITY_TYPE_NPC] = { - .init = npcInit, - .movement = npcMovement, - }, - - [ENTITY_TYPE_ITEM] = { - .init = entityItemInit, - .movement = entityItemMovement, - } -}; \ No newline at end of file diff --git a/src/dusk/rpg/entity/global/CMakeLists.txt b/src/dusk/rpg/entity/global/CMakeLists.txt deleted file mode 100644 index 9b35b01d..00000000 --- a/src/dusk/rpg/entity/global/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC -) \ No newline at end of file diff --git a/src/dusk/rpg/entity/global/entityglobal.h b/src/dusk/rpg/entity/global/entityglobal.h deleted file mode 100644 index 10d51d60..00000000 --- a/src/dusk/rpg/entity/global/entityglobal.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "entityglobaldefs.h" -#include "entitygloballist.h" - -#define ENTITY_GLOBAL_LIST_COUNT ( \ - sizeof(ENTITY_GLOBAL_LIST) / \ - sizeof(ENTITY_GLOBAL_LIST[0]) \ -) - -//EOF diff --git a/src/dusk/rpg/entity/global/entityglobaldefs.h b/src/dusk/rpg/entity/global/entityglobaldefs.h deleted file mode 100644 index 73913e45..00000000 --- a/src/dusk/rpg/entity/global/entityglobaldefs.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "rpg/overworld/worldpos.h" -#include "rpg/entity/entity.h" - -typedef struct entity_s entity_t; - -typedef struct { - entity_t *entity; - worldpos_t position; -} entityglobalcreate_t; - -/** - * Callback invoked to initialize a global entity. - * - * @param create Pointer to the entity/position being initialized. - * @returns An error code. - */ -typedef void (*entityglobalinitcallback_t)( - entityglobalcreate_t *create -); - -typedef struct { - entitytype_t type; - entityglobalinitcallback_t callback; -} entityglobaldef_t; - -#define ENTITY_GLOBAL(id, entType, callbackFn) \ - [id] = { .type = entType, .callback = callbackFn } - -#define ENTITY_GLOBAL_CALLBACK(id) \ - static void ENTTIYT_GLOBAL_CALLBACK_##id(entityglobalcreate_t *create) - -#define ENTITY_GLOBAL_REF(id) \ - ENTTIYT_GLOBAL_CALLBACK_##id - -//EOF \ No newline at end of file diff --git a/src/dusk/rpg/entity/global/entitygloballist.h b/src/dusk/rpg/entity/global/entitygloballist.h deleted file mode 100644 index 2207763c..00000000 --- a/src/dusk/rpg/entity/global/entitygloballist.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "entityglobaldefs.h" -#include "rpg/cutscene/scene/testcutscene.h" - -ENTITY_GLOBAL_CALLBACK(3) { - create->entity->data.npc.moveType = NPC_MOVE_TYPE_PATH; - npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 4, 4, 0 }); - npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 10, 10, 1 }); - npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 4, 4, 0 }); - npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 10, 10, 1 }); - - create->entity->interact.type = ENTITY_INTERACT_CUTSCENE; - create->entity->interact.data.cutscene = CUTSCENE_REFERENCE(TEST_TWO); -} - -static const entityglobaldef_t ENTITY_GLOBAL_LIST[] = { - ENTITY_GLOBAL(ENTITY_GLOBAL_ID_NULL, ENTITY_TYPE_NULL, NULL), - ENTITY_GLOBAL(ENTITY_GLOBAL_ID_PLAYER, ENTITY_TYPE_PLAYER, NULL), - - ENTITY_GLOBAL(3, ENTITY_TYPE_NPC, ENTITY_GLOBAL_REF(3)), -}; - -//EOF diff --git a/src/dusk/rpg/entity/interact/CMakeLists.txt b/src/dusk/rpg/entity/interact/CMakeLists.txt deleted file mode 100644 index f7e07e35..00000000 --- a/src/dusk/rpg/entity/interact/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - entityinteract.c -) diff --git a/src/dusk/rpg/entity/interact/entityinteract.c b/src/dusk/rpg/entity/interact/entityinteract.c deleted file mode 100644 index d7a8b224..00000000 --- a/src/dusk/rpg/entity/interact/entityinteract.c +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/entity/entity.h" -#include "assert/assert.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "ui/rpg/textbox/uitextboxmain.h" - -void entityInteractWith(entity_t *player, entity_t *target) { - assertNotNull(player, "Player entity pointer cannot be NULL"); - assertNotNull(target, "Target entity pointer cannot be NULL"); - - switch(target->interact.type) { - case ENTITY_INTERACT_CUTSCENE: - assertNotNull( - target->interact.data.cutscene, - "Interact cutscene pointer cannot be NULL" - ); - cutsceneSystemStartCutsceneWith( - target->interact.data.cutscene, - player, - target - ); - break; - - case ENTITY_INTERACT_PRINT: - uiTextboxMainSetText(target->interact.data.message); - - // If NPC turn to face player. - if(target->type == ENTITY_TYPE_NPC) { - target->data.npc.interactState = NPC_INTERACT_STATE_CONVERSING; - target->animation = ENTITY_ANIM_IDLE; - entityTurn(target, entityDirGetOpposite(player->direction)); - } - - // entityTurn(player, player->direction); // Redundant (for now) - break; - - case ENTITY_INTERACT_CALLBACK: - assertNotNull( - target->interact.data.callback, - "Interact callback pointer cannot be NULL" - ); - target->interact.data.callback(player, target); - break; - - case ENTITY_INTERACT_NULL: - break; - - default: - assertUnreachable("Unknown entity interact type"); - break; - } -} \ No newline at end of file diff --git a/src/dusk/rpg/entity/interact/entityinteract.h b/src/dusk/rpg/entity/interact/entityinteract.h deleted file mode 100644 index 4f1f39d4..00000000 --- a/src/dusk/rpg/entity/interact/entityinteract.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct entity_s entity_t; -typedef struct cutscene_s cutscene_t; - -/** - * Describes the type of interaction an entity supports. - */ -typedef enum { - ENTITY_INTERACT_NULL = 0, - - ENTITY_INTERACT_CUTSCENE, - ENTITY_INTERACT_PRINT, - ENTITY_INTERACT_CALLBACK, - - ENTITY_INTERACT_COUNT -} entityinteracttype_t; - -/** - * Per-type data for an entity's interact component. - */ -typedef union { - const cutscene_t *cutscene; - const char_t *message; - void (*callback)(entity_t *player, entity_t *target); -} entityinteractdata_t; - -/** - * Interact component attached to any entity that can be interacted with. - * Set type to ENTITY_INTERACT_NULL to mark the entity as non-interactable. - */ -typedef struct { - entityinteracttype_t type; - entityinteractdata_t data; -} entityinteract_t; - -/** - * Attempts to interact with the target entity on behalf of the player. - * Dispatches via the interact component; falls back to the entity type - * callback if no component is set. - * - * @param player Pointer to the player entity. - * @param target Pointer to the entity to interact with. - */ -void entityInteractWith(entity_t *player, entity_t *target); diff --git a/src/dusk/rpg/entity/item/CMakeLists.txt b/src/dusk/rpg/entity/item/CMakeLists.txt deleted file mode 100644 index 6834d19b..00000000 --- a/src/dusk/rpg/entity/item/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - entityitem.c -) diff --git a/src/dusk/rpg/entity/item/entityitem.c b/src/dusk/rpg/entity/item/entityitem.c deleted file mode 100644 index eccfd0f6..00000000 --- a/src/dusk/rpg/entity/item/entityitem.c +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entityitem.h" -#include "rpg/entity/entity.h" -#include "assert/assert.h" -#include "rpg/item/itemgive.h" -#include "ui/rpg/textbox/uitextboxmain.h" - -void entityItemInit(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - entity->interact.type = ENTITY_INTERACT_CALLBACK; - entity->interact.data.callback = entityItemInteract; -} - -void entityItemSet( - entity_t *entity, - const itemid_t item, - const uint8_t quantity -) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - entity->data.item.item = item; - entity->data.item.quantity = quantity; -} - -void entityItemInteract(entity_t *player, entity_t *target) { - assertNotNull(player, "Player entity pointer cannot be NULL"); - assertNotNull(target, "Target entity pointer cannot be NULL"); - - itemGive(target->data.item.item, target->data.item.quantity); - target->data.item.collected = true; -} - -void entityItemMovement(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - if(!entity->data.item.collected) return; - if(uiTextboxMainIsActive()) return; - - entity->type = ENTITY_TYPE_NULL; -} diff --git a/src/dusk/rpg/entity/item/entityitem.h b/src/dusk/rpg/entity/item/entityitem.h deleted file mode 100644 index 1485f1fa..00000000 --- a/src/dusk/rpg/entity/item/entityitem.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/item/item.h" - -typedef struct entity_s entity_t; - -typedef struct { - itemid_t item; - uint8_t quantity; - bool_t collected; -} entityitem_t; - -/** - * Initializes an item entity. Wires up the interact component so that - * interacting with the entity gives its item and removes it. - * - * @param entity Pointer to the entity structure to initialize. - */ -void entityItemInit(entity_t *entity); - -/** - * Sets the item and quantity represented by an item entity. - * - * @param entity Pointer to the entity structure. - * @param item The item ID to give when picked up. - * @param quantity The quantity to give when picked up. - */ -void entityItemSet( - entity_t *entity, - const itemid_t item, - const uint8_t quantity -); - -/** - * Interact callback for item entities. Gives the entity's item to the - * player and shows the pickup message. The entity itself is removed once - * the message has been dismissed, via entityItemMovement. - * - * @param player Pointer to the player entity. - * @param target Pointer to the item entity being picked up. - */ -void entityItemInteract(entity_t *player, entity_t *target); - -/** - * Update callback for item entities. Removes the entity once its pickup - * message has been dismissed. No-op if the item hasn't been collected. - * - * @param entity Pointer to the entity structure to update. - */ -void entityItemMovement(entity_t *entity); diff --git a/src/dusk/rpg/entity/npc/CMakeLists.txt b/src/dusk/rpg/entity/npc/CMakeLists.txt deleted file mode 100644 index 922a4e1d..00000000 --- a/src/dusk/rpg/entity/npc/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - npc.c - npcturn.c - npcwalk.c - npcpath.c -) diff --git a/src/dusk/rpg/entity/npc/npc.c b/src/dusk/rpg/entity/npc/npc.c deleted file mode 100644 index 05175828..00000000 --- a/src/dusk/rpg/entity/npc/npc.c +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg/entity/entity.h" -#include "assert/assert.h" -#include "rpg/cutscene/cutscenesystem.h" - -#include "rpg/cutscene/scene/testcutscene.h" - -const npcmovecallback_t NPC_MOVE_CALLBACKS[NPC_MOVE_TYPE_COUNT] = { - [NPC_MOVE_TYPE_NULL] = { 0 }, - - [NPC_MOVE_TYPE_RANDOM_TURN] = { - npcRandomTurnInit, - npcRandomTurnMovement - }, - - [NPC_MOVE_TYPE_RANDOM_WALK] = { - npcRandomWalkInit, - npcRandomWalkMovement - }, - - [NPC_MOVE_TYPE_RANDOM_TURN_AND_WALK] = { - npcRandomTurnAndWalkInit, - npcRandomTurnAndWalkMovement - }, - - [NPC_MOVE_TYPE_PATH] = { - npcPathInit, - npcPathMovement - }, -}; - -void npcInit(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); -} - -void npcSetMoveType(entity_t *entity, const npcmovetype_t moveType) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - npc_t *npc = &entity->data.npc; - npc->moveType = moveType; - if(NPC_MOVE_CALLBACKS[moveType].init != NULL) { - NPC_MOVE_CALLBACKS[moveType].init(npc); - } -} - -void npcMovement(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - if(CUTSCENE_SYSTEM.pause & CUTSCENE_PAUSE_NPC) return; - - npc_t *npc = &entity->data.npc; - if(npc->interactState != NPC_INTERACT_STATE_NONE) return; - - const npcmovecallback_t *cb = &NPC_MOVE_CALLBACKS[npc->moveType]; - if(cb->movement != NULL) cb->movement(entity); -} \ No newline at end of file diff --git a/src/dusk/rpg/entity/npc/npc.h b/src/dusk/rpg/entity/npc/npc.h deleted file mode 100644 index be16ee9b..00000000 --- a/src/dusk/rpg/entity/npc/npc.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "npcturn.h" -#include "npcwalk.h" -#include "npcpath.h" - -typedef struct entity_s entity_t; - -typedef enum { - NPC_INTERACT_STATE_NONE, - NPC_INTERACT_STATE_CONVERSING, - NPC_INTERACT_STATE_COUNT -} npcinteractstate_t; - -typedef enum { - NPC_MOVE_TYPE_NULL, - NPC_MOVE_TYPE_RANDOM_TURN, - NPC_MOVE_TYPE_RANDOM_WALK, - NPC_MOVE_TYPE_RANDOM_TURN_AND_WALK, - NPC_MOVE_TYPE_PATH, - NPC_MOVE_TYPE_COUNT -} npcmovetype_t; - -typedef union { - npcrandomturn_t randomTurn; - npcrandomwalk_t randomWalk; - npcrandomturnandwalk_t randomTurnAndWalk; - npcpath_t path; -} npcmovedata_t; - -typedef struct npc_s { - npcinteractstate_t interactState; - npcmovetype_t moveType; - npcmovedata_t moveData; -} npc_t; - -typedef struct { - /** Called once when the move type is set. */ - void (*init)(npc_t *npc); - /** Called each movement tick. */ - void (*movement)(entity_t *entity); -} npcmovecallback_t; - -extern const npcmovecallback_t NPC_MOVE_CALLBACKS[NPC_MOVE_TYPE_COUNT]; - -/** - * Initializes an NPC entity. - * - * @param entity Pointer to the entity structure to initialize. - */ -void npcInit(entity_t *entity); - -/** - * Sets the movement type for an NPC entity. - * - * @param entity Pointer to the entity structure. - * @param moveType The movement type to set. - */ -void npcSetMoveType(entity_t *entity, const npcmovetype_t moveType); - -/** - * Movement callback for an NPC entity. Gated by cutscene input. - * - * @param entity Pointer to the entity structure to update. - */ -void npcMovement(entity_t *entity); - -/** - * Free movement callback for an NPC entity. Runs always-run move types - * regardless of cutscene state. - * - * @param entity Pointer to the entity structure to update. - */ -void npcFreeMovement(entity_t *entity); \ No newline at end of file diff --git a/src/dusk/rpg/entity/npc/npcpath.c b/src/dusk/rpg/entity/npc/npcpath.c deleted file mode 100644 index 9d6ea47d..00000000 --- a/src/dusk/rpg/entity/npc/npcpath.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "npc.h" -#include "rpg/entity/entity.h" -#include "rpg/entity/entitypathstep.h" -#include "rpg/overworld/worldpos.h" -#include "assert/assert.h" - -void npcPathInit(npc_t *npc) { - npcpath_t *path = &npc->moveData.path; - path->count = 0; - path->index = 0; -} - -void npcPathAddNode(npc_t *npc, const worldpos_t pos) { - assertNotNull(npc, "NPC must not be NULL"); - assertTrue( - npc->moveData.path.count < NPC_PATH_COUNT_MAX, - "NPC path is full" - ); - npc->moveData.path.positions[npc->moveData.path.count++] = pos; -} - -void npcPathMovement(entity_t *entity) { - npcpath_t *path = &entity->data.npc.moveData.path; - if(path->count == 0) return; - if(!entityCanWalk(entity)) return; - - // Advance past any waypoints already reached (including the current one). - worldpos_t *target = &path->positions[path->index]; - if(entityPathStep(entity, *target, false)) { - path->index = (path->index + 1) % path->count; - target = &path->positions[path->index]; - // New target is the same tile - nothing to do this tick - if(worldPosIsEqual(entity->position, *target)) return; - entityPathStep(entity, *target, false); - } -} diff --git a/src/dusk/rpg/entity/npc/npcpath.h b/src/dusk/rpg/entity/npc/npcpath.h deleted file mode 100644 index d6469168..00000000 --- a/src/dusk/rpg/entity/npc/npcpath.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "rpg/overworld/worldpos.h" - -typedef struct npc_s npc_t; -typedef struct entity_s entity_t; - -/** Maximum number of waypoints in an NPC path. */ -#define NPC_PATH_COUNT_MAX 8 - -typedef struct { - worldpos_t positions[NPC_PATH_COUNT_MAX]; - uint8_t count; - uint8_t index; -} npcpath_t; - -/** - * Initializes the path movement data for an NPC. - * - * @param npc Pointer to the NPC to initialize. - */ -void npcPathInit(npc_t *npc); - -/** - * Appends a waypoint to the NPC's path. Has no effect if the path is full. - * - * @param npc Pointer to the NPC. - * @param pos The world position to append. - */ -void npcPathAddNode(npc_t *npc, const worldpos_t pos); - -/** - * Movement tick for an NPC following a path. - * - * @param entity Pointer to the entity to update. - */ -void npcPathMovement(entity_t *entity); diff --git a/src/dusk/rpg/entity/npc/npcturn.c b/src/dusk/rpg/entity/npc/npcturn.c deleted file mode 100644 index 63654ab3..00000000 --- a/src/dusk/rpg/entity/npc/npcturn.c +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "npc.h" -#include "rpg/entity/entity.h" -#include "util/random.h" -#include "time/time.h" -#include - -void npcRandomTurnInit(npc_t *npc) { - npcrandomturn_t *turn = &npc->moveData.randomTurn; - turn->frequencyMin = NPC_RANDOM_TURN_FREQUENCY_MIN_DEFAULT; - turn->frequencyMax = NPC_RANDOM_TURN_FREQUENCY_MAX_DEFAULT; - turn->timer = randomFloat(turn->frequencyMin, turn->frequencyMax); -} - -void npcRandomTurnMovement(entity_t *entity) { - npcrandomturn_t *turn = &entity->data.npc.moveData.randomTurn; - turn->timer -= TIME.delta; - if(turn->timer > 0.0f) return; - turn->timer = randomFloat(turn->frequencyMin, turn->frequencyMax); - if(entityCanTurn(entity)) entityTurn(entity, (entitydir_t)(rand() % 4)); -} diff --git a/src/dusk/rpg/entity/npc/npcturn.h b/src/dusk/rpg/entity/npc/npcturn.h deleted file mode 100644 index 3568bbdb..00000000 --- a/src/dusk/rpg/entity/npc/npcturn.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct npc_s npc_t; -typedef struct entity_s entity_t; - -/** Default min/max seconds between NPC random-turn ticks. */ -#define NPC_RANDOM_TURN_FREQUENCY_MIN_DEFAULT 2.0f -#define NPC_RANDOM_TURN_FREQUENCY_MAX_DEFAULT 4.0f - -typedef struct { - float_t frequencyMin; - float_t frequencyMax; - float_t timer; -} npcrandomturn_t; - -/** - * Initializes the random-turn movement data for an NPC. - * - * @param npc Pointer to the NPC to initialize. - */ -void npcRandomTurnInit(npc_t *npc); - -/** - * Movement tick for an NPC using random-turn movement. - * - * @param entity Pointer to the entity to update. - */ -void npcRandomTurnMovement(entity_t *entity); diff --git a/src/dusk/rpg/entity/npc/npcwalk.c b/src/dusk/rpg/entity/npc/npcwalk.c deleted file mode 100644 index dc8794ec..00000000 --- a/src/dusk/rpg/entity/npc/npcwalk.c +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "npc.h" -#include "rpg/entity/entity.h" -#include "util/random.h" -#include "time/time.h" -#include - -void npcRandomWalkInit(npc_t *npc) { - npcrandomwalk_t *walk = &npc->moveData.randomWalk; - walk->frequencyMin = NPC_RANDOM_WALK_FREQUENCY_MIN_DEFAULT; - walk->frequencyMax = NPC_RANDOM_WALK_FREQUENCY_MAX_DEFAULT; - walk->timer = randomFloat(walk->frequencyMin, walk->frequencyMax); -} - -void npcRandomWalkMovement(entity_t *entity) { - npcrandomwalk_t *walk = &entity->data.npc.moveData.randomWalk; - walk->timer -= TIME.delta; - if(walk->timer > 0.0f) return; - walk->timer = randomFloat(walk->frequencyMin, walk->frequencyMax); - if(entityCanWalk(entity)) entityWalk(entity, (entitydir_t)(rand() % 4)); -} - -void npcRandomTurnAndWalkInit(npc_t *npc) { - npcRandomTurnInit(npc); - npcrandomturnandwalk_t *tw = &npc->moveData.randomTurnAndWalk; - tw->walk.frequencyMin = NPC_RANDOM_WALK_FREQUENCY_MIN_DEFAULT; - tw->walk.frequencyMax = NPC_RANDOM_WALK_FREQUENCY_MAX_DEFAULT; - tw->walk.timer = randomFloat(tw->walk.frequencyMin, tw->walk.frequencyMax); -} - -void npcRandomTurnAndWalkMovement(entity_t *entity) { - npcrandomturnandwalk_t *tw = &entity->data.npc.moveData.randomTurnAndWalk; - - tw->turn.timer -= TIME.delta; - if(tw->turn.timer <= 0.0f) { - tw->turn.timer = randomFloat(tw->turn.frequencyMin, tw->turn.frequencyMax); - if(entityCanTurn(entity)) entityTurn(entity, (entitydir_t)(rand() % 4)); - } - - tw->walk.timer -= TIME.delta; - if(tw->walk.timer <= 0.0f) { - tw->walk.timer = randomFloat(tw->walk.frequencyMin, tw->walk.frequencyMax); - if(entityCanWalk(entity)) entityWalk(entity, (entitydir_t)(rand() % 4)); - } -} - diff --git a/src/dusk/rpg/entity/npc/npcwalk.h b/src/dusk/rpg/entity/npc/npcwalk.h deleted file mode 100644 index 4a65c4f8..00000000 --- a/src/dusk/rpg/entity/npc/npcwalk.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "npcturn.h" - -/** Default min/max seconds between NPC random-walk ticks. */ -#define NPC_RANDOM_WALK_FREQUENCY_MIN_DEFAULT 2.0f -#define NPC_RANDOM_WALK_FREQUENCY_MAX_DEFAULT 5.0f - -typedef struct { - float_t frequencyMin; - float_t frequencyMax; - float_t timer; -} npcrandomwalk_t; - -typedef struct { - npcrandomturn_t turn; - npcrandomwalk_t walk; -} npcrandomturnandwalk_t; - -/** - * Initializes the random-walk movement data for an NPC. - * - * @param npc Pointer to the NPC to initialize. - */ -void npcRandomWalkInit(npc_t *npc); - -/** - * Movement tick for an NPC using random-walk movement. - * - * @param entity Pointer to the entity to update. - */ -void npcRandomWalkMovement(entity_t *entity); - -/** - * Initializes the random-turn-and-walk movement data for an NPC. - * - * @param npc Pointer to the NPC to initialize. - */ -void npcRandomTurnAndWalkInit(npc_t *npc); - -/** - * Movement tick for an NPC using random-turn-and-walk movement. - * - * @param entity Pointer to the entity to update. - */ -void npcRandomTurnAndWalkMovement(entity_t *entity); - diff --git a/src/dusk/rpg/entity/player.c b/src/dusk/rpg/entity/player.c deleted file mode 100644 index 632f726b..00000000 --- a/src/dusk/rpg/entity/player.c +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entity.h" -#include "assert/assert.h" -#include "rpg/rpgcamera.h" -#include "util/memory.h" -#include "time/time.h" -#include "ui/focus/uifocus.h" -#include "ui/frame/game/uigamemenu.h" -#include "rpg/cutscene/cutscenesystem.h" - -void playerInit(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - entity->globalId = ENTITY_GLOBAL_ID_PLAYER; -} - -bool_t playerCanInteract(entity_t *entity) { - return entity->animation == ENTITY_ANIM_IDLE; -} - -void playerInput(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - if(CUTSCENE_SYSTEM.pause & CUTSCENE_PAUSE_PLAYER) return; - - // Toggle game menu on pause - if(uiGameMenuIsOpen() && inputPressed(INPUT_ACTION_PAUSE)) { - uiGameMenuClose(); - } else if( - inputPressed(INPUT_ACTION_PAUSE) && - entity->animation == ENTITY_ANIM_IDLE - ) { - uiGameMenuOpen(); - } - - // Can player act? - if(UI_FOCUS.count > 0) return; - - // Determine direction player may be trying to face/go. - const playerinputdirmap_t *dirMap; - - // First pass, we want to prefer a button relative to what the player is - // already facing, e.g. if they hold DOWN and start moving down, then tap - // right we want to prefer down over right. - - // Determine current dirmap based on facing direction. - dirMap = PLAYER_INPUT_DIR_MAP; - do { - if(dirMap->direction != entity->direction) continue; - break; - } while((++dirMap)->action != 0xFF); - - // Are we holding that button? - if(!inputIsDown(dirMap->action)) { - // No, so we need to check all directions. - dirMap = PLAYER_INPUT_DIR_MAP; - do { - if(!inputIsDown(dirMap->action)) continue; - break; - } while((++dirMap)->action != 0xFF); - } - - // Trying to direct? - if(dirMap->action != 0xFF) { - // Is the player attempting to turn? That is, is the player idle and has the - // turn lockout passed? - if(entityCanTurn(entity)) { - if(entity->direction != dirMap->direction) { - entityTurn(entity, dirMap->direction); - return; - } - } - - bool_t running = inputIsDown(INPUT_ACTION_CANCEL); - if(running && entityCanRun(entity)) { - entityRun(entity, dirMap->direction); - } else if(entityCanWalk(entity)) { - entityWalk(entity, dirMap->direction); - } - } - - // Interaction - if(inputPressed(INPUT_ACTION_ACCEPT) && playerCanInteract(entity)) { - worldunit_t x, y, z; - { - worldunits_t relX, relY; - entityDirGetRelative(entity->direction, &relX, &relY); - x = entity->position.x + relX; - y = entity->position.y + relY; - z = entity->position.z; - } - - entity_t *target = entityGetAt((worldpos_t){ x, y, z }); - if(target == NULL) return; - entityInteractWith(entity, target); - } -} \ No newline at end of file diff --git a/src/dusk/rpg/entity/player.h b/src/dusk/rpg/entity/player.h deleted file mode 100644 index 13e369d1..00000000 --- a/src/dusk/rpg/entity/player.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "input/input.h" -#include "entitydir.h" - -typedef struct entity_s entity_t; - -typedef struct { - void *nothing; -} player_t; - -typedef struct { - inputaction_t action; - entitydir_t direction; -} playerinputdirmap_t; - -static const playerinputdirmap_t PLAYER_INPUT_DIR_MAP[] = { - { INPUT_ACTION_UP, ENTITY_DIR_NORTH }, - { INPUT_ACTION_DOWN, ENTITY_DIR_SOUTH }, - { INPUT_ACTION_LEFT, ENTITY_DIR_WEST }, - { INPUT_ACTION_RIGHT, ENTITY_DIR_EAST }, - - { 0xFF, 0xFF } -}; - -/** - * Initializes a player entity. - * - * @param entity Pointer to the entity structure to initialize. - */ -void playerInit(entity_t *entity); - -/** - * Returns true if the player entity is in a state where it can interact. - * - * @param entity Pointer to the player entity to check. - * @returns True if the entity can interact. - */ -bool_t playerCanInteract(entity_t *entity); - -/** - * Handles movement logic for the player entity. - * - * @param entity Pointer to the player entity structure. - */ -void playerInput(entity_t *entity); \ No newline at end of file diff --git a/src/dusk/rpg/item/CMakeLists.txt b/src/dusk/rpg/item/CMakeLists.txt deleted file mode 100644 index cbd4416d..00000000 --- a/src/dusk/rpg/item/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - item.c - inventory.c - backpack.c - itemgive.c -) - -# Item Definitions -dusk_run_python( - dusk_item_json_defs - tools.item - --json ${CMAKE_CURRENT_SOURCE_DIR}/item.json - --output ${DUSK_GENERATED_HEADERS_DIR}/rpg/item/itemdef.h -) -add_dependencies(${DUSK_LIBRARY_TARGET_NAME} dusk_item_json_defs) \ No newline at end of file diff --git a/src/dusk/rpg/item/backpack.c b/src/dusk/rpg/item/backpack.c deleted file mode 100644 index 03bd91ae..00000000 --- a/src/dusk/rpg/item/backpack.c +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "backpack.h" -#include "assert/assert.h" - -backpack_t BACKPACK; - -void backpackInit() { - for(uint8_t i = 0; i < ITEM_TYPE_COUNT; i++) { - inventoryInit( - &BACKPACK.inventories[i], - BACKPACK.storage[i], - ITEM_TYPE_COUNT_MAX - ); - } -} - -inventory_t *backpackGetInventory(const itemtype_t type) { - assertTrue(type > ITEM_TYPE_NULL, "Item type must not be null"); - assertTrue(type < ITEM_TYPE_COUNT, "Item type out of range"); - return &BACKPACK.inventories[type]; -} - -void backpackAdd(const itemid_t item, const uint8_t quantity) { - assertTrue(item > ITEM_ID_NULL, "Item ID must not be null"); - assertTrue(item < ITEM_ID_COUNT, "Item ID out of range"); - inventoryAdd(backpackGetInventory(ITEMS[item].type), item, quantity); -} - -void backpackRemove(const itemid_t item) { - assertTrue(item > ITEM_ID_NULL, "Item ID must not be null"); - assertTrue(item < ITEM_ID_COUNT, "Item ID out of range"); - inventoryRemove(backpackGetInventory(ITEMS[item].type), item); -} - -void backpackSet(const itemid_t item, const uint8_t quantity) { - assertTrue(item > ITEM_ID_NULL, "Item ID must not be null"); - assertTrue(item < ITEM_ID_COUNT, "Item ID out of range"); - inventorySet(backpackGetInventory(ITEMS[item].type), item, quantity); -} - -uint8_t backpackGetCount(const itemid_t item) { - assertTrue(item > ITEM_ID_NULL, "Item ID must not be null"); - assertTrue(item < ITEM_ID_COUNT, "Item ID out of range"); - return inventoryGetCount(backpackGetInventory(ITEMS[item].type), item); -} - -bool_t backpackItemExists(const itemid_t item) { - assertTrue(item > ITEM_ID_NULL, "Item ID must not be null"); - assertTrue(item < ITEM_ID_COUNT, "Item ID out of range"); - return inventoryItemExists(backpackGetInventory(ITEMS[item].type), item); -} - -bool_t backpackIsFull(const itemtype_t type) { - assertTrue(type > ITEM_TYPE_NULL, "Item type must not be null"); - assertTrue(type < ITEM_TYPE_COUNT, "Item type out of range"); - return inventoryIsFull(backpackGetInventory(type)); -} - -bool_t backpackItemFull(const itemid_t item) { - assertTrue(item > ITEM_ID_NULL, "Item ID must not be null"); - assertTrue(item < ITEM_ID_COUNT, "Item ID out of range"); - return inventoryItemFull(backpackGetInventory(ITEMS[item].type), item); -} - -void backpackSort( - const itemtype_t type, - const inventorysort_t sortBy, - const bool_t reverse -) { - assertTrue(type > ITEM_TYPE_NULL, "Item type must not be null"); - assertTrue(type < ITEM_TYPE_COUNT, "Item type out of range"); - inventorySort(backpackGetInventory(type), sortBy, reverse); -} \ No newline at end of file diff --git a/src/dusk/rpg/item/backpack.h b/src/dusk/rpg/item/backpack.h deleted file mode 100644 index 5812befa..00000000 --- a/src/dusk/rpg/item/backpack.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "inventory.h" - -typedef struct { - inventorystack_t storage[ITEM_TYPE_COUNT][ITEM_TYPE_COUNT_MAX]; - inventory_t inventories[ITEM_TYPE_COUNT]; -} backpack_t; - -extern backpack_t BACKPACK; - -/** - * Initializes the backpack inventory for the player. - */ -void backpackInit(); - -/** - * Returns the inventory for a given item type. - * - * @param type The item type. - * @returns Pointer to the inventory for that type. - */ -inventory_t *backpackGetInventory(const itemtype_t type); - -/** - * Adds a quantity of an item to the backpack. - * - * @param item The item ID to add. - * @param quantity The quantity to add. - */ -void backpackAdd(const itemid_t item, const uint8_t quantity); - -/** - * Removes an item from the backpack. - * - * @param item The item ID to remove. - */ -void backpackRemove(const itemid_t item); - -/** - * Sets the quantity of an item in the backpack. - * - * @param item The item ID to set. - * @param quantity The quantity to set. - */ -void backpackSet(const itemid_t item, const uint8_t quantity); - -/** - * Gets the quantity of an item in the backpack. - * - * @param item The item ID to check. - * @returns The quantity held. - */ -uint8_t backpackGetCount(const itemid_t item); - -/** - * Checks if an item exists in the backpack (quantity > 0). - * - * @param item The item ID to check. - * @returns true if the item exists. - */ -bool_t backpackItemExists(const itemid_t item); - -/** - * Checks if the inventory for a given type is full. - * - * @param type The item type to check. - * @returns true if the type's inventory is full. - */ -bool_t backpackIsFull(const itemtype_t type); - -/** - * Checks if an item's stack is full in the backpack. - * - * @param item The item ID to check. - * @returns true if the item stack is full. - */ -bool_t backpackItemFull(const itemid_t item); - -/** - * Sorts the inventory for a given item type. - * - * @param type The item type whose inventory to sort. - * @param sortBy The sorting criteria. - * @param reverse Whether to sort in reverse order. - */ -void backpackSort( - const itemtype_t type, - const inventorysort_t sortBy, - const bool_t reverse -); \ No newline at end of file diff --git a/src/dusk/rpg/item/inventory.c b/src/dusk/rpg/item/inventory.c deleted file mode 100644 index b3579ccb..00000000 --- a/src/dusk/rpg/item/inventory.c +++ /dev/null @@ -1,250 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "inventory.h" -#include "util/memory.h" -#include "util/sort.h" -#include "assert/assert.h" - -void inventoryInit( - inventory_t* inventory, - inventorystack_t* storage, - uint8_t storageSize -) { - assertNotNull(inventory, "Inventory pointer is NULL."); - assertNotNull(storage, "Storage pointer is NULL."); - assertTrue(storageSize > 0, "Storage size must be greater than zero."); - - inventory->storage = storage; - inventory->storageSize = storageSize; - - memoryZero(storage, sizeof(inventorystack_t) * storageSize); -} - -bool_t inventoryItemExists(const inventory_t *inventory, const itemid_t item) { - assertNotNull(inventory, "Inventory pointer is NULL."); - assertNotNull(inventory->storage, "Storage pointer is NULL."); - assertTrue(inventory->storageSize > 0, "Storage too small."); - assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL."); - - inventorystack_t *stack = inventory->storage; - inventorystack_t *end = stack + inventory->storageSize; - do { - if(stack->item == ITEM_ID_NULL) break; - if(stack->item != item) continue; - assertTrue(stack->quantity > 0, "Item has quantity zero."); - return true; - } while(++stack < end); - - return false; -} - -void inventorySet( - inventory_t *inventory, - const itemid_t item, - const uint8_t quantity -) { - assertNotNull(inventory, "Inventory pointer is NULL."); - assertNotNull(inventory->storage, "Storage pointer is NULL."); - assertTrue(inventory->storageSize > 0, "Storage too small."); - assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL."); - - // If quantity 0, remove. - if(quantity == 0) return inventoryRemove(inventory, item); - - // Search for existing stack. - inventorystack_t *stack = inventory->storage; - inventorystack_t *end = stack + inventory->storageSize; - do { - // Not in inventory yet, add as new stack. - if(stack->item == ITEM_ID_NULL) { - stack->item = item; - stack->quantity = quantity; - return; - } - - // Not the stack we're looking for. - if(stack->item != item) continue; - - // Update existing stack. - stack->quantity = quantity; - return; - } while(++stack < end); - - // No space in the inventory. - assertUnreachable("Inventory is full, cannot set more items."); -} - -void inventoryAdd( - inventory_t *inventory, - const itemid_t item, - const uint8_t quantity -) { - uint8_t current = inventoryGetCount(inventory, item); - uint16_t newQuantity = (uint16_t)current + (uint16_t)quantity; - - assertTrue( - newQuantity <= UINT8_MAX, - "Cannot add item, would overflow maximum quantity." - ); - - inventorySet(inventory, item, (uint8_t)newQuantity); -} - -void inventoryRemove(inventory_t *inventory, const itemid_t item) { - assertNotNull(inventory, "Inventory pointer is NULL."); - assertNotNull(inventory->storage, "Storage pointer is NULL."); - assertTrue(inventory->storageSize > 0, "Storage too small."); - assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL."); - - inventorystack_t *stack = inventory->storage; - inventorystack_t *end = stack + inventory->storageSize; - - // Search for existing stack. - do { - // End of inventory, item not present. - if(stack->item == ITEM_ID_NULL) break; - - // Not matching stack. - if(stack->item != item) continue; - - // Match found, shift everything else down - memoryMove( - stack, - stack + 1, - (end - (stack + 1)) * sizeof(inventorystack_t) - ); - - // Clear last stack. - inventorystack_t *last = end - 1; - last->item = ITEM_ID_NULL; - - break; - } while(++stack < end); -} - -uint8_t inventoryGetCount(const inventory_t *inventory, const itemid_t item) { - assertNotNull(inventory, "Inventory pointer is NULL."); - assertNotNull(inventory->storage, "Storage pointer is NULL."); - assertTrue(inventory->storageSize > 0, "Storage too small."); - assertTrue(item != ITEM_ID_NULL, "Item ID cannot be ITEM_ID_NULL."); - - inventorystack_t *stack = inventory->storage; - inventorystack_t *end = stack + inventory->storageSize; - do { - // End of inventory, item not present. - if(stack->item == ITEM_ID_NULL) break; - - // Not matching stack. - if(stack->item != item) continue; - - // Match found, return quantity. - return stack->quantity; - } while(++stack < end); - - return 0; -} - -bool_t inventoryIsFull(const inventory_t *inventory) { - assertNotNull(inventory, "Inventory pointer is NULL."); - assertNotNull(inventory->storage, "Storage pointer is NULL."); - assertTrue(inventory->storageSize > 0, "Storage too small."); - - inventorystack_t *stack = inventory->storage; - inventorystack_t *end = stack + inventory->storageSize; - do { - // Found empty stack, not full. - if(stack->item == ITEM_ID_NULL) return false; - } while(++stack < end); - - return true; -} - -bool_t inventoryItemFull(const inventory_t *inventory, const itemid_t item) { - return inventoryGetCount(inventory, item) == ITEM_STACK_QUANTITY_MAX; -} - -// Sorters -int_t inventorySortById(const void *a, const void *b) { - const inventorystack_t *stackA = (const inventorystack_t*)a; - const inventorystack_t *stackB = (const inventorystack_t*)b; - if(stackA->item < stackB->item) return -1; - if(stackA->item > stackB->item) return 1; - return 0; -} - -int_t inventorySortByIdReverse(const void *a, const void *b) { - const inventorystack_t *stackA = (const inventorystack_t*)a; - const inventorystack_t *stackB = (const inventorystack_t*)b; - if(stackA->item < stackB->item) return 1; - if(stackA->item > stackB->item) return -1; - return 0; -} - -int_t inventorySortByType(const void *a, const void *b) { - const inventorystack_t *stackA = (const inventorystack_t*)a; - const inventorystack_t *stackB = (const inventorystack_t*)b; - const itemtype_t typeA = ITEMS[stackA->item].type; - const itemtype_t typeB = ITEMS[stackB->item].type; - if(typeA < typeB) return -1; - if(typeA > typeB) return 1; - return 0; -} - -int_t inventorySortByTypeReverse(const void *a, const void *b) { - const inventorystack_t *stackA = (const inventorystack_t*)a; - const inventorystack_t *stackB = (const inventorystack_t*)b; - const itemtype_t typeA = ITEMS[stackA->item].type; - const itemtype_t typeB = ITEMS[stackB->item].type; - if(typeA < typeB) return 1; - if(typeA > typeB) return -1; - return 0; -} - -void inventorySort( - inventory_t *inventory, - const inventorysort_t sortBy, - const bool_t reverse -) { - assertNotNull(inventory, "Inventory pointer is NULL."); - assertNotNull(inventory->storage, "Storage pointer is NULL."); - assertTrue(inventory->storageSize > 0, "Storage too small."); - assertTrue(sortBy < INVENTORY_SORT_COUNT, "Invalid sort type."); - - // Get count of used stacks - size_t count = 0; - inventorystack_t *stack = inventory->storage; - inventorystack_t *end = stack + inventory->storageSize; - do { - if(stack->item == ITEM_ID_NULL) break; - count++; - } while(++stack < end); - - if(count == 0) return; // Nothing to sort - - // Comparator - sortcompare_t comparator = NULL; - switch(sortBy) { - case INVENTORY_SORT_BY_ID: { - comparator = reverse ? inventorySortByIdReverse : inventorySortById; - break; - }; - - case INVENTORY_SORT_BY_TYPE: { - comparator = reverse ? inventorySortByTypeReverse : inventorySortByType; - break; - }; - - default: - assertUnreachable("Invalid sort type."); - break; - } - - assertNotNull(comparator, "Comparator function is NULL."); - - sort((void*)inventory->storage, count, sizeof(inventorystack_t), comparator); -} \ No newline at end of file diff --git a/src/dusk/rpg/item/inventory.h b/src/dusk/rpg/item/inventory.h deleted file mode 100644 index ba559dfe..00000000 --- a/src/dusk/rpg/item/inventory.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/item/item.h" - -#define ITEM_STACK_QUANTITY_MAX 99 - -typedef enum { - INVENTORY_SORT_BY_ID, - INVENTORY_SORT_BY_TYPE, - - INVENTORY_SORT_COUNT -} inventorysort_t; - -typedef struct { - itemid_t item; - uint8_t quantity; -} inventorystack_t; - -typedef struct { - inventorystack_t *storage; - uint8_t storageSize; -} inventory_t; - -/** - * Initializes an inventory. - * - * @param inventory The inventory to initialize. - * @param storage The storage array for the inventory. - * @param storageSize The size of the storage array. - */ -void inventoryInit( - inventory_t* inventory, - inventorystack_t* storage, - uint8_t storageSize -); - -/** - * Checks if a specific item exists in the inventory (and has quantity > 0). - * - * @param inventory The inventory to check. - * @param item The item ID to check. - * @return true if the item exists, false otherwise. - */ -bool_t inventoryItemExists(const inventory_t *inventory, const itemid_t item); - -/** - * Sets the quantity of a specific item in the inventory. - * - * @param inventory The inventory to modify. - * @param item The item ID to set. - * @param quantity The quantity to set. - */ -void inventorySet( - inventory_t *inventory, - const itemid_t item, - const uint8_t quantity -); - -/** - * Adds a specific quantity of an item to the inventory. - * - * @param inventory The inventory to modify. - * @param item The item ID to add. - * @param quantity The quantity to add. - */ -void inventoryAdd( - inventory_t *inventory, - const itemid_t item, - const uint8_t quantity -); - -/** - * Removes an item from the inventory. - * - * @param inventory The inventory to modify. - * @param item The item ID to remove. - */ -void inventoryRemove(inventory_t *inventory, const itemid_t item); - -/** - * Gets the count of a specific item in the inventory. - * - * @param inventory The inventory to check. - * @param item The item ID to check. - * @return The count of the item in the inventory. - */ -uint8_t inventoryGetCount(const inventory_t *inventory, const itemid_t item); - -/** - * Checks if the inventory is full. - * - * @param inventory The inventory to check. - * @return true if full, false otherwise. - */ -bool_t inventoryIsFull(const inventory_t *inventory); - -/** - * Checks if a specific item stack is full in the inventory. - * - * @param inventory The inventory to check. - * @param item The item ID to check. - * @return true if the item stack is full, false otherwise. - */ -bool_t inventoryItemFull(const inventory_t *inventory, const itemid_t item); - -/** - * Sorts the inventory based on the specified criteria. - * - * @param inventory The inventory to sort. - * @param sortBy The sorting criteria. - * @param reverse Whether to sort in reverse order. - */ -void inventorySort( - inventory_t *inventory, - const inventorysort_t sortBy, - const bool_t reverse -); \ No newline at end of file diff --git a/src/dusk/rpg/item/item.c b/src/dusk/rpg/item/item.c deleted file mode 100644 index d80a6b67..00000000 --- a/src/dusk/rpg/item/item.c +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "item.h" -#include "assert/assert.h" -#include "locale/localemanager.h" -#include "asset/loader/locale/assetlocaleloader.h" - -errorret_t itemGetName( - const itemid_t item, - char_t *buffer, - const size_t bufferSize -) { - assertTrue(item > ITEM_ID_NULL, "Item ID must not be null"); - assertTrue(item < ITEM_ID_COUNT, "Item ID out of range"); - - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - ITEMS[item].name, - 0, - buffer, - bufferSize - )); - - errorOk(); -} diff --git a/src/dusk/rpg/item/item.h b/src/dusk/rpg/item/item.h deleted file mode 100644 index 1c1beda5..00000000 --- a/src/dusk/rpg/item/item.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "rpg/item/itemdef.h" - -/** - * Gets the localized display name for an item. - * - * @param item The item ID to look up. Must not be ITEM_ID_NULL. - * @param buffer Buffer to write the localized name into. - * @param bufferSize Size of the buffer. - * @return Any error that occurs. - */ -errorret_t itemGetName( - const itemid_t item, - char_t *buffer, - const size_t bufferSize -); diff --git a/src/dusk/rpg/item/item.json b/src/dusk/rpg/item/item.json deleted file mode 100644 index 35aceb4d..00000000 --- a/src/dusk/rpg/item/item.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { "id": "POTION", "type": "MEDICINE", "weight": 1.0, "name": "potion" }, - { "id": "POTATO", "type": "FOOD", "weight": 0.5, "name": "potato" }, - { "id": "APPLE", "type": "FOOD", "weight": 0.3, "name": "apple" } -] diff --git a/src/dusk/rpg/item/itemgive.c b/src/dusk/rpg/item/itemgive.c deleted file mode 100644 index c7416dc2..00000000 --- a/src/dusk/rpg/item/itemgive.c +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "itemgive.h" -#include "rpg/item/backpack.h" -#include "rpg/item/item.h" -#include "ui/rpg/textbox/uitextboxmain.h" -#include "util/string.h" -#include "error/error.h" - -#define ITEM_GIVE_NAME_MAX_CHARS 32 - -void itemGive(const itemid_t item, const uint8_t quantity) { - backpackAdd(item, quantity); - - char_t name[ITEM_GIVE_NAME_MAX_CHARS]; - errorCatch(itemGetName(item, name, ITEM_GIVE_NAME_MAX_CHARS)); - - char_t msg[ITEM_GIVE_MESSAGE_MAX_CHARS]; - stringFormat( - msg, - ITEM_GIVE_MESSAGE_MAX_CHARS - 1, - "Received %s x%u", - name, - (uint32_t)quantity - ); - uiTextboxMainSetText(msg); -} diff --git a/src/dusk/rpg/item/itemgive.h b/src/dusk/rpg/item/itemgive.h deleted file mode 100644 index 5fa02b91..00000000 --- a/src/dusk/rpg/item/itemgive.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/item/item.h" - -#define ITEM_GIVE_MESSAGE_MAX_CHARS 256 - -/** - * Adds a quantity of an item to the player's backpack and shows a - * "Received x" message in the main textbox. - * - * @param item The item ID to give. - * @param quantity The quantity to give. - */ -void itemGive(const itemid_t item, const uint8_t quantity); diff --git a/src/dusk/rpg/overworld/CMakeLists.txt b/src/dusk/rpg/overworld/CMakeLists.txt deleted file mode 100644 index a6c4f934..00000000 --- a/src/dusk/rpg/overworld/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - chunk.c - map.c - maparea.c - worldpos.c - tile.c - tileshape.c -) - diff --git a/src/dusk/rpg/overworld/chunk.c b/src/dusk/rpg/overworld/chunk.c deleted file mode 100644 index 18a5316e..00000000 --- a/src/dusk/rpg/overworld/chunk.c +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "chunk.h" - -uint32_t chunkGetTileIndex(const chunkpos_t position) { - return (position.y * CHUNK_WIDTH) + position.x; -} - -bool_t chunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b) { - return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); -} \ No newline at end of file diff --git a/src/dusk/rpg/overworld/chunk.h b/src/dusk/rpg/overworld/chunk.h deleted file mode 100644 index 38cc9abe..00000000 --- a/src/dusk/rpg/overworld/chunk.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/overworld/tile.h" -#include "worldpos.h" - -#define CHUNK_MESH_COUNT_MAX 10 -#define CHUNK_MESH_NAME_MAX 64 -#define CHUNK_ENTITY_COUNT_MAX 10 - -typedef struct assetentry_s assetentry_t; - -typedef struct chunk_s { - chunkpos_t position; - tile_t tiles[CHUNK_TILE_COUNT]; - - assetentry_t *dcfEntry; - - uint8_t meshCount; - char_t modelNames[CHUNK_MESH_COUNT_MAX][CHUNK_MESH_NAME_MAX]; - vec3 meshOffsets[CHUNK_MESH_COUNT_MAX]; - mat4 meshModels[CHUNK_MESH_COUNT_MAX]; - assetentry_t *modelEntries[CHUNK_MESH_COUNT_MAX]; - - uint8_t entities[CHUNK_ENTITY_COUNT_MAX]; -} chunk_t; - -/** - * Gets the tile index for a tile position within a chunk. - * - * @param position The position within the chunk. - * @return The tile index within the chunk. - */ -uint32_t chunkGetTileIndex(const chunkpos_t position); - -/** - * Checks if two chunk positions are equal. - * - * @param a The first chunk position. - * @param b The second chunk position. - * @return true if equal, false otherwise. - */ -bool_t chunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b); diff --git a/src/dusk/rpg/overworld/map.c b/src/dusk/rpg/overworld/map.c deleted file mode 100644 index 20ad8de1..00000000 --- a/src/dusk/rpg/overworld/map.c +++ /dev/null @@ -1,438 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "map.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "asset/asset.h" -#include "asset/loader/assetloader.h" -#include "console/console.h" -#include "event/event.h" -#include "util/string.h" -#include "rpg/entity/global/entityglobal.h" - -map_t MAP; - -errorret_t mapInit() { - memoryZero(&MAP, sizeof(map_t)); - MAP.loaded = true; - - chunkindex_t i = 0; - for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) { - for(chunkunit_t y = 0; y < MAP_CHUNK_HEIGHT; y++) { - for(chunkunit_t x = 0; x < MAP_CHUNK_WIDTH; x++) { - chunk_t *chunk = &MAP.chunks[i++]; - chunk->position = (chunkpos_t){ - (chunkunit_t)x, (chunkunit_t)y, (chunkunit_t)z - }; - errorChain(mapChunkLoad(chunk)); - } - } - } - - mapRebuildChunkOrder(); - errorOk(); -} - -bool_t mapIsLoaded() { - return MAP.loaded; -} - -errorret_t mapPositionSet(const chunkpos_t newPos) { - if(!mapIsLoaded()) errorThrow("No map loaded"); - if(chunkPositionIsEqual(newPos, MAP.chunkPosition)) errorOk(); - - // Separate loaded chunks into "keep" and "free" buckets. - chunkindex_t chunksFreed[MAP_CHUNK_COUNT]; - uint32_t freedCount = 0; - - // Use a boolean grid so the inner load loop can check O(1). - bool_t posLoaded[MAP_CHUNK_WIDTH][MAP_CHUNK_HEIGHT][MAP_CHUNK_DEPTH]; - memoryZero(posLoaded, sizeof(posLoaded)); - - for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { - chunk_t *chunk = &MAP.chunks[i]; - chunkunit_t rx = chunk->position.x - newPos.x; - chunkunit_t ry = chunk->position.y - newPos.y; - chunkunit_t rz = chunk->position.z - newPos.z; - if( - rx >= 0 && rx < MAP_CHUNK_WIDTH && - ry >= 0 && ry < MAP_CHUNK_HEIGHT && - rz >= 0 && rz < MAP_CHUNK_DEPTH - ) { - posLoaded[rx][ry][rz] = true; - } else { - mapChunkUnload(chunk); - chunksFreed[freedCount++] = i; - } - } - - for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) { - for(chunkunit_t y = 0; y < MAP_CHUNK_HEIGHT; y++) { - for(chunkunit_t x = 0; x < MAP_CHUNK_WIDTH; x++) { - if(posLoaded[x][y][z]) continue; - assertTrue(freedCount > 0, "No free chunk slot available."); - chunk_t *chunk = &MAP.chunks[chunksFreed[--freedCount]]; - chunk->position = (chunkpos_t){ - newPos.x + (chunkunit_t)x, - newPos.y + (chunkunit_t)y, - newPos.z + (chunkunit_t)z - }; - errorChain(mapChunkLoad(chunk)); - } - } - } - - MAP.chunkPosition = newPos; - mapRebuildChunkOrder(); - errorOk(); -} - -errorret_t mapUpdate() { - errorOk(); -} - -errorret_t mapDispose() { - for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { - mapChunkUnload(&MAP.chunks[i]); - } - errorOk(); -} - -void mapChunkUnload(chunk_t *chunk) { - mapChunkLoadQueueRemove(chunk); - if(MAP.loadingChunk == chunk) MAP.loadingChunk = NULL; - - for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { - if(chunk->entities[i] == 0xFF) continue; - entity_t *entity = &ENTITIES[chunk->entities[i]]; - if(!entityCanUnload(entity)) { - entitySetChunk(entity, 0xFF); - } else { - entity->type = ENTITY_TYPE_NULL; - } - } - - memorySet(chunk->entities, 0xFF, sizeof(chunk->entities)); - - if(chunk->dcfEntry != NULL) { - eventUnsubscribe(&chunk->dcfEntry->onLoaded, mapChunkLoaded); - eventUnsubscribe(&chunk->dcfEntry->onError, mapChunkLoadError); - assetUnlockEntry(chunk->dcfEntry); - chunk->dcfEntry = NULL; - } - - // modelEntries are borrowed pointers, not independently locked - the - // chunk asset entry (released above) is what actually holds the ref on - // each model, so nothing to unlock here, just drop our own copies. - for(uint8_t m = 0; m < chunk->meshCount; m++) { - chunk->modelEntries[m] = NULL; - } - chunk->meshCount = 0; -} - -errorret_t mapChunkLoad(chunk_t *chunk) { - if(!mapIsLoaded()) errorThrow("No map loaded"); - - mapChunkLoadQueueRemove(chunk); - if(MAP.loadingChunk == chunk) MAP.loadingChunk = NULL; - - if(chunk->dcfEntry != NULL) { - eventUnsubscribe(&chunk->dcfEntry->onLoaded, mapChunkLoaded); - eventUnsubscribe(&chunk->dcfEntry->onError, mapChunkLoadError); - assetUnlockEntry(chunk->dcfEntry); - chunk->dcfEntry = NULL; - } - - memorySet(chunk->entities, 0xFF, sizeof(chunk->entities)); - chunk->meshCount = 0; - - char_t name[64]; - stringFormat( - name, sizeof(name), - "chunks/%d_%d_%d.dcf", - (int32_t)chunk->position.x, - (int32_t)chunk->position.y, - (int32_t)chunk->position.z - ); - - if(!assetFileExists(name)) { - for(uint32_t i = 0; i < CHUNK_TILE_COUNT; i++) { - // chunk->tiles[i] = (tile_t){ .shape = TILE_SHAPE_GROUND, .z = 0 }; - chunk->tiles[i] = (tile_t){ .shape = TILE_SHAPE_GROUND }; - } - errorOk(); - } - - assertTrue( - MAP.loadQueueCount < MAP_CHUNK_COUNT, - "Chunk load queue overflow" - ); - MAP.loadQueue[MAP.loadQueueCount++] = chunk; - mapChunkLoadNext(); - errorOk(); -} - -void mapChunkLoadNext() { - if(MAP.loadingChunk != NULL) return; - if(MAP.loadQueueCount == 0) return; - - chunk_t *chunk = MAP.loadQueue[0]; - for(uint32_t i = 1; i < MAP.loadQueueCount; i++) { - MAP.loadQueue[i - 1] = MAP.loadQueue[i]; - } - MAP.loadQueueCount--; - MAP.loadingChunk = chunk; - - char_t name[64]; - stringFormat( - name, sizeof(name), - "chunks/%d_%d_%d.dcf", - (int32_t)chunk->position.x, - (int32_t)chunk->position.y, - (int32_t)chunk->position.z - ); - - assetentry_t *entry = assetLock(name, ASSET_LOADER_TYPE_CHUNK, NULL); - assertNotNull(entry, "Failed to get chunk asset entry"); - chunk->dcfEntry = entry; - - // The entry may already be resident from an earlier load that hasn't been - // reaped yet - in that case onLoaded/onError already fired once and never - // will again, so handle the terminal state directly instead of waiting on - // a subscription that would never trigger. - if(entry->state == ASSET_ENTRY_STATE_LOADED) { - mapChunkLoaded(entry, chunk); - return; - } - if(entry->state == ASSET_ENTRY_STATE_ERROR) { - mapChunkLoadError(entry, chunk); - return; - } - - eventSubscribe(&entry->onLoaded, mapChunkLoaded, chunk); - eventSubscribe(&entry->onError, mapChunkLoadError, chunk); -} - -void mapChunkLoadQueueRemove(chunk_t *chunk) { - for(uint32_t i = 0; i < MAP.loadQueueCount; i++) { - if(MAP.loadQueue[i] != chunk) continue; - for(uint32_t j = i + 1; j < MAP.loadQueueCount; j++) { - MAP.loadQueue[j - 1] = MAP.loadQueue[j]; - } - MAP.loadQueueCount--; - return; - } -} - - -chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) { - if(!mapIsLoaded()) return -1; - - chunkpos_t relPos = { - position.x - MAP.chunkPosition.x, - position.y - MAP.chunkPosition.y, - position.z - MAP.chunkPosition.z - }; - - if( - relPos.x < 0 || relPos.y < 0 || relPos.z < 0 || - relPos.x >= MAP_CHUNK_WIDTH || - relPos.y >= MAP_CHUNK_HEIGHT || - relPos.z >= MAP_CHUNK_DEPTH - ) { - return -1; - } - - return chunkPosToIndex(&relPos); -} - -chunk_t *mapGetChunk(const uint8_t index) { - if(index >= MAP_CHUNK_COUNT) return NULL; - if(!mapIsLoaded()) return NULL; - return MAP.chunkOrder[index]; -} - -tile_t mapGetTile(const worldpos_t position) { - if(!mapIsLoaded()) return TILE_NULL; - - chunkpos_t chunkPos; - worldPosToChunkPos(&position, &chunkPos); - chunkindex_t chunkIndex = mapGetChunkIndexAt(chunkPos); - if(chunkIndex == -1) return TILE_NULL; - - chunk_t *chunk = mapGetChunk(chunkIndex); - assertNotNull(chunk, "Chunk pointer cannot be NULL"); - chunktileindex_t tileIndex = worldPosToChunkTileIndex(&position); - tile_t tile = chunk->tiles[tileIndex]; - if(tile.z != worldPosToChunkLocalZ(&position)) return TILE_NULL; - return tile; -} - -bool_t mapGetWalkableZNear( - const worldunit_t x, - const worldunit_t y, - const worldunit_t nearZ, - worldunit_t *outZ -) { - assertNotNull(outZ, "Output Z pointer cannot be NULL"); - - const worldunit_t candidates[] = { - nearZ, (worldunit_t)(nearZ + 1), (worldunit_t)(nearZ - 1) - }; - for(uint8_t i = 0; i < 3; i++) { - const worldpos_t pos = { x, y, candidates[i] }; - if(!tileShapeIsWalkable(mapGetTile(pos).shape)) continue; - *outZ = candidates[i]; - return true; - } - - return false; -} - -entity_t * mapSpawnEntity( - const entityglobalid_t globalId, - const worldpos_t position -) { - assertTrue( - globalId > ENTITY_GLOBAL_ID_START, - "mapSpawnEntity requires a global ID greater than ENTITY_GLOBAL_ID_START" - ); - assertTrue( - globalId < ENTITY_GLOBAL_LIST_COUNT, - "Global ID is out of range for entity global init callbacks" - ); - - // Already spawned? Reuse the existing entity instead of making a - // duplicate - two entities must never share a global ID. - entity_t *existing = entityGetByGlobalId(globalId); - if(existing != NULL) return existing; - - // See if there is a callback for this entity first. - const entityglobaldef_t *def = &ENTITY_GLOBAL_LIST[globalId]; - assertNotNull(def, "No global entity definition for this ID"); - assertNotNull(def->callback, "No callback registered for this global ID"); - - // Get available entity. - uint8_t index = entityGetAvailable(); - assertTrue(index != 0xFF, "No available entity slots for mapSpawnEntity"); - - // Get the pointer and do the init. - entity_t *entity = &ENTITIES[index]; - entityInit(entity, def->type); - entity->globalId = globalId; - entityPositionSet(entity, position);// Also assigns the entity's chunk. - - // Invoke the callback to initialize the entity. - entityglobalcreate_t create = { - .entity = entity, - .position = position - }; - def->callback(&create); - return entity; -} - -void mapRebuildChunkOrder() { - memoryZero(MAP.chunkOrder, sizeof(MAP.chunkOrder)); - for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { - chunk_t *chunk = &MAP.chunks[i]; - const chunkpos_t rel = { - chunk->position.x - MAP.chunkPosition.x, - chunk->position.y - MAP.chunkPosition.y, - chunk->position.z - MAP.chunkPosition.z - }; - if( - rel.x < 0 || rel.x >= MAP_CHUNK_WIDTH || - rel.y < 0 || rel.y >= MAP_CHUNK_HEIGHT || - rel.z < 0 || rel.z >= MAP_CHUNK_DEPTH - ) continue; - MAP.chunkOrder[chunkPosToIndex(&rel)] = chunk; - } -} - -void mapChunkLoadError(void *params, void *user) { - assertNotNull(params, "mapChunkLoadError: params cannot be NULL"); - assertNotNull(user, "mapChunkLoadError: user cannot be NULL"); - assetentry_t *entry = (assetentry_t *)params; - chunk_t *chunk = (chunk_t *)user; - if(chunk->dcfEntry != entry) return; - consolePrint( - "Chunk load error: %d %d %d", - (int32_t)chunk->position.x, - (int32_t)chunk->position.y, - (int32_t)chunk->position.z - ); - eventUnsubscribe(&entry->onLoaded, mapChunkLoaded); - eventUnsubscribe(&entry->onError, mapChunkLoadError); - assetUnlockEntry(chunk->dcfEntry); - chunk->dcfEntry = NULL; - memorySet(chunk->tiles, 0x00, sizeof(chunk->tiles)); - - if(MAP.loadingChunk == chunk) MAP.loadingChunk = NULL; - mapChunkLoadNext(); -} - -void mapChunkLoaded(void *params, void *user) { - assertNotNull(params, "mapChunkLoaded: params cannot be NULL"); - assertNotNull(user, "mapChunkLoaded: user cannot be NULL"); - assetentry_t *entry = (assetentry_t *)params; - chunk_t *chunk = (chunk_t *)user; - if(chunk->dcfEntry != entry) return; - // consolePrint( - // "Chunk loaded: %d %d %d", - // (int32_t)chunk->position.x, - // (int32_t)chunk->position.y, - // (int32_t)chunk->position.z - // ); - uint8_t meshCount = entry->data.chunk.meshCount; - memoryCopy( - chunk->tiles, - entry->data.chunk.tiles, - sizeof(chunk->tiles) - ); - worldpos_t wp; - chunkPosToWorldPos(&chunk->position, &wp); - vec3 wpf = { - (float_t)wp.x, (float_t)wp.y, (float_t)wp.z * WORLD_LAYER_HEIGHT - }; - for(uint8_t m = 0; m < meshCount; m++) { - stringCopy( - chunk->modelNames[m], - entry->data.chunk.modelNames[m], - CHUNK_MESH_NAME_MAX - ); - glm_vec3_copy( - entry->data.chunk.meshOffsets[m], - chunk->meshOffsets[m] - ); - vec3 scaledOffset = { - chunk->meshOffsets[m][0], - chunk->meshOffsets[m][1], - chunk->meshOffsets[m][2] * WORLD_LAYER_HEIGHT - }; - vec3 pos; - glm_vec3_add(wpf, scaledOffset, pos); - glm_translate_make(chunk->meshModels[m], pos); - // Borrow the pointer rather than stealing it - the chunk asset entry - // keeps its own lock on each model (taken once while it loaded) and we - // keep the chunk asset entry itself locked (see below), so the models - // stay valid for as long as this chunk_t is using them. The entry may - // now be reused by a later mapChunkLoad for a different chunk_t once we - // eventually unlock it in mapChunkUnload, at which point its - // modelEntries must still be intact for that next reuse to copy from. - chunk->modelEntries[m] = entry->data.chunk.modelEntries[m]; - } - eventUnsubscribe(&entry->onLoaded, mapChunkLoaded); - eventUnsubscribe(&entry->onError, mapChunkLoadError); - // Deliberately keep chunk->dcfEntry locked and set - it is what keeps the - // chunk asset entry (and therefore its model locks) alive for as long as - // this chunk_t is displaying it. Released in mapChunkUnload instead. - chunk->meshCount = meshCount; - - if(MAP.loadingChunk == chunk) MAP.loadingChunk = NULL; - mapChunkLoadNext(); -} diff --git a/src/dusk/rpg/overworld/map.h b/src/dusk/rpg/overworld/map.h deleted file mode 100644 index f8b09bf8..00000000 --- a/src/dusk/rpg/overworld/map.h +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "rpg/overworld/chunk.h" -#include "rpg/entity/entity.h" - -#define MAP_FILE_PATH_MAX 128 - -typedef struct map_s { - bool_t loaded; - - chunk_t chunks[MAP_CHUNK_COUNT]; - chunk_t *chunkOrder[MAP_CHUNK_COUNT]; - chunkpos_t chunkPosition; - - // Only one chunk may be mid-load (asset locked & awaiting onLoaded/ - // onError) at any given time - everything else waits here in FIFO order. - chunk_t *loadQueue[MAP_CHUNK_COUNT]; - uint32_t loadQueueCount; - chunk_t *loadingChunk; -} map_t; - -extern map_t MAP; - -/** - * Initializes the map. - * - * @return An error code. - */ -errorret_t mapInit(); - -/** - * Checks if a map is loaded. - * - * @return true if a map is loaded, false otherwise. - */ -bool_t mapIsLoaded(); - -/** - * Updates the map. - * - * @return An error code. - */ -errorret_t mapUpdate(); - -/** - * Disposes of the map. - * - * @return An error code. - */ -errorret_t mapDispose(); - -/** - * Sets the map position and updates chunks accordingly. - * - * @param newPos The new chunk position. - * @return An error code. - */ -errorret_t mapPositionSet(const chunkpos_t newPos); - -/** - * Unloads a chunk. - * - * @param chunk The chunk to unload. - */ -void mapChunkUnload(chunk_t* chunk); - -/** - * Loads a chunk. Starts async loading without blocking. - * - * @param chunk The chunk to load. - * @return An error code. - */ -errorret_t mapChunkLoad(chunk_t* chunk); - -/** - * Starts loading the next queued chunk, if no chunk is currently mid-load. - * Called after mapChunkLoad enqueues a chunk, and again after the - * currently-loading chunk finishes (or is unloaded) to advance the queue. - */ -void mapChunkLoadNext(); - -/** - * Removes a chunk from the load queue if present. Used when a chunk is - * re-queued or unloaded before its turn to load has come up. - * - * @param chunk The chunk to remove from the load queue. - */ -void mapChunkLoadQueueRemove(chunk_t *chunk); - -/** - * Callback invoked when a chunk DCF asset fails to load. Fills the - * chunk tiles with TILE_SHAPE_GROUND as a fallback. - * Always invoked on the main thread. - * - * @param params The failed assetentry_t. - * @param user The chunk_t that owns the entry. - */ -void mapChunkLoadError(void *params, void *user); - -/** - * Callback invoked when a chunk DCF asset finishes loading. - * Always invoked on the main thread. - * - * @param params The loaded assetentry_t. - * @param user The chunk_t that owns the entry. - */ -void mapChunkLoaded(void *params, void *user); - -/** - * Rebuilds chunkOrder from the loaded chunks that fall within the - * current render window. Called whenever chunkPosition changes. - */ -void mapRebuildChunkOrder(); - -/** - * Gets the index of a chunk, within the world, at the given position. - * - * @param position The chunk position. - * @return The index of the chunk, or -1 if out of bounds. - */ -chunkindex_t mapGetChunkIndexAt(const chunkpos_t position); - -/** - * Gets a chunk by its index. - * - * @param chunkIndex The index of the chunk. - * @return A pointer to the chunk. - */ -chunk_t * mapGetChunk(const uint8_t chunkIndex); - -/** - * Gets the tile at the given world position. - * - * @param position The world position. - * @return The tile at that position, or TILE_NULL if the chunk is unloaded. - */ -tile_t mapGetTile(const worldpos_t position); - -/** - * Finds the closest walkable Z layer to nearZ at the given X/Y. Checks - * nearZ first, then nearZ + 1, then nearZ - 1, since ramps only ever - * change height by one Z layer between adjacent tiles. - * - * @param x The world X coordinate to check. - * @param y The world Y coordinate to check. - * @param nearZ The reference Z layer to search outward from. - * @param outZ Output pointer, set to the resolved Z layer on success. - * @return true if a walkable tile was found, false otherwise. - */ -bool_t mapGetWalkableZNear( - const worldunit_t x, - const worldunit_t y, - const worldunit_t nearZ, - worldunit_t *outZ -); - -/** - * Spawns a global (persistent) entity into the world at the given position. - * Asserts globalId is greater than ENTITY_GLOBAL_ID_START - use entityInit - * directly for ephemeral, non-global entities. - * - * @param globalId The global entity ID to assign, must be greater than - * ENTITY_GLOBAL_ID_START. - * @param position The world position to spawn the entity at. - * @return Pointer to the spawned entity. - */ -entity_t * mapSpawnEntity( - const entityglobalid_t globalId, - const worldpos_t position -); \ No newline at end of file diff --git a/src/dusk/rpg/overworld/maparea.c b/src/dusk/rpg/overworld/maparea.c deleted file mode 100644 index 95efe628..00000000 --- a/src/dusk/rpg/overworld/maparea.c +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "maparea.h" -#include "assert/assert.h" -#include "util/math.h" -#include "util/memory.h" -#include "rpg/overworld/map.h" - -maparea_t MAP_AREAS[MAP_AREA_COUNT_MAX]; - -void mapAreaInit( - maparea_t *area, - const worldpos_t min, - const worldpos_t max, - const mapareacallback_t callback, - const uint8_t notify, - const uint8_t trigger -) { - assertNotNull(area, "Map area pointer cannot be NULL"); - assertNotNull(callback, "Map area callback cannot be NULL"); - - area->min.x = mathMin(min.x, max.x); - area->min.y = mathMin(min.y, max.y); - area->min.z = mathMin(min.z, max.z); - - area->max.x = mathMax(min.x, max.x); - area->max.y = mathMax(min.y, max.y); - area->max.z = mathMax(min.z, max.z); - - area->callback = callback; - area->notify = notify; - area->trigger = trigger; - area->triggerCount = 0; - - memorySet(area->entities, 0, sizeof(area->entities)); -} - -bool_t mapAreaIsInside(const maparea_t *area, const worldpos_t position) { - assertNotNull(area, "Map area pointer cannot be NULL"); - - return ( - position.x >= area->min.x && position.x <= area->max.x && - position.y >= area->min.y && position.y <= area->max.y && - position.z >= area->min.z && position.z <= area->max.z - ); -} - -bool_t mapAreaIsChunkOverlappingOrInside( - const maparea_t *area, - const chunk_t *chunk -) { - assertNotNull(area, "Map area pointer cannot be NULL"); - assertNotNull(chunk, "Chunk pointer cannot be NULL"); - - worldpos_t chunkMin, chunkMax; - chunkPosToWorldPos(&chunk->position, &chunkMin); - chunkMax.x = chunkMin.x + CHUNK_WIDTH - 1; - chunkMax.y = chunkMin.y + CHUNK_HEIGHT - 1; - chunkMax.z = chunkMin.z + CHUNK_DEPTH - 1; - - return ( - chunkMin.x <= area->max.x && area->min.x <= chunkMax.x && - chunkMin.y <= area->max.y && area->min.y <= chunkMax.y && - chunkMin.z <= area->max.z && area->min.z <= chunkMax.z - ); -} - -bool_t mapAreaCanUnload(const maparea_t *area) { - assertNotNull(area, "Map area pointer cannot be NULL"); - - for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { - if(mapAreaIsChunkOverlappingOrInside(area, &MAP.chunks[i])) return false; - } - - return true; -} - -bool_t mapAreaShouldNotify(const maparea_t *area, const entity_t *entity) { - assertNotNull(area, "Map area pointer cannot be NULL"); - assertNotNull(entity, "Entity pointer cannot be NULL"); - - switch(entity->type) { - case ENTITY_TYPE_PLAYER: - return (area->notify & MAP_AREA_NOTIFY_PLAYER) != 0; - - case ENTITY_TYPE_NPC: - return (area->notify & MAP_AREA_NOTIFY_NPC) != 0; - - default: - return false; - } -} - -uint8_t mapAreaAdd( - const worldpos_t min, - const worldpos_t max, - const mapareacallback_t callback, - const uint8_t notify, - const uint8_t trigger -) { - for(uint8_t i = 0; i < MAP_AREA_COUNT_MAX; i++) { - if(MAP_AREAS[i].callback != NULL) continue; - mapAreaInit(&MAP_AREAS[i], min, max, callback, notify, trigger); - return i; - } - - assertUnreachable("No available map area slots"); - return 0xFF; -} - -void mapAreaRemove(const uint8_t id) { - assertTrue(id < MAP_AREA_COUNT_MAX, "Map area ID is out of range"); - MAP_AREAS[id].callback = NULL; -} - -void mapAreaCheckEntity(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); - - for(uint8_t i = 0; i < MAP_AREA_COUNT_MAX; i++) { - maparea_t *area = &MAP_AREAS[i]; - if(area->callback == NULL) continue; - if(!mapAreaShouldNotify(area, entity)) continue; - - bool_t wasInside = area->entities[entity->id] != 0; - bool_t isInside = mapAreaIsInside(area, entity->position); - uint8_t trigger = 0; - - if(isInside && !wasInside) { - area->entities[entity->id] = 1; - trigger = MAP_TRIGGER_ENTER; - } else if(isInside && wasInside) { - trigger = MAP_TRIGGER_STEP; - } else if(!isInside && wasInside) { - area->entities[entity->id] = 0; - trigger = MAP_TRIGGER_EXIT; - } - - if(trigger == 0 || !(area->trigger & trigger)) continue; - area->triggerCount++; - area->callback(entity, trigger); - } -} - -void mapAreaNoopCallback(entity_t *entity, const uint8_t trigger) { -} diff --git a/src/dusk/rpg/overworld/maparea.h b/src/dusk/rpg/overworld/maparea.h deleted file mode 100644 index 836f712a..00000000 --- a/src/dusk/rpg/overworld/maparea.h +++ /dev/null @@ -1,161 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "worldpos.h" -#include "rpg/entity/entity.h" - -typedef struct chunk_s chunk_t; -typedef struct maparea_s maparea_t; - -#define MAP_AREA_COUNT_MAX 32 - -#define MAP_AREA_NOTIFY_PLAYER (1 << 0) -#define MAP_AREA_NOTIFY_NPC (1 << 1) -#define MAP_AREA_NOTIFY_ALL (MAP_AREA_NOTIFY_PLAYER | MAP_AREA_NOTIFY_NPC) - -#define MAP_TRIGGER_STEP (1 << 0) -#define MAP_TRIGGER_ENTER (1 << 1) -#define MAP_TRIGGER_EXIT (1 << 2) -#define MAP_TRIGGER_ALL (MAP_TRIGGER_STEP | MAP_TRIGGER_ENTER | MAP_TRIGGER_EXIT) - -/** - * Callback invoked for a map area. - * - * @param entity Pointer to the entity associated with the callback. - * @param trigger Which MAP_TRIGGER_* condition invoked the callback. - */ -typedef void (*mapareacallback_t)(entity_t *entity, const uint8_t trigger); - -typedef struct maparea_s { - worldpos_t min; - worldpos_t max; - mapareacallback_t callback; - uint8_t notify; - uint8_t trigger; - uint8_t entities[ENTITY_COUNT]; - - // Incremented every time this area's callback is invoked. Lets other - // systems (e.g. cutscenes) detect "has this area fired since I last - // checked" without needing to be the callback themselves. - uint32_t triggerCount; -} maparea_t; - -extern maparea_t MAP_AREAS[MAP_AREA_COUNT_MAX]; - -/** - * Initializes a map area with the given bounds, callback, notify flags - * and trigger flags. - * - * @param area Pointer to the map area to initialize. - * @param min The minimum world position of the area. - * @param max The maximum world position of the area. - * @param callback The callback to invoke for this area. Must not be NULL. - * @param notify Bitwise MAP_AREA_NOTIFY_* flags for which entity types - * should trigger the callback. - * @param trigger Bitwise MAP_TRIGGER_* flags for which conditions should - * invoke the callback. - */ -void mapAreaInit( - maparea_t *area, - const worldpos_t min, - const worldpos_t max, - const mapareacallback_t callback, - const uint8_t notify, - const uint8_t trigger -); - -/** - * Checks whether a world position falls within a map area's bounds - * (inclusive on all axes). - * - * @param area Pointer to the map area to check. - * @param position The world position to check. - * @returns true if the position is inside the area. - */ -bool_t mapAreaIsInside(const maparea_t *area, const worldpos_t position); - -/** - * Checks whether a chunk's full footprint overlaps a map area's bounds, - * rather than just testing the chunk's origin corner. - * - * @param area Pointer to the map area to check. - * @param chunk Pointer to the chunk to check. - * @returns true if the chunk overlaps the area. - */ -bool_t mapAreaIsChunkOverlappingOrInside( - const maparea_t *area, - const chunk_t *chunk -); - -/** - * Checks whether a map area is safe to unload, i.e. no entity currently - * occupies a position within its bounds. - * - * @param area Pointer to the map area to check. - * @returns true if no entity is inside the area. - */ -bool_t mapAreaCanUnload(const maparea_t *area); - -/** - * Checks whether an entity's type is included in a map area's notify flags. - * - * @param area Pointer to the map area to check. - * @param entity Pointer to the entity to check. - * @returns true if the entity's type should trigger this area's callback. - */ -bool_t mapAreaShouldNotify(const maparea_t *area, const entity_t *entity); - -/** - * Adds a map area to the global MAP_AREAS list, in the first free slot. - * A slot is considered free if its callback is NULL. - * - * @param min The minimum world position of the area. - * @param max The maximum world position of the area. - * @param callback The callback to invoke for this area. Must not be NULL. - * @param notify Bitwise MAP_AREA_NOTIFY_* flags for which entity types - * should trigger the callback. - * @param trigger Bitwise MAP_TRIGGER_* flags for which conditions should - * invoke the callback. - * @returns The ID of the newly added map area. - */ -uint8_t mapAreaAdd( - const worldpos_t min, - const worldpos_t max, - const mapareacallback_t callback, - const uint8_t notify, - const uint8_t trigger -); - -/** - * Removes a map area from the global MAP_AREAS list, freeing its slot by - * clearing its callback to NULL. - * - * @param id The ID of the map area to remove. - */ -void mapAreaRemove(const uint8_t id); - -/** - * Checks every active map area against an entity's current position, - * for areas whose notify flags include the entity's type. Invokes the - * area's callback with MAP_TRIGGER_ENTER the frame the entity first - * becomes inside, MAP_TRIGGER_STEP on every subsequent frame it remains - * inside, and MAP_TRIGGER_EXIT the frame it leaves. - * - * @param entity Pointer to the entity to check. - */ -void mapAreaCheckEntity(entity_t *entity); - -/** - * A map area callback that does nothing. Useful for areas whose only - * purpose is to be waited on (see CUTSCENE_MAP_AREA_WAIT), since the - * wait is driven by triggerCount rather than callback logic. - * - * @param entity Pointer to the entity associated with the callback. - * @param trigger Which MAP_TRIGGER_* condition invoked the callback. - */ -void mapAreaNoopCallback(entity_t *entity, const uint8_t trigger); \ No newline at end of file diff --git a/src/dusk/rpg/overworld/tile.c b/src/dusk/rpg/overworld/tile.c deleted file mode 100644 index 34e25cda..00000000 --- a/src/dusk/rpg/overworld/tile.c +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "tile.h" diff --git a/src/dusk/rpg/overworld/tile.h b/src/dusk/rpg/overworld/tile.h deleted file mode 100644 index 82f30850..00000000 --- a/src/dusk/rpg/overworld/tile.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "tileshape.h" - -typedef struct { - tileshape_t shape; - - // Local Z layer (0..CHUNK_DEPTH-1) this tile occupies within its chunk's - // depth slab. Used for entity navigation since chunk_t only stores one - // tile per X/Y column rather than one per X/Y/Z. - uint8_t z; -} tile_t; - -#define TILE_NULL ((tile_t){ .shape = TILE_SHAPE_NULL, .z = 0 }) \ No newline at end of file diff --git a/src/dusk/rpg/overworld/tileshape.c b/src/dusk/rpg/overworld/tileshape.c deleted file mode 100644 index 13124c6f..00000000 --- a/src/dusk/rpg/overworld/tileshape.c +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "tileshape.h" - -bool_t tileShapeIsWalkable(const tileshape_t shape) { - switch(shape) { - case TILE_SHAPE_NULL: - return false; - - default: - return true; - } -} - -bool_t tileShapeIsRamp(const tileshape_t shape) { - switch(shape) { - case TILE_SHAPE_RAMP_NORTH: - case TILE_SHAPE_RAMP_SOUTH: - case TILE_SHAPE_RAMP_EAST: - case TILE_SHAPE_RAMP_WEST: - case TILE_SHAPE_RAMP_NORTHEAST: - case TILE_SHAPE_RAMP_NORTHWEST: - case TILE_SHAPE_RAMP_SOUTHEAST: - case TILE_SHAPE_RAMP_SOUTHWEST: - case TILE_SHAPE_RAMP_NORTHEAST_INNER: - case TILE_SHAPE_RAMP_NORTHWEST_INNER: - case TILE_SHAPE_RAMP_SOUTHEAST_INNER: - case TILE_SHAPE_RAMP_SOUTHWEST_INNER: - return true; - - default: - return false; - } -} \ No newline at end of file diff --git a/src/dusk/rpg/overworld/tileshape.h b/src/dusk/rpg/overworld/tileshape.h deleted file mode 100644 index 1187ac70..00000000 --- a/src/dusk/rpg/overworld/tileshape.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/entity/entitydir.h" - -typedef enum { - TILE_SHAPE_NULL = 0, - - TILE_SHAPE_GROUND = 1, - TILE_SHAPE_RAMP_NORTH = 2, - TILE_SHAPE_RAMP_EAST = 3, - TILE_SHAPE_RAMP_SOUTH = 4, - TILE_SHAPE_RAMP_WEST = 5, - TILE_SHAPE_RAMP_NORTHEAST = 6, - TILE_SHAPE_RAMP_NORTHWEST = 7, - TILE_SHAPE_RAMP_SOUTHEAST = 8, - TILE_SHAPE_RAMP_SOUTHWEST = 9, - TILE_SHAPE_RAMP_NORTHEAST_INNER = 10, - TILE_SHAPE_RAMP_NORTHWEST_INNER = 11, - TILE_SHAPE_RAMP_SOUTHEAST_INNER = 12, - TILE_SHAPE_RAMP_SOUTHWEST_INNER = 13, - - TILE_SHAPE_COUNT -} tileshape_t; - -/** - * Returns whether or not the given tile shape is a ramp. - * - * @param shape The tile shape to check. - * @return bool_t True if ramp, false if not. - */ -bool_t tileShapeIsRamp(const tileshape_t shape); - -/** - * Returns whether or not the given tile shape is walkable. - * - * @param shape The tile shape to check. - * @return bool_t True if walkable, false if not. - */ -bool_t tileShapeIsWalkable(const tileshape_t shape); \ No newline at end of file diff --git a/src/dusk/rpg/overworld/worldpos.c b/src/dusk/rpg/overworld/worldpos.c deleted file mode 100644 index 57bf5118..00000000 --- a/src/dusk/rpg/overworld/worldpos.c +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "worldpos.h" -#include "assert/assert.h" - -bool_t worldPosIsEqual(const worldpos_t a, const worldpos_t b) { - return a.x == b.x && a.y == b.y && a.z == b.z; -} - -void chunkPosToWorldPos(const chunkpos_t* chunkPos, worldpos_t* out) { - assertNotNull(chunkPos, "Chunk position pointer cannot be NULL"); - assertNotNull(out, "Output world position pointer cannot be NULL"); - - out->x = (worldunit_t)(chunkPos->x * CHUNK_WIDTH); - out->y = (worldunit_t)(chunkPos->y * CHUNK_HEIGHT); - out->z = (worldunit_t)(chunkPos->z * CHUNK_DEPTH); -} - -void worldPosToChunkPos(const worldpos_t* worldPos, chunkpos_t* out) { - assertNotNull(worldPos, "World position pointer cannot be NULL"); - assertNotNull(out, "Output chunk position pointer cannot be NULL"); - - if(worldPos->x < 0) { - out->x = (chunkunit_t)((worldPos->x - (CHUNK_WIDTH - 1)) / CHUNK_WIDTH); - } else { - out->x = (chunkunit_t)(worldPos->x / CHUNK_WIDTH); - } - - if(worldPos->y < 0) { - out->y = (chunkunit_t)((worldPos->y - (CHUNK_HEIGHT - 1)) / CHUNK_HEIGHT); - } else { - out->y = (chunkunit_t)(worldPos->y / CHUNK_HEIGHT); - } - - if(worldPos->z < 0) { - out->z = (chunkunit_t)((worldPos->z - (CHUNK_DEPTH - 1)) / CHUNK_DEPTH); - } else { - out->z = (chunkunit_t)(worldPos->z / CHUNK_DEPTH); - } -} - -chunktileindex_t worldPosToChunkTileIndex(const worldpos_t* worldPos) { - assertNotNull(worldPos, "World position pointer cannot be NULL"); - - uint8_t localX, localY; - if(worldPos->x < 0) { - localX = (uint8_t)( - (CHUNK_WIDTH - 1) - ((-worldPos->x - 1) % CHUNK_WIDTH) - ); - } else { - localX = (uint8_t)(worldPos->x % CHUNK_WIDTH); - } - - if(worldPos->y < 0) { - localY = (uint8_t)( - (CHUNK_HEIGHT - 1) - ((-worldPos->y - 1) % CHUNK_HEIGHT) - ); - } else { - localY = (uint8_t)(worldPos->y % CHUNK_HEIGHT); - } - - chunktileindex_t chunkTileIndex = (chunktileindex_t)( - (localY * CHUNK_WIDTH) + localX - ); - assertTrue( - chunkTileIndex < CHUNK_TILE_COUNT, - "Calculated chunk tile index is out of bounds" - ); - return chunkTileIndex; -} - -uint8_t worldPosToChunkLocalZ(const worldpos_t* worldPos) { - assertNotNull(worldPos, "World position pointer cannot be NULL"); - - if(worldPos->z < 0) { - return (uint8_t)( - (CHUNK_DEPTH - 1) - ((-worldPos->z - 1) % CHUNK_DEPTH) - ); - } - return (uint8_t)(worldPos->z % CHUNK_DEPTH); -} - -chunkindex_t chunkPosToIndex(const chunkpos_t* pos) { - assertNotNull(pos, "Chunk position pointer cannot be NULL"); - - chunkindex_t chunkIndex = (chunkindex_t)( - (pos->z * MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT) + - (pos->y * MAP_CHUNK_WIDTH) + - pos->x - ); - - return chunkIndex; -} \ No newline at end of file diff --git a/src/dusk/rpg/overworld/worldpos.h b/src/dusk/rpg/overworld/worldpos.h deleted file mode 100644 index 32758288..00000000 --- a/src/dusk/rpg/overworld/worldpos.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "display/display.h" -#include "util/math.h" - -#define TILE_SIZE_PIXELS 24 - -// World-space Z distance of one Z-layer/story, in render/world-float -// space. A ramp rises this much over a horizontal run of 1 tile-width; -// chosen as 1/sqrt(2) so the ramp's slope, derived from a 45-45-90 -// triangle with hypotenuse 1, matches the length of a flat tile edge. -#define WORLD_LAYER_HEIGHT 0.70710678f - -#define CHUNK_WIDTH 16 -#define CHUNK_HEIGHT 16 -#define CHUNK_DEPTH 8 - -// Chunks store one tile per X/Y column, not one per X/Y/Z - each tile -// records its own local Z layer (see tile_t) instead. -#define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT) - -#define MAP_CHUNK_WIDTH 3 -#define MAP_CHUNK_HEIGHT 3 -#define MAP_CHUNK_DEPTH 4 -#define MAP_CHUNK_COUNT (MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT * MAP_CHUNK_DEPTH) - -#define ENTITY_COUNT 32 - -typedef int16_t worldunit_t; -typedef int16_t chunkunit_t; -typedef int16_t chunkindex_t; -typedef uint32_t chunktileindex_t; - -typedef int32_t worldunits_t; -typedef int32_t chunkunits_t; - -typedef struct worldpos2d_s { - worldunit_t x, y; -} worldpos2d_t; - -typedef struct worldpos_s { - worldunit_t x, y, z; -} worldpos_t; - -typedef struct chunkpos_t { - chunkunit_t x, y, z; -} chunkpos_t; - -/** - * Compares two world positions for equality. - * - * @param a The first world position. - * @param b The second world position. - * @return true if equal, false otherwise. - */ -bool_t worldPosIsEqual(const worldpos_t a, const worldpos_t b); - -/** - * Converts a world position to a chunk position. - * - * @param worldPos The world position. - * @param out The output chunk position. - */ -void chunkPosToWorldPos(const chunkpos_t* chunkPos, worldpos_t* out); - -/** - * Converts a chunk position to a world position. - * - * @param worldPos The world position. - * @param out The output chunk position. - */ -void worldPosToChunkPos(const worldpos_t* worldPos, chunkpos_t* out); - -/** - * Converts a position in world-space to an index inside a chunk that the tile - * resides in. - * - * @param worldPos The world position. - * @return The tile index within the chunk. - */ -chunktileindex_t worldPosToChunkTileIndex(const worldpos_t* worldPos); - -/** - * Converts a world-space Z coordinate to the local Z layer (0..CHUNK_DEPTH-1) - * within the chunk that owns it, for comparison against tile_t.z. - * - * @param worldPos The world position. - * @return The local Z layer within the owning chunk. - */ -uint8_t worldPosToChunkLocalZ(const worldpos_t* worldPos); - -/** - * Converts a chunk position to a world position. - * - * @param worldPos The world position. - * @param out The output chunk position. - */ -chunkindex_t chunkPosToIndex(const chunkpos_t* pos); \ No newline at end of file diff --git a/src/dusk/rpg/rpg.c b/src/dusk/rpg/rpg.c deleted file mode 100644 index 6e04ae7b..00000000 --- a/src/dusk/rpg/rpg.c +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpg.h" -#include "entity/entity.h" -#include "rpg/entity/npc/npcpath.h" -#include "rpg/entity/item/entityitem.h" -#include "rpg/overworld/map.h" -#include "rpg/overworld/maparea.h" -#include "rpg/cutscene/cutscenesystem.h" -#include "rpg/cutscene/scene/testcutscene.h" -#include "rpg/item/backpack.h" -#include "rpg/battle/party.h" -#include "ui/rpg/textbox/uitextboxminilist.h" -#include "time/time.h" -#include "rpgcamera.h" -#include "util/memory.h" -#include "util/string.h" -#include "assert/assert.h" -#include "console/console.h" - -#include "ui/rpg/uiemoji.h" - -void rpgTestAreaCallback(entity_t *entity, const uint8_t trigger) { - consolePrint("rpgTestAreaCallback: trigger=%u", trigger); -} - -errorret_t rpgInit(void) { - memoryZero(ENTITIES, sizeof(ENTITIES)); - memoryZero(MAP_AREAS, sizeof(MAP_AREAS)); - - backpackInit(); - partyInit(); - cutsceneSystemInit(); - - errorChain(mapInit()); - - rpgCameraInit(); - // Init world - errorChain(mapPositionSet((chunkpos_t){ 0, 0, 0 })); - - // TEST: Create some entities. - uint8_t entIndex = entityGetAvailable(); - assertTrue(entIndex != 0xFF, "No available entity slots!."); - entity_t *ent = &ENTITIES[entIndex]; - entityInit(ent, ENTITY_TYPE_PLAYER); - entityPositionSet(ent, (worldpos_t){ 10, 2, 0 });// Also assigns the chunk. - RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY; - RPG_CAMERA.followEntity.followEntityId = ent->id; - - mapSpawnEntity(3, (worldpos_t){ 8, 8, 1 }); - - // TEST: Place an item entity. - uint8_t itemEntIndex = entityGetAvailable(); - assertTrue(itemEntIndex != 0xFF, "No available entity slots!."); - entity_t *itemEnt = &ENTITIES[itemEntIndex]; - entityInit(itemEnt, ENTITY_TYPE_ITEM); - entityItemSet(itemEnt, ITEM_ID_POTION, 1); - entityPositionSet(itemEnt, (worldpos_t){ 12, 2, 0 }); - - // TEST: Give the player a starting assortment of items. - backpackAdd(ITEM_ID_POTION, 5); - backpackAdd(ITEM_ID_POTATO, 3); - backpackAdd(ITEM_ID_APPLE, 8); - - // TEST: Create a test map area. - uint8_t areaIndex = mapAreaAdd( - (worldpos_t){ 11, 3, 0 }, - (worldpos_t){ 16, 9, 10 }, - rpgTestAreaCallback, - MAP_AREA_NOTIFY_ALL, - MAP_TRIGGER_ENTER | MAP_TRIGGER_EXIT - ); - assertTrue(areaIndex != 0xFF, "No available map area slots!."); - - // All Good! - errorOk(); -} - -errorret_t rpgUpdate(void) { - #ifdef DUSK_TIME_DYNAMIC - if(TIME.dynamicUpdate) { - errorOk(); - } - #endif - - // TODO: Do not update if the scene is not the map scene? - errorChain(mapUpdate()); - - // Update overworld ents. - entity_t *ent = &ENTITIES[0]; - do { - if(ent->type == ENTITY_TYPE_NULL) continue; - entityUpdate(ent); - } while(++ent < &ENTITIES[ENTITY_COUNT]); - - cutsceneSystemUpdate(); - errorChain(rpgCameraUpdate()); - errorOk(); -} - -errorret_t rpgDispose(void) { - cutsceneSystemDispose(); - errorChain(mapDispose()); - - errorOk(); -} \ No newline at end of file diff --git a/src/dusk/rpg/rpg.h b/src/dusk/rpg/rpg.h deleted file mode 100644 index 9396c326..00000000 --- a/src/dusk/rpg/rpg.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" - -typedef struct { - int32_t nothing; -} rpg_t; - -/** - * Initialize the RPG subsystem. - * - * @return An error code and state. - */ -errorret_t rpgInit(void); - -/** - * Update the RPG subsystem. - * - * @return An error code. - */ -errorret_t rpgUpdate(void); - -/** - * Dispose of the RPG subsystem. - * - * @return An error code. - */ -errorret_t rpgDispose(void); \ No newline at end of file diff --git a/src/dusk/rpg/rpgcamera.c b/src/dusk/rpg/rpgcamera.c deleted file mode 100644 index d3742d88..00000000 --- a/src/dusk/rpg/rpgcamera.c +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "rpgcamera.h" -#include "util/memory.h" -#include "util/random.h" -#include "rpg/entity/entity.h" -#include "rpg/overworld/map.h" -#include "assert/assert.h" -#include "time/time.h" - -#include "display/screen/screen.h" - -static const float_t RPG_CAMERA_SHAKE_AMOUNTS[] = { - 0.0f, 0.5f, 1.0f, 2.0f, 3.0f -}; - -rpgcamera_t RPG_CAMERA; - -void rpgCameraInit(void) { - memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t)); - RPG_CAMERA.projectionDirty = true; -} - -void rpgCameraShake(uint8_t amount, float_t duration) { - assertTrue(amount <= 4, "Camera shake amount must be between 0 and 4"); - RPG_CAMERA.shakeAmount = RPG_CAMERA_SHAKE_AMOUNTS[amount]; - RPG_CAMERA.shakeDuration = duration; - RPG_CAMERA.shakeTime = 0.0f; -} - -void rpgCameraGetPosition(vec3 out) { - switch(RPG_CAMERA.mode) { - case RPG_CAMERA_MODE_FREE: - glm_vec3_copy(RPG_CAMERA.free, out); - return; - - case RPG_CAMERA_MODE_FOLLOW_ENTITY: { - entity_t *entity = &ENTITIES[RPG_CAMERA.followEntity.followEntityId]; - if(entity->type == ENTITY_TYPE_NULL) { - glm_vec3_zero(out); - return; - } - glm_vec3_copy(entity->renderPosition, out); - return; - } - - default: - assertUnreachable("Invalid RPG camera mode"); - } -} - -void rpgCameraUpdateProjection(void) { - #ifdef DUSK_DISPLAY_WIDTH - if(!RPG_CAMERA.projectionDirty) return; - RPG_CAMERA.projectionDirty = false; - #endif - - glm_perspective( - glm_rad(RPG_CAMERA_FOV), - SCREEN.aspect, - 0.1f, - 100.0f, - RPG_CAMERA.projection - ); -} - -void rpgCameraUpdateEye(void) { - float_t fov = glm_rad(RPG_CAMERA_FOV); - float_t pixelsPerUnit = TILE_SIZE_PIXELS; - float_t worldH = (float_t)(SCREEN.height / SCREEN.scale3d) / pixelsPerUnit; - float_t z = (worldH * 0.5f) / tanf(fov * 0.5f); - float_t offset = -24.0f * (worldH / TILE_SIZE_PIXELS); - - vec3 target; - rpgCameraGetPosition(target); - glm_vec3_add(target, (vec3){ 0.5f, 0.5f, 0.5f }, target); - - if(RPG_CAMERA.shakeTime < RPG_CAMERA.shakeDuration) { - float_t t = 1.0f - (RPG_CAMERA.shakeTime / RPG_CAMERA.shakeDuration); - float_t magnitude = RPG_CAMERA.shakeAmount * t; - target[0] += randomFloat(-magnitude, magnitude); - target[2] += randomFloat(-magnitude, magnitude); - } - - glm_lookat( - (vec3){ target[0], target[1] + offset, target[2] + z }, - target, - (vec3){ 0, 1, 0 }, // up - RPG_CAMERA.eye - ); -} - -void rpgCameraToScreen(vec3 worldPos, vec2 out) { - mat4 viewProj; - glm_mat4_mul(RPG_CAMERA.projection, RPG_CAMERA.eye, viewProj); - - vec4 viewport = { - 0.0f, 0.0f, (float_t)SCREEN.width, (float_t)SCREEN.height - }; - vec3 window; - glm_project(worldPos, viewProj, viewport, window); - - out[0] = window[0]; - out[1] = (float_t)SCREEN.height - window[1]; -} - -errorret_t rpgCameraUpdate(void) { - if(RPG_CAMERA.shakeTime < RPG_CAMERA.shakeDuration) { - RPG_CAMERA.shakeTime += TIME.delta; - } - - if(!mapIsLoaded()) errorOk(); - - vec3 pos; - rpgCameraGetPosition(pos); - - chunkpos_t chunkPos = { - .x = (chunkunit_t)floorf(pos[0] / CHUNK_WIDTH), - .y = (chunkunit_t)floorf(pos[1] / CHUNK_HEIGHT), - .z = (chunkunit_t)floorf(pos[2] / WORLD_LAYER_HEIGHT / CHUNK_DEPTH) - }; - - errorChain(mapPositionSet((chunkpos_t){ - .x = chunkPos.x - (MAP_CHUNK_WIDTH / 2), - .y = chunkPos.y - (MAP_CHUNK_HEIGHT / 2), - .z = chunkPos.z - (MAP_CHUNK_DEPTH / 2) - })); - errorOk(); -} \ No newline at end of file diff --git a/src/dusk/rpg/rpgcamera.h b/src/dusk/rpg/rpgcamera.h deleted file mode 100644 index 12742ff7..00000000 --- a/src/dusk/rpg/rpgcamera.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/overworld/worldpos.h" -#include "error/error.h" - -#define RPG_CAMERA_FOV 35.0f - -typedef enum { - RPG_CAMERA_MODE_FREE, - RPG_CAMERA_MODE_FOLLOW_ENTITY, -} rpgcameramode_t; - -typedef struct { - rpgcameramode_t mode; - - union { - vec3 free; - - struct { - uint8_t followEntityId; - } followEntity; - }; - - mat4 eye; - mat4 projection; - bool_t projectionDirty; - - float_t shakeAmount; - float_t shakeDuration; - float_t shakeTime; -} rpgcamera_t; - -extern rpgcamera_t RPG_CAMERA; - -/** - * Initializes the RPG camera. - */ -void rpgCameraInit(void); - -/** - * Gets the RPG camera's position. - * - * @param out Output vec3 filled with the camera world position. - */ -void rpgCameraGetPosition(vec3 out); - -/** - * Updates the RPG camera. - * - * @return An error code. - */ -errorret_t rpgCameraUpdate(void); - -/** - * Recomputes the camera projection matrix and stores it in - * RPG_CAMERA.projection. On platforms with a fixed display size the - * matrix is computed once and cached; on dynamic-display platforms it - * is recomputed every call. - */ -void rpgCameraUpdateProjection(void); - -/** - * Recomputes the camera eye/view matrix from the camera's current mode - * and position, and stores it in RPG_CAMERA.eye. Unlike the projection - * matrix this is never cached, since the camera position can change - * every frame. - */ -void rpgCameraUpdateEye(void); - -/** - * Shakes the RPG camera, randomly offsetting its position by a - * decreasing amount over the given duration. - * - * @param amount Shake strength from 0 (no shake) to 4 (three tiles). - * 1 is half a tile, 2 is a full tile, 3 is two tiles, and 4 is three - * tiles. - * @param duration How long the shake lasts, in seconds. - */ -void rpgCameraShake(uint8_t amount, float_t duration); - -/** - * Converts a world-space position to screen-space pixel coordinates, - * using the camera's current eye and projection matrices. - * - * @param worldPos The world-space position to convert. - * @param out Output vec2 filled with the screen-space pixel position. - */ -void rpgCameraToScreen(vec3 worldPos, vec2 out); \ No newline at end of file diff --git a/src/dusk/rpg/story/CMakeLists.txt b/src/dusk/rpg/story/CMakeLists.txt deleted file mode 100644 index 6aace3e7..00000000 --- a/src/dusk/rpg/story/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - storyflag.c -) - -# Story Flag Definitions -dusk_run_python( - dusk_story_defs - tools.story - --csv ${CMAKE_CURRENT_SOURCE_DIR}/storyflag.csv - --output ${DUSK_GENERATED_HEADERS_DIR}/rpg/story/storyflagvalue.h -) -add_dependencies(${DUSK_LIBRARY_TARGET_NAME} dusk_story_defs) \ No newline at end of file diff --git a/src/dusk/rpg/story/storyflag.c b/src/dusk/rpg/story/storyflag.c deleted file mode 100644 index e83ba3a8..00000000 --- a/src/dusk/rpg/story/storyflag.c +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "storyflag.h" -#include "assert/assert.h" - -void storyFlagSet(const storyflag_t flag, const storyflagvalue_t value) { - assertTrue(flag > STORY_FLAG_NULL && flag < STORY_FLAG_COUNT, "Bad Flag"); - STORY_FLAG_VALUES[flag] = value; -} \ No newline at end of file diff --git a/src/dusk/rpg/story/storyflag.csv b/src/dusk/rpg/story/storyflag.csv deleted file mode 100644 index ac5197d1..00000000 --- a/src/dusk/rpg/story/storyflag.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,description,initial -test,"Test flag for debugging purposes",1 diff --git a/src/dusk/rpg/story/storyflag.h b/src/dusk/rpg/story/storyflag.h deleted file mode 100644 index 00fb88e0..00000000 --- a/src/dusk/rpg/story/storyflag.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "rpg/story/storyflagvalue.h" - -/** - * Gets the value of a story flag. - * - * @param flag The story flag to get. - * @return The value of the story flag. - */ -#define storyFlagGet(flag) (STORY_FLAG_VALUES[(flag)]) - -/** - * Sets the value of a story flag. - * - * @param flag The story flag to set. - * @param value The value to set the story flag to. - */ -void storyFlagSet(const storyflag_t flag, const storyflagvalue_t value); \ No newline at end of file diff --git a/src/dusk/rpg/story/storyflagdefs.h b/src/dusk/rpg/story/storyflagdefs.h deleted file mode 100644 index 2dd81c3f..00000000 --- a/src/dusk/rpg/story/storyflagdefs.h +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef uint8_t storyflagvalue_t; \ No newline at end of file diff --git a/src/dusk/save/CMakeLists.txt b/src/dusk/save/CMakeLists.txt deleted file mode 100644 index 55b35252..00000000 --- a/src/dusk/save/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - save.c - savestream.c -) diff --git a/src/dusk/save/save.c b/src/dusk/save/save.c deleted file mode 100644 index 2b046807..00000000 --- a/src/dusk/save/save.c +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" -#include "save/savestream.h" -#include "util/memory.h" -#include "assert/assert.h" - -save_t SAVE; - -errorret_t saveInit(void) { - memoryZero(&SAVE, sizeof(save_t)); - - #ifdef saveInitPlatform - errorChain(saveInitPlatform()); - #endif - - errorOk(); -} - -errorret_t saveDispose(void) { - #ifdef saveDisposePlatform - errorChain(saveDisposePlatform()); - #endif - errorOk(); -} - -errorret_t saveLoad(const uint8_t slot) { - assertTrue(slot < SAVE_FILE_COUNT_MAX, "slot exceeds SAVE_FILE_COUNT_MAX"); - - savefile_t *file = &SAVE.files[slot]; - file->exists = false; - - savestream_t stream; - memoryZero(&stream, sizeof(savestream_t)); - - #ifdef saveStreamOpenReadPlatform - errorChain(saveStreamOpenReadPlatform(&stream, slot)); - #endif - - if(!stream.found) errorOk(); - - errorret_t ret = saveFileLoad(&stream, file); - - #ifdef saveStreamClosePlatform - saveStreamClosePlatform(&stream); - #endif - - if(errorIsNotOk(ret)) return ret; - - errorChain(saveStreamVerifyChecksumImpl(&stream, slot)); - - file->exists = true; - errorOk(); -} - -errorret_t saveWrite(const uint8_t slot) { - assertTrue(slot < SAVE_FILE_COUNT_MAX, "slot exceeds SAVE_FILE_COUNT_MAX"); - - savefile_t *file = &SAVE.files[slot]; - - savestream_t stream; - memoryZero(&stream, sizeof(savestream_t)); - - #ifdef saveStreamOpenWritePlatform - errorChain(saveStreamOpenWritePlatform(&stream, slot)); - #endif - - errorret_t ret = saveFileWrite(&stream, file); - - if(errorIsOk(ret)) { - ret = saveStreamFinalizeWriteImpl(&stream); - } - - #ifdef saveStreamClosePlatform - saveStreamClosePlatform(&stream); - #endif - - if(errorIsNotOk(ret)) return ret; - - file->exists = true; - errorOk(); -} - -errorret_t saveDelete(const uint8_t slot) { - assertTrue(slot < SAVE_FILE_COUNT_MAX, "slot exceeds SAVE_FILE_COUNT_MAX"); - - #ifdef saveDeletePlatform - errorChain(saveDeletePlatform(slot)); - #endif - - SAVE.files[slot].exists = false; - errorOk(); -} - -bool_t saveExists(const uint8_t slot) { - assertTrue(slot < SAVE_FILE_COUNT_MAX, "slot exceeds SAVE_FILE_COUNT_MAX"); - return SAVE.files[slot].exists; -} - -savefile_t * saveGet(const uint8_t slot) { - assertTrue(slot < SAVE_FILE_COUNT_MAX, "slot exceeds SAVE_FILE_COUNT_MAX"); - return &SAVE.files[slot]; -} diff --git a/src/dusk/save/save.h b/src/dusk/save/save.h deleted file mode 100644 index 1309dc02..00000000 --- a/src/dusk/save/save.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "savefile.h" -#include "save/saveplatform.h" - -typedef struct { - /** Per-slot save file data; indexed 0 to SAVE_FILE_COUNT_MAX - 1. */ - savefile_t files[SAVE_FILE_COUNT_MAX]; - /** Platform-specific save system state (paths, card handles, etc.). */ - saveplatform_t platform; -} save_t; - -extern save_t SAVE; - -/** - * Initializes the save system. - * - * @return An error code if initialization fails. - */ -errorret_t saveInit(void); - -/** - * Disposes of the save system. - * - * @return An error code if disposal fails. - */ -errorret_t saveDispose(void); - -/** - * Loads the save file for a given slot from persistent storage. - * - * @param slot The save slot index (0 to SAVE_FILE_COUNT_MAX - 1). - * @return An error code if the load fails. - */ -errorret_t saveLoad(const uint8_t slot); - -/** - * Writes the save file for a given slot to persistent storage. - * - * @param slot The save slot index (0 to SAVE_FILE_COUNT_MAX - 1). - * @return An error code if the write fails. - */ -errorret_t saveWrite(const uint8_t slot); - -/** - * Deletes the save file for a given slot from persistent storage. - * - * @param slot The save slot index (0 to SAVE_FILE_COUNT_MAX - 1). - * @return An error code if the delete fails. - */ -errorret_t saveDelete(const uint8_t slot); - -/** - * Checks whether a save file exists for a given slot. - * - * @param slot The save slot index (0 to SAVE_FILE_COUNT_MAX - 1). - * @return true if a save file exists for the slot, false otherwise. - */ -bool_t saveExists(const uint8_t slot); - -/** - * Gets a pointer to the save file data for a given slot. - * - * @param slot The save slot index (0 to SAVE_FILE_COUNT_MAX - 1). - * @return A pointer to the savefile_t for the given slot. - */ -savefile_t * saveGet(const uint8_t slot); diff --git a/src/dusk/save/savefile.h b/src/dusk/save/savefile.h deleted file mode 100644 index dfef1d66..00000000 --- a/src/dusk/save/savefile.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -/** Save file format version. Increment on breaking change. */ -#define SAVE_FILE_VERSION 1 - -/** Magic bytes that identify a Dusk save file. */ -#define SAVE_FILE_HEADER "DSK" - -/** Byte length of the magic header (excludes the null terminator). */ -#define SAVE_FILE_HEADER_SIZE (sizeof(SAVE_FILE_HEADER) - 1) - -/** Maximum number of independent save slots supported. */ -#define SAVE_FILE_COUNT_MAX 3 - -typedef struct { - /** Magic header bytes read from the file; must equal SAVE_FILE_HEADER. */ - char_t header[SAVE_FILE_HEADER_SIZE]; - /** Format version read from the file; used to branch on older layouts. */ - uint32_t version; - /** Runtime flag - true if this slot was successfully loaded or written. */ - bool_t exists; -} savefile_t; diff --git a/src/dusk/save/savestream.c b/src/dusk/save/savestream.c deleted file mode 100644 index efad01aa..00000000 --- a/src/dusk/save/savestream.c +++ /dev/null @@ -1,340 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/savestream.h" -#include "util/crypt.h" -#include "util/endian.h" -#include "util/string.h" -#include "util/memory.h" - -errorret_t saveStreamReadBytesRawImpl( - savestream_t *stream, void *buf, const size_t len -) { - #ifdef saveStreamReadBytesPlatform - errorChain(saveStreamReadBytesPlatform(stream, buf, len)); - #endif - errorOk(); -} - -errorret_t saveStreamWriteBytesRawImpl( - savestream_t *stream, const void *buf, const size_t len -) { - #ifdef saveStreamWriteBytesPlatform - errorChain(saveStreamWriteBytesPlatform(stream, buf, len)); - #endif - errorOk(); -} - -errorret_t saveStreamReadBytesImpl( - savestream_t *stream, void *buf, const size_t len -) { - errorChain(saveStreamReadBytesRawImpl(stream, buf, len)); - cryptCRC32Update(&stream->checksum, buf, len); - errorOk(); -} - -errorret_t saveStreamWriteBytesImpl( - savestream_t *stream, const void *buf, const size_t len -) { - cryptCRC32Update(&stream->checksum, buf, len); - errorChain(saveStreamWriteBytesRawImpl(stream, buf, len)); - errorOk(); -} - -errorret_t saveStreamFinalizeWriteImpl(savestream_t *stream) { - uint32_t finalCRC = cryptCRC32End(stream->checksum); - uint32_t leChecksum = endianLittleToHost32(finalCRC); - - #ifdef saveStreamSeekPlatform - errorChain(saveStreamSeekPlatform(stream, SAVE_FILE_HEADER_SIZE)); - #endif - - errorChain(saveStreamWriteBytesRawImpl( - stream, &leChecksum, sizeof(uint32_t) - )); - errorOk(); -} - -errorret_t saveStreamVerifyChecksumImpl( - savestream_t *stream, const uint8_t slot -) { - uint32_t computed = cryptCRC32End(stream->checksum); - if(computed != stream->expectedChecksum) { - errorThrow("Save slot %u has invalid checksum", (uint32_t)slot); - } - errorOk(); -} - - -errorret_t saveStreamReadHeaderImpl( - savestream_t *stream, char_t header[SAVE_FILE_HEADER_SIZE] -) { - errorChain(saveStreamReadBytesRawImpl(stream, header, SAVE_FILE_HEADER_SIZE)); - - if( - header[0] != SAVE_FILE_HEADER[0] || - header[1] != SAVE_FILE_HEADER[1] || - header[2] != SAVE_FILE_HEADER[2] - ) { - errorThrow("Save file has invalid header"); - } - - uint32_t leChecksum; - errorChain(saveStreamReadBytesRawImpl(stream, &leChecksum, sizeof(uint32_t))); - stream->expectedChecksum = endianLittleToHost32(leChecksum); - stream->checksum = cryptCRC32Begin(); - errorOk(); -} - -errorret_t saveStreamWriteHeaderImpl( - savestream_t *stream, const char_t header[SAVE_FILE_HEADER_SIZE] -) { - errorChain(saveStreamWriteBytesRawImpl( - stream, header, SAVE_FILE_HEADER_SIZE - )); - - uint32_t placeholder = 0; - errorChain(saveStreamWriteBytesRawImpl( - stream, &placeholder, sizeof(uint32_t) - )); - stream->checksum = cryptCRC32Begin(); - errorOk(); -} - -errorret_t saveStreamReadVersionImpl(savestream_t *stream, uint32_t *out) { - uint32_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint32_t))); - *out = endianLittleToHost32(raw); - errorOk(); -} - -errorret_t saveStreamWriteVersionImpl( - savestream_t *stream, const uint32_t *input -) { - uint32_t raw = endianLittleToHost32(*input); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint32_t))); - errorOk(); -} - -errorret_t saveStreamReadBoolImpl(savestream_t *stream, bool_t *out) { - uint8_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint8_t))); - *out = (bool_t)(raw != 0); - errorOk(); -} - -errorret_t saveStreamWriteBoolImpl(savestream_t *stream, const bool_t *input) { - uint8_t raw = *input ? 1 : 0; - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint8_t))); - errorOk(); -} - -errorret_t saveStreamReadInt8Impl(savestream_t *stream, int8_t *out) { - errorChain(saveStreamReadBytesImpl(stream, out, sizeof(int8_t))); - errorOk(); -} - -errorret_t saveStreamWriteInt8Impl(savestream_t *stream, const int8_t *input) { - errorChain(saveStreamWriteBytesImpl(stream, input, sizeof(int8_t))); - errorOk(); -} - -errorret_t saveStreamReadUInt8Impl(savestream_t *stream, uint8_t *out) { - errorChain(saveStreamReadBytesImpl(stream, out, sizeof(uint8_t))); - errorOk(); -} - -errorret_t saveStreamWriteUInt8Impl( - savestream_t *stream, const uint8_t *input -) { - errorChain(saveStreamWriteBytesImpl(stream, input, sizeof(uint8_t))); - errorOk(); -} - -errorret_t saveStreamReadInt16Impl(savestream_t *stream, int16_t *out) { - uint16_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint16_t))); - uint16_t host = endianLittleToHost16(raw); - memoryCopy(out, &host, sizeof(int16_t)); - errorOk(); -} - -errorret_t saveStreamWriteInt16Impl( - savestream_t *stream, const int16_t *input -) { - uint16_t raw; - memoryCopy(&raw, input, sizeof(int16_t)); - raw = endianLittleToHost16(raw); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint16_t))); - errorOk(); -} - -errorret_t saveStreamReadUInt16Impl(savestream_t *stream, uint16_t *out) { - uint16_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint16_t))); - *out = endianLittleToHost16(raw); - errorOk(); -} - -errorret_t saveStreamWriteUInt16Impl( - savestream_t *stream, const uint16_t *input -) { - uint16_t raw = endianLittleToHost16(*input); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint16_t))); - errorOk(); -} - -errorret_t saveStreamReadInt32Impl(savestream_t *stream, int32_t *out) { - uint32_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint32_t))); - uint32_t host = endianLittleToHost32(raw); - memoryCopy(out, &host, sizeof(int32_t)); - errorOk(); -} - -errorret_t saveStreamWriteInt32Impl( - savestream_t *stream, const int32_t *input -) { - uint32_t raw; - memoryCopy(&raw, input, sizeof(int32_t)); - raw = endianLittleToHost32(raw); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint32_t))); - errorOk(); -} - -errorret_t saveStreamReadUInt32Impl(savestream_t *stream, uint32_t *out) { - uint32_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint32_t))); - *out = endianLittleToHost32(raw); - errorOk(); -} - -errorret_t saveStreamWriteUInt32Impl( - savestream_t *stream, const uint32_t *input -) { - uint32_t raw = endianLittleToHost32(*input); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint32_t))); - errorOk(); -} - -errorret_t saveStreamReadInt64Impl(savestream_t *stream, int64_t *out) { - uint64_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint64_t))); - uint64_t host = endianLittleToHost64(raw); - memoryCopy(out, &host, sizeof(int64_t)); - errorOk(); -} - -errorret_t saveStreamWriteInt64Impl( - savestream_t *stream, const int64_t *input -) { - uint64_t raw; - memoryCopy(&raw, input, sizeof(int64_t)); - raw = endianLittleToHost64(raw); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint64_t))); - errorOk(); -} - -errorret_t saveStreamReadUInt64Impl(savestream_t *stream, uint64_t *out) { - uint64_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint64_t))); - *out = endianLittleToHost64(raw); - errorOk(); -} - -errorret_t saveStreamWriteUInt64Impl( - savestream_t *stream, const uint64_t *input -) { - uint64_t raw = endianLittleToHost64(*input); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint64_t))); - errorOk(); -} - -errorret_t saveStreamReadFloatImpl(savestream_t *stream, float_t *out) { - float_t raw; - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(float_t))); - *out = endianLittleToHostFloat(raw); - errorOk(); -} - -errorret_t saveStreamWriteFloatImpl( - savestream_t *stream, const float_t *input -) { - float_t raw = endianLittleToHostFloat(*input); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(float_t))); - errorOk(); -} - -errorret_t saveStreamReadStringImpl( - savestream_t *stream, char_t *out, const size_t maxLen -) { - for(size_t i = 0; i < maxLen; i++) { - errorChain(saveStreamReadBytesImpl(stream, &out[i], sizeof(char_t))); - if(out[i] == '\0') errorOk(); - } - out[maxLen - 1] = '\0'; - errorOk(); -} - -errorret_t saveStreamWriteStringImpl( - savestream_t *stream, const char_t *input, const size_t maxLen -) { - size_t len = strlen(input); - if(len >= maxLen) len = maxLen - 1; - errorChain(saveStreamWriteBytesImpl(stream, input, len + 1)); - errorOk(); -} - -errorret_t saveStreamReadDateImpl(savestream_t *stream, dusktimeepoch_t *out) { - uint64_t raw; - - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint64_t))); - raw = endianLittleToHost64(raw); - memoryCopy(&out->time, &raw, sizeof(double_t)); - - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint64_t))); - raw = endianLittleToHost64(raw); - memoryCopy(&out->timeZone, &raw, sizeof(double_t)); - - errorChain(saveStreamReadBytesImpl(stream, &raw, sizeof(uint64_t))); - raw = endianLittleToHost64(raw); - memoryCopy(&out->offsetTime, &raw, sizeof(double_t)); - - errorOk(); -} - -errorret_t saveStreamWriteDateImpl( - savestream_t *stream, const dusktimeepoch_t *input -) { - uint64_t raw; - - memoryCopy(&raw, &input->time, sizeof(double_t)); - raw = endianLittleToHost64(raw); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint64_t))); - - memoryCopy(&raw, &input->timeZone, sizeof(double_t)); - raw = endianLittleToHost64(raw); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint64_t))); - - memoryCopy(&raw, &input->offsetTime, sizeof(double_t)); - raw = endianLittleToHost64(raw); - errorChain(saveStreamWriteBytesImpl(stream, &raw, sizeof(uint64_t))); - - errorOk(); -} - -errorret_t saveFileLoad(savestream_t *stream, savefile_t *file) { - saveFileReadHeader(stream, file->header); - saveFileReadVersion(stream, &file->version); - errorOk(); -} - -errorret_t saveFileWrite(savestream_t *stream, savefile_t *file) { - saveFileWriteHeader(stream, file->header); - saveFileWriteVersion(stream, &file->version); - errorOk(); -} diff --git a/src/dusk/save/savestream.h b/src/dusk/save/savestream.h deleted file mode 100644 index 4eb6c540..00000000 --- a/src/dusk/save/savestream.h +++ /dev/null @@ -1,468 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "savefile.h" -#include "save/saveplatform.h" -#include "time/timeepoch.h" - -typedef struct { - bool_t found; - uint32_t checksum; - uint32_t expectedChecksum; - saveplatformstream_t platform; -} savestream_t; - -/** - * Reads bytes from the platform stream without updating the CRC. - * - * @param stream Active stream. - * @param buf Destination buffer. - * @param len Number of bytes to read. - * @return An error if the read fails. - */ -errorret_t saveStreamReadBytesRawImpl( - savestream_t *stream, void *buf, const size_t len -); - -/** - * Writes bytes to the platform stream without updating the CRC. - * - * @param stream Active stream. - * @param buf Source buffer. - * @param len Number of bytes to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteBytesRawImpl( - savestream_t *stream, const void *buf, const size_t len -); - -/** - * Reads bytes from the platform stream and accumulates them into the CRC. - * - * @param stream Active stream. - * @param buf Destination buffer. - * @param len Number of bytes to read. - * @return An error if the read fails. - */ -errorret_t saveStreamReadBytesImpl( - savestream_t *stream, void *buf, const size_t len -); - -/** - * Updates the CRC then writes bytes to the platform stream. - * - * @param stream Active stream. - * @param buf Source buffer. - * @param len Number of bytes to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteBytesImpl( - savestream_t *stream, const void *buf, const size_t len -); - -/** - * Finalizes a write stream: computes the final CRC32, seeks to the - * checksum field in the header, and writes it in little-endian order. - * - * @param stream Active write stream. - * @return An error if the seek or write fails. - */ -errorret_t saveStreamFinalizeWriteImpl(savestream_t *stream); - -/** - * Verifies that the CRC32 accumulated during loading matches the value - * stored in the file header. - * - * @param stream Active read stream (loading must be complete). - * @param slot Slot index used in the error message on mismatch. - * @return An error if the checksum does not match. - */ -errorret_t saveStreamVerifyChecksumImpl( - savestream_t *stream, const uint8_t slot -); - -/** - * Reads and validates the magic header, then reads the stored CRC32 and - * resets the running accumulator. - * - * @param stream Active read stream. - * @param header Buffer of SAVE_FILE_HEADER_SIZE bytes to receive the header. - * @return An error if the header is missing or invalid. - */ -errorret_t saveStreamReadHeaderImpl( - savestream_t *stream, char_t header[SAVE_FILE_HEADER_SIZE] -); - -/** - * Writes the magic header and a zero CRC32 placeholder, then resets the - * running accumulator. - * - * @param stream Active write stream. - * @param header Buffer of SAVE_FILE_HEADER_SIZE bytes to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteHeaderImpl( - savestream_t *stream, - const char_t header[SAVE_FILE_HEADER_SIZE] -); - -/** - * Reads a little-endian uint32 version field from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadVersionImpl(savestream_t *stream, uint32_t *out); - -/** - * Writes a uint32 version field to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteVersionImpl( - savestream_t *stream, const uint32_t *input -); - -/** - * Reads a single byte as a boolean (0 = false, non-zero = true). - * - * @param stream Active read stream. - * @param out Receives the boolean value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadBoolImpl(savestream_t *stream, bool_t *out); - -/** - * Writes a boolean as a single byte (true = 1, false = 0). - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteBoolImpl(savestream_t *stream, const bool_t *input); - -/** - * Reads a signed 8-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadInt8Impl(savestream_t *stream, int8_t *out); - -/** - * Writes a signed 8-bit integer to the stream. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteInt8Impl(savestream_t *stream, const int8_t *input); - -/** - * Reads an unsigned 8-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadUInt8Impl(savestream_t *stream, uint8_t *out); - -/** - * Writes an unsigned 8-bit integer to the stream. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteUInt8Impl(savestream_t *stream, const uint8_t *input); - -/** - * Reads a little-endian signed 16-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadInt16Impl(savestream_t *stream, int16_t *out); - -/** - * Writes a signed 16-bit integer to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteInt16Impl( - savestream_t *stream, const int16_t *input -); - -/** - * Reads a little-endian unsigned 16-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadUInt16Impl(savestream_t *stream, uint16_t *out); - -/** - * Writes an unsigned 16-bit integer to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteUInt16Impl( - savestream_t *stream, const uint16_t *input -); - -/** - * Reads a little-endian signed 32-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadInt32Impl(savestream_t *stream, int32_t *out); - -/** - * Writes a signed 32-bit integer to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteInt32Impl( - savestream_t *stream, const int32_t *input -); - -/** - * Reads a little-endian unsigned 32-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadUInt32Impl(savestream_t *stream, uint32_t *out); - -/** - * Writes an unsigned 32-bit integer to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteUInt32Impl( - savestream_t *stream, const uint32_t *input -); - -/** - * Reads a little-endian signed 64-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadInt64Impl(savestream_t *stream, int64_t *out); - -/** - * Writes a signed 64-bit integer to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteInt64Impl( - savestream_t *stream, const int64_t *input -); - -/** - * Reads a little-endian unsigned 64-bit integer from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadUInt64Impl(savestream_t *stream, uint64_t *out); - -/** - * Writes an unsigned 64-bit integer to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteUInt64Impl( - savestream_t *stream, const uint64_t *input -); - -/** - * Reads a little-endian float from the stream. - * - * @param stream Active read stream. - * @param out Receives the host-order value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadFloatImpl(savestream_t *stream, float_t *out); - -/** - * Writes a float to the stream in little-endian order. - * - * @param stream Active write stream. - * @param input Value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteFloatImpl( - savestream_t *stream, const float_t *input -); - -/** - * Reads a null-terminated string from the stream up to maxLen bytes - * (including the terminator). Always null-terminates the output buffer. - * - * @param stream Active read stream. - * @param out Destination buffer of at least maxLen bytes. - * @param maxLen Maximum bytes to read, including the null terminator. - * @return An error if the read fails. - */ -errorret_t saveStreamReadStringImpl( - savestream_t *stream, char_t *out, const size_t maxLen -); - -/** - * Writes a null-terminated string to the stream, truncating to maxLen-1 - * characters and always appending a null terminator. - * - * @param stream Active write stream. - * @param input Source string. - * @param maxLen Maximum bytes to write, including the null terminator. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteStringImpl( - savestream_t *stream, const char_t *input, const size_t maxLen -); - -/** - * Reads a dusktimeepoch_t as three little-endian 64-bit IEEE 754 doubles - * (time, timeZone, offsetTime). - * - * @param stream Active read stream. - * @param out Receives the epoch value. - * @return An error if the read fails. - */ -errorret_t saveStreamReadDateImpl( - savestream_t *stream, dusktimeepoch_t *out -); - -/** - * Writes a dusktimeepoch_t as three little-endian 64-bit IEEE 754 doubles - * (time, timeZone, offsetTime). - * - * @param stream Active write stream. - * @param input Epoch value to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteDateImpl( - savestream_t *stream, const dusktimeepoch_t *input -); - -/** - * Reads the contents of a save slot from the stream into the save file - * struct. Use saveFileRead* macros to deserialize fields one at a time. - * - * @param stream Active read stream for this slot. - * @param file Save file struct to populate. - * @return An error code if loading fails. - */ -errorret_t saveFileLoad(savestream_t *stream, savefile_t *file); - -/** - * Writes the contents of the save file struct into the stream. - * Use saveFileWrite* macros to serialize fields one at a time. - * - * @param stream Active write stream for this slot. - * @param file Save file struct to serialize. - * @return An error code if writing fails. - */ -errorret_t saveFileWrite(savestream_t *stream, savefile_t *file); - -#define saveFileReadHeader(stream, header) \ - errorChain(saveStreamReadHeaderImpl(stream, header)) -#define saveFileWriteHeader(stream, header) \ - errorChain(saveStreamWriteHeaderImpl(stream, header)) - -#define saveFileReadVersion(stream, out) \ - errorChain(saveStreamReadVersionImpl(stream, out)) -#define saveFileWriteVersion(stream, input) \ - errorChain(saveStreamWriteVersionImpl(stream, input)) - -#define saveFileReadBool(stream, out) \ - errorChain(saveStreamReadBoolImpl(stream, out)) -#define saveFileWriteBool(stream, input) \ - errorChain(saveStreamWriteBoolImpl(stream, input)) - -#define saveFileReadInt8(stream, out) \ - errorChain(saveStreamReadInt8Impl(stream, out)) -#define saveFileWriteInt8(stream, input) \ - errorChain(saveStreamWriteInt8Impl(stream, input)) - -#define saveFileReadUInt8(stream, out) \ - errorChain(saveStreamReadUInt8Impl(stream, out)) -#define saveFileWriteUInt8(stream, input) \ - errorChain(saveStreamWriteUInt8Impl(stream, input)) - -#define saveFileReadInt16(stream, out) \ - errorChain(saveStreamReadInt16Impl(stream, out)) -#define saveFileWriteInt16(stream, input) \ - errorChain(saveStreamWriteInt16Impl(stream, input)) - -#define saveFileReadUInt16(stream, out) \ - errorChain(saveStreamReadUInt16Impl(stream, out)) -#define saveFileWriteUInt16(stream, input) \ - errorChain(saveStreamWriteUInt16Impl(stream, input)) - -#define saveFileReadInt32(stream, out) \ - errorChain(saveStreamReadInt32Impl(stream, out)) -#define saveFileWriteInt32(stream, input) \ - errorChain(saveStreamWriteInt32Impl(stream, input)) - -#define saveFileReadUInt32(stream, out) \ - errorChain(saveStreamReadUInt32Impl(stream, out)) -#define saveFileWriteUInt32(stream, input) \ - errorChain(saveStreamWriteUInt32Impl(stream, input)) - -#define saveFileReadInt64(stream, out) \ - errorChain(saveStreamReadInt64Impl(stream, out)) -#define saveFileWriteInt64(stream, input) \ - errorChain(saveStreamWriteInt64Impl(stream, input)) - -#define saveFileReadUInt64(stream, out) \ - errorChain(saveStreamReadUInt64Impl(stream, out)) -#define saveFileWriteUInt64(stream, input) \ - errorChain(saveStreamWriteUInt64Impl(stream, input)) - -#define saveFileReadFloat(stream, out) \ - errorChain(saveStreamReadFloatImpl(stream, out)) -#define saveFileWriteFloat(stream, input) \ - errorChain(saveStreamWriteFloatImpl(stream, input)) - -#define saveFileReadString(stream, out, maxLen) \ - errorChain(saveStreamReadStringImpl(stream, out, maxLen)) -#define saveFileWriteString(stream, input, maxLen) \ - errorChain(saveStreamWriteStringImpl(stream, input, maxLen)) - -#define saveFileReadDate(stream, out) \ - errorChain(saveStreamReadDateImpl(stream, out)) -#define saveFileWriteDate(stream, input) \ - errorChain(saveStreamWriteDateImpl(stream, input)) - diff --git a/src/dusk/scene/CMakeLists.txt b/src/dusk/scene/CMakeLists.txt index b8480d21..214a8e93 100644 --- a/src/dusk/scene/CMakeLists.txt +++ b/src/dusk/scene/CMakeLists.txt @@ -7,8 +7,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC scene.c scenetype.c -) - -# Subdirs -add_subdirectory(overworld) -add_subdirectory(battle) \ No newline at end of file +) \ No newline at end of file diff --git a/src/dusk/scene/battle/CMakeLists.txt b/src/dusk/scene/battle/CMakeLists.txt deleted file mode 100644 index a743129d..00000000 --- a/src/dusk/scene/battle/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - scenebattle.c -) diff --git a/src/dusk/scene/battle/scenebattle.c b/src/dusk/scene/battle/scenebattle.c deleted file mode 100644 index 0fabef58..00000000 --- a/src/dusk/scene/battle/scenebattle.c +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "scenebattle.h" -#include "rpg/battle/battle.h" - -errorret_t sceneBattleInit(scenedata_t *sceneData) { - errorOk(); -} - -errorret_t sceneBattleUpdate(scenedata_t *sceneData) { - battleUpdate(); - errorOk(); -} - -errorret_t sceneBattleRender(scenedata_t *sceneData) { - errorOk(); -} - -errorret_t sceneBattleDispose(scenedata_t *sceneData) { - errorOk(); -} diff --git a/src/dusk/scene/battle/scenebattle.h b/src/dusk/scene/battle/scenebattle.h deleted file mode 100644 index 17046a35..00000000 --- a/src/dusk/scene/battle/scenebattle.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "scene/scenebase.h" - -typedef struct { - -} scenebattle_t; - -/** - * Initializes the battle scene. The battle itself (BATTLE global) is - * expected to already be started, e.g. by a StartBattle cutscene item. - * - * @param sceneData The scene data used for this scene. - * @return An error if the init failed, or errorOk() if it succeeded. - */ -errorret_t sceneBattleInit(scenedata_t *sceneData); - -/** - * Updates the battle scene, ticking the battle simulation. - * - * @param sceneData The scene data used for this scene. - * @return An error if the update failed, or errorOk() if it succeeded. - */ -errorret_t sceneBattleUpdate(scenedata_t *sceneData); - -/** - * Renders the battle scene. - * - * @param sceneData The scene data used for this scene. - * @return An error if the render failed, or errorOk() if it succeeded. - */ -errorret_t sceneBattleRender(scenedata_t *sceneData); - -/** - * Disposes the battle scene. - * - * @param sceneData The scene data used for this scene. - * @return An error if the dispose failed, or errorOk() if it succeeded. - */ -errorret_t sceneBattleDispose(scenedata_t *sceneData); diff --git a/src/dusk/scene/overworld/CMakeLists.txt b/src/dusk/scene/overworld/CMakeLists.txt deleted file mode 100644 index 6038dc07..00000000 --- a/src/dusk/scene/overworld/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - sceneoverworld.c -) \ No newline at end of file diff --git a/src/dusk/scene/overworld/sceneoverworld.c b/src/dusk/scene/overworld/sceneoverworld.c deleted file mode 100644 index 4e42a149..00000000 --- a/src/dusk/scene/overworld/sceneoverworld.c +++ /dev/null @@ -1,262 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "scene/scene.h" -#include "console/console.h" -#include "assert/assert.h" - -#include "display/display.h" -#include "display/displaystate.h" -#include "display/shader/shader.h" -#include "display/screen/screen.h" -#include "display/shader/shaderunlit.h" -#include "display/spritebatch/spritebatch.h" -#include "display/texture/texture.h" - -#include "rpg/overworld/map.h" -#include "rpg/entity/entity.h" -#include "rpg/rpgcamera.h" - -#include "asset/loader/assetloader.h" -#include "asset/loader/assetentry.h" - -#include "util/memory.h" - -errorret_t sceneOverworldInit(scenedata_t *sceneData) { - assertNotNull(sceneData, "Scene data cannot be null"); - errorOk(); -} - -errorret_t sceneOverworldUpdate(scenedata_t *sceneData) { - assertNotNull(sceneData, "Scene data cannot be null"); - errorOk(); -} - -errorret_t sceneOverworldRender(scenedata_t *sceneData) { - assertNotNull(sceneData, "Scene data cannot be null"); - - sceneoverworld_t *overworld = &sceneData->overworld; - sceneOverworldCullUpdate(overworld); - - - // Overworld camera - errorChain(shaderBind(&SHADER_UNLIT)); - errorChain(shaderSetMatrix( - &SHADER_UNLIT, SHADER_UNLIT_MODEL, SCENE.screenIdentity - )); - - rpgCameraUpdateProjection(); - errorChain(shaderSetMatrix( - &SHADER_UNLIT, SHADER_UNLIT_PROJECTION, RPG_CAMERA.projection - )); - - rpgCameraUpdateEye(); - errorChain(shaderSetMatrix( - &SHADER_UNLIT, SHADER_UNLIT_VIEW, RPG_CAMERA.eye - )); - - // Chunk tiles - errorChain(displaySetState((displaystate_t){ - .flags = DISPLAY_STATE_FLAG_DEPTH_TEST | DISPLAY_STATE_FLAG_CULL - })); - errorChain(sceneOverworldDrawChunksBase(overworld)); - - // Entities - errorChain(displaySetState((displaystate_t){ - .flags = DISPLAY_STATE_FLAG_CULL - })); - - for(uint8_t i = 0; i < ENTITY_COUNT; i++) { - entity_t *ent = &ENTITIES[i]; - if(ent->type == ENTITY_TYPE_NULL) continue; - errorChain(sceneOverworldDrawEntity(overworld, ent)); - } - - // Chunk props - errorChain(displaySetState((displaystate_t){ - .flags = DISPLAY_STATE_FLAG_DEPTH_TEST | DISPLAY_STATE_FLAG_CULL - })); - errorChain(sceneOverworldDrawChunksProps(overworld)); - - // Weather effects - // errorChain(shaderSetMatrix( - // &SHADER_UNLIT, SHADER_UNLIT_PROJECTION, SCENE.screenProj - // )); - // errorChain(shaderSetMatrix( - // &SHADER_UNLIT, SHADER_UNLIT_VIEW, SCENE.screenView - // )); - // errorChain(displaySetState((displaystate_t){ - // .flags = DISPLAY_STATE_FLAG_BLEND - // })); - - // spritebatchsprite_t skyboxSprite; - // memoryZero(&skyboxSprite, sizeof(spritebatchsprite_t)); - // skyboxSprite.max[0] = (float_t)(SCREEN.width / SCREEN.scaleUi); - // skyboxSprite.max[1] = (float_t)(SCREEN.height / SCREEN.scaleUi); - // shadermaterial_t skyboxMaterial = { - // .unlit = { .color = color(0xFF, 0x00, 0x00, 0xFF/2), .texture = NULL } - // }; - // errorChain(spriteBatchBuffer(&skyboxSprite, 1, &SHADER_UNLIT, skyboxMaterial)); - // errorChain(spriteBatchFlush()); - - errorOk(); -} - -void sceneOverworldCullUpdate(sceneoverworld_t *overworld) { - rpgCameraGetPosition(overworld->cullTarget); - - const float_t worldH = - (float_t)(SCREEN.height / SCREEN.scale3d) / TILE_SIZE_PIXELS; - const float_t worldW = worldH * SCREEN.aspect; - - overworld->cullHalfRangeX = - (worldW * 0.5f) + SCENE_OVERWORLD_CHUNK_CULL_SKIN_X; - overworld->cullHalfRangeY = - (worldH * 0.5f) + SCENE_OVERWORLD_CHUNK_CULL_SKIN_Y; -} - -bool_t sceneOverworldChunkShouldRender( - const sceneoverworld_t *overworld, - const chunk_t *chunk -) { - worldpos_t worldPos; - chunkPosToWorldPos(&chunk->position, &worldPos); - - const float_t chunkCenterX = (float_t)worldPos.x + (CHUNK_WIDTH * 0.5f); - const float_t chunkCenterY = (float_t)worldPos.y + (CHUNK_HEIGHT * 0.5f); - - if(fabsf(overworld->cullTarget[0] - chunkCenterX) > - overworld->cullHalfRangeX) return false; - if(fabsf(overworld->cullTarget[1] - chunkCenterY) > - overworld->cullHalfRangeY) return false; - - return true; -} - -bool_t sceneOverworldEntityShouldRender( - const sceneoverworld_t *overworld, - const entity_t *ent -) { - if(fabsf(overworld->cullTarget[0] - ent->renderPosition[0]) > - overworld->cullHalfRangeX) return false; - if(fabsf(overworld->cullTarget[1] - ent->renderPosition[1]) > - overworld->cullHalfRangeY) return false; - - return true; -} - -errorret_t sceneOverworldDrawEntity( - const sceneoverworld_t *overworld, - entity_t *ent -) { - if(!sceneOverworldEntityShouldRender(overworld, ent)) errorOk(); - - spritebatchsprite_t sprite; - glm_vec3_copy(ent->renderPosition, sprite.min); - glm_vec3_add(sprite.min, (vec3){ 0, -0.05f, 0.05f }, sprite.min);// Stop Fight - glm_vec3_copy(sprite.min, sprite.max); - glm_vec3_add(sprite.max, (vec3){ 1, 1, 0 }, sprite.max); - glm_vec2_copy((vec2){ 0, 0 }, sprite.uvMin); - glm_vec2_copy((vec2){ 1, 1 }, sprite.uvMax); - - color_t color; - switch(ent->direction) { - case ENTITY_DIR_NORTH: color = COLOR_YELLOW; break; - case ENTITY_DIR_EAST: color = COLOR_RED; break; - case ENTITY_DIR_SOUTH: color = COLOR_GREEN; break; - case ENTITY_DIR_WEST: color = COLOR_BLUE; break; - default: color = COLOR_CYAN; break; - } - - shadermaterial_t material = { - .unlit = { .color = color, .texture = NULL } - }; - errorChain(spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, material)); - errorChain(spriteBatchFlush()); - - errorOk(); -} - -errorret_t sceneOverworldDrawChunksBase(const sceneoverworld_t *overworld) { - for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { - chunk_t *chunk = MAP.chunkOrder[i]; - if(chunk == NULL) continue; - if(!sceneOverworldChunkShouldRender(overworld, chunk)) continue; - if(chunk->meshCount == 0) continue; - if(chunk->modelEntries[0] == NULL) continue; - if(chunk->modelEntries[0]->state != ASSET_ENTRY_STATE_LOADED) continue; - - assetmodeloutput_t *model = &chunk->modelEntries[0]->data.model; - if(model->meshEntry == NULL) continue; - - texture_t *tex = model->texEntry != NULL - ? &model->texEntry->data.texture - : NULL; - - shadermaterial_t mat = { - .unlit = { .color = model->color, .texture = tex } - }; - errorChain(shaderSetMatrix( - &SHADER_UNLIT, SHADER_UNLIT_MODEL, chunk->meshModels[0] - )); - errorChain(shaderSetMaterial(&SHADER_UNLIT, &mat)); - errorChain(meshDraw( - &model->meshEntry->data.mesh.mesh, 0, -1 - )); - } - - // Restore identity model so subsequent renders (e.g. entities) are - // not affected by the last chunk transform. - mat4 identity; - glm_mat4_identity(identity); - errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, identity)); - - errorOk(); -} - -errorret_t sceneOverworldDrawChunksProps(const sceneoverworld_t *overworld) { - for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { - chunk_t *chunk = MAP.chunkOrder[i]; - if(chunk == NULL) continue; - if(!sceneOverworldChunkShouldRender(overworld, chunk)) continue; - - for(uint8_t m = 1; m < chunk->meshCount; m++) { - if(chunk->modelEntries[m] == NULL) continue; - if(chunk->modelEntries[m]->state != ASSET_ENTRY_STATE_LOADED) continue; - - assetmodeloutput_t *model = &chunk->modelEntries[m]->data.model; - if(model->meshEntry == NULL) continue; - - texture_t *tex = model->texEntry != NULL - ? &model->texEntry->data.texture - : NULL; - - shadermaterial_t mat = { - .unlit = { .color = model->color, .texture = tex } - }; - errorChain(shaderSetMatrix( - &SHADER_UNLIT, SHADER_UNLIT_MODEL, chunk->meshModels[m] - )); - errorChain(shaderSetMaterial(&SHADER_UNLIT, &mat)); - errorChain(meshDraw( - &model->meshEntry->data.mesh.mesh, 0, -1 - )); - } - } - - // Restore identity model in case anything renders after props. - mat4 identity; - glm_mat4_identity(identity); - errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, identity)); - - errorOk(); -} - -errorret_t sceneOverworldDispose(scenedata_t *sceneData) { - assertNotNull(sceneData, "Scene data cannot be null"); - errorOk(); -} diff --git a/src/dusk/scene/overworld/sceneoverworld.h b/src/dusk/scene/overworld/sceneoverworld.h deleted file mode 100644 index 048e20d0..00000000 --- a/src/dusk/scene/overworld/sceneoverworld.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "scene/scenebase.h" -#include "rpg/overworld/chunk.h" -#include "rpg/entity/entity.h" - -typedef struct { - // Cached per-frame chunk culling bounds, refreshed by - // sceneOverworldCullUpdate() so sceneOverworldChunkShouldRender() - // does not need to recompute them for every chunk. - vec3 cullTarget; - float_t cullHalfRangeX; - float_t cullHalfRangeY; -} sceneoverworld_t; - -// Extra world-space margin, in tiles, added on top of the rough -// screen-size skin below - cheap insurance against the approximation -// culling a chunk that is actually still just in view. Y gets its own -// value since the camera's tilt makes the vertical check less exact. -#define SCENE_OVERWORLD_CHUNK_CULL_PADDING_X 8.0f -#define SCENE_OVERWORLD_CHUNK_CULL_PADDING_Y 4.0f - -// The camera is tilted between the ground-depth (Y) and height (Z) -// axes, so a chunk's on-screen vertical extent also depends on its Z -// layers. Rather than projecting every corner, fold that into a -// generous skin margin on the depth check. -#define SCENE_OVERWORLD_CHUNK_CULL_SKIN_X \ - ((CHUNK_WIDTH * 0.5f) + SCENE_OVERWORLD_CHUNK_CULL_PADDING_X) -#define SCENE_OVERWORLD_CHUNK_CULL_SKIN_Y \ - ((CHUNK_HEIGHT * 0.5f) + (CHUNK_DEPTH * WORLD_LAYER_HEIGHT) + \ - SCENE_OVERWORLD_CHUNK_CULL_PADDING_Y) - -/** - * Initialises the overworld scene. - * - * @param sceneData The scene data used for this scene. - * @return An error if the init failed, or errorOk() if it succeeded. - */ -errorret_t sceneOverworldInit(scenedata_t *sceneData); - -/** - * Updates the overworld scene. - * - * @param sceneData The scene data used for this scene. - * @return An error if the update failed, or errorOk() if it succeeded. - */ -errorret_t sceneOverworldUpdate(scenedata_t *sceneData); - -/** - * Refreshes the chunk culling bounds cached on the overworld scene data, - * from the current camera position and screen dimensions. Must be - * called once per frame before sceneOverworldChunkShouldRender(). - * - * @param overworld The overworld scene data to update. - */ -void sceneOverworldCullUpdate(sceneoverworld_t *overworld); - -/** - * Roughly checks whether a chunk falls within the visible screen area, - * based on chunk size and screen dimensions. Cheap approximation, not - * an exact frustum check - includes a generous skin margin to account - * for the camera's angle tilting height/depth onto the screen's - * vertical axis, so it may pass some chunks that are actually just out - * of view but will never wrongly cull one that is visible. - * - * @param overworld The overworld scene data holding the cached culling - * bounds, as refreshed by sceneOverworldCullUpdate(). - * @param chunk The chunk to check. - * @return true if the chunk should be rendered, false otherwise. - */ -bool_t sceneOverworldChunkShouldRender( - const sceneoverworld_t *overworld, - const chunk_t *chunk -); - -/** - * Draws the base (tile) mesh of every loaded chunk, with normal depth - * testing. Must be called before entities are rendered. - * - * @param overworld The overworld scene data holding the cached culling - * bounds, as refreshed by sceneOverworldCullUpdate(). - * @return An error if drawing failed, or errorOk() on success. - */ -errorret_t sceneOverworldDrawChunksBase(const sceneoverworld_t *overworld); - -/** - * Draws every loaded chunk's additional meshes (trees, buildings, etc), - * with normal depth testing so they correctly occlude entities standing - * beneath them. Must be called after entities are rendered. - * - * @param overworld The overworld scene data holding the cached culling - * bounds, as refreshed by sceneOverworldCullUpdate(). - * @return An error if drawing failed, or errorOk() on success. - */ -errorret_t sceneOverworldDrawChunksProps(const sceneoverworld_t *overworld); - -/** - * Roughly checks whether an entity falls within the visible screen - * area. Reuses the same cached chunk culling bounds, since an entity - * is just a point within that same space - deliberately cheap, a - * couple of subtractions and comparisons, since it runs per entity - * every frame and it is not worth spending more math than that to - * avoid drawing one that is slightly off-screen. - * - * @param overworld The overworld scene data holding the cached culling - * bounds, as refreshed by sceneOverworldCullUpdate(). - * @param ent The entity to check. - * @return true if the entity should be rendered, false otherwise. - */ -bool_t sceneOverworldEntityShouldRender( - const sceneoverworld_t *overworld, - const entity_t *ent -); - -/** - * Draws a single entity as a sprite, colored by its facing direction. - * Skips drawing (without error) if the entity should not render. - * - * @param overworld The overworld scene data holding the cached culling - * bounds, as refreshed by sceneOverworldCullUpdate(). - * @param ent The entity to draw. - * @return An error if drawing failed, or errorOk() on success. - */ -errorret_t sceneOverworldDrawEntity( - const sceneoverworld_t *overworld, - entity_t *ent -); - -/** - * Renders the overworld scene. - * - * @param sceneData The scene data used for this scene. - * @return An error if the render failed, or errorOk() if it succeeded. - */ -errorret_t sceneOverworldRender(scenedata_t *sceneData); - -/** - * Disposes the overworld scene. - * - * @param sceneData The scene data used for this scene. - * @return An error if the dispose failed, or errorOk() if it succeeded. - */ -errorret_t sceneOverworldDispose(scenedata_t *sceneData); \ No newline at end of file diff --git a/src/dusk/scene/scenetype.c b/src/dusk/scene/scenetype.c index da285e33..19498b91 100644 --- a/src/dusk/scene/scenetype.c +++ b/src/dusk/scene/scenetype.c @@ -9,19 +9,5 @@ scenecallbacks_t SCENE_TYPES[SCENE_TYPE_COUNT] = { [SCENE_TYPE_NULL] = { 0 }, - - [SCENE_TYPE_OVERWORLD] = { - .init = sceneOverworldInit, - .update = sceneOverworldUpdate, - .render = sceneOverworldRender, - .dispose = sceneOverworldDispose - }, - - [SCENE_TYPE_BATTLE] = { - .init = sceneBattleInit, - .update = sceneBattleUpdate, - .render = sceneBattleRender, - .dispose = sceneBattleDispose - }, }; diff --git a/src/dusk/scene/scenetype.h b/src/dusk/scene/scenetype.h index f3dd88bf..2b11a3bf 100644 --- a/src/dusk/scene/scenetype.h +++ b/src/dusk/scene/scenetype.h @@ -7,12 +7,9 @@ #pragma once #include "scene/scenebase.h" -#include "scene/overworld/sceneoverworld.h" -#include "scene/battle/scenebattle.h" typedef union scenedata_u { - sceneoverworld_t overworld; - scenebattle_t battle; + uint8_t _unused; } scenedata_t; typedef errorret_t (*scenecallback_t)(scenedata_t *); @@ -27,9 +24,6 @@ typedef struct { typedef enum { SCENE_TYPE_NULL, - SCENE_TYPE_OVERWORLD, - SCENE_TYPE_BATTLE, - SCENE_TYPE_COUNT } scenetype_t; diff --git a/src/dusk/ui/CMakeLists.txt b/src/dusk/ui/CMakeLists.txt index 26754f0d..eea2c400 100644 --- a/src/dusk/ui/CMakeLists.txt +++ b/src/dusk/ui/CMakeLists.txt @@ -4,11 +4,8 @@ # https://opensource.org/licenses/MIT add_subdirectory(debug) -add_subdirectory(frame) add_subdirectory(focus) add_subdirectory(overlay) -add_subdirectory(rpg) -add_subdirectory(transition) add_subdirectory(widget) # Sources diff --git a/src/dusk/ui/debug/CMakeLists.txt b/src/dusk/ui/debug/CMakeLists.txt index 74e31662..9d377628 100644 --- a/src/dusk/ui/debug/CMakeLists.txt +++ b/src/dusk/ui/debug/CMakeLists.txt @@ -7,5 +7,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC uiconsole.c uifps.c - uiplayerpos.c ) diff --git a/src/dusk/ui/debug/uiplayerpos.c b/src/dusk/ui/debug/uiplayerpos.c deleted file mode 100644 index 29cc8a75..00000000 --- a/src/dusk/ui/debug/uiplayerpos.c +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uiplayerpos.h" -#include "display/screen/screen.h" -#include "display/text/text.h" -#include "display/spritebatch/spritebatch.h" -#include "rpg/entity/entity.h" -#include "rpg/entity/entitytype.h" -#include "rpg/overworld/worldpos.h" - -errorret_t uiPlayerPosDraw() { - entity_t *player = NULL; - for(uint8_t i = 0; i < ENTITY_COUNT; i++) { - if(ENTITIES[i].type == ENTITY_TYPE_PLAYER) { - player = &ENTITIES[i]; - break; - } - } - if(!player) errorOk(); - - chunkpos_t chunkPos; - worldPosToChunkPos(&player->position, &chunkPos); - - char_t text[64]; - snprintf( - text, - sizeof(text), - "%d,%d,%d[%d,%d,%d]", - (int_t)player->position.x, - (int_t)player->position.y, - (int_t)player->position.z, - (int_t)chunkPos.x, - (int_t)chunkPos.y, - (int_t)chunkPos.z - ); - - float_t y = (float_t)SCREEN.scanY + - (float_t)FONT_DEFAULT.tileset->tileHeight; - errorChain(textDraw( - (float_t)SCREEN.scanX, y, text, COLOR_GREEN, &FONT_DEFAULT - )); - return spriteBatchFlush(); -} diff --git a/src/dusk/ui/debug/uiplayerpos.h b/src/dusk/ui/debug/uiplayerpos.h deleted file mode 100644 index 88cde124..00000000 --- a/src/dusk/ui/debug/uiplayerpos.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" - -/** - * Draws the player world and chunk position on screen. - * Searches for the first ENTITY_TYPE_PLAYER and renders: - * WORLDX,WORLDY,WORLDZ[chunkx,chunky,chunkz] - * - * @return Any error that occurs. - */ -errorret_t uiPlayerPosDraw(); diff --git a/src/dusk/ui/frame/CMakeLists.txt b/src/dusk/ui/frame/CMakeLists.txt deleted file mode 100644 index 906cf620..00000000 --- a/src/dusk/ui/frame/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uiframe.c - uiconfirm.c -) - -add_subdirectory(game) -add_subdirectory(settings) -add_subdirectory(battle) -add_subdirectory(backpack) diff --git a/src/dusk/ui/frame/backpack/CMakeLists.txt b/src/dusk/ui/frame/backpack/CMakeLists.txt deleted file mode 100644 index 570abb53..00000000 --- a/src/dusk/ui/frame/backpack/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uibackpack.c -) diff --git a/src/dusk/ui/frame/backpack/uibackpack.c b/src/dusk/ui/frame/backpack/uibackpack.c deleted file mode 100644 index d2cbddbf..00000000 --- a/src/dusk/ui/frame/backpack/uibackpack.c +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uibackpack.h" -#include "ui/frame/uiframe.h" -#include "rpg/item/backpack.h" -#include "util/memory.h" -#include "util/string.h" -#include "display/spritebatch/spritebatch.h" -#include "display/screen/screen.h" -#include "display/text/text.h" -#include "assert/assert.h" - -uibackpack_t UI_BACKPACK; - -void uiBackpackTabChanged( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - const itemtype_t type = (itemtype_t)(index + 1); - const inventory_t *inventory = backpackGetInventory(type); - - errorCatch(uiItemListSetItemStacks( - &UI_BACKPACK.itemList, inventory->storage, inventory->storageSize - )); -} - -void uiBackpackTabSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - uiItemListOpen(&UI_BACKPACK.itemList); -} - -errorret_t uiBackpackInit(void) { - memoryZero(&UI_BACKPACK, sizeof(uibackpack_t)); - - MENU_BEGIN( - &UI_BACKPACK.tabsMenu, UI_BACKPACK.tabs, - uiBackpackTabSelected, NULL, uiBackpackTabChanged - ); - for(uint8_t i = 0; i < UI_BACKPACK_TAB_COUNT; i++) { - stringFormat( - UI_BACKPACK.tabLabels[i], UI_BACKPACK_TAB_LABEL_MAX - 1, - "Category %u", i + 1 - ); - MENU_TAB(UI_BACKPACK.tabLabels[i]); - } - MENU_END(UI_BACKPACK.tabs, menuIndex); - - uiItemListInit( - &UI_BACKPACK.itemList, - UI_BACKPACK_ITEM_LIST_COLUMNS, UI_BACKPACK_ITEM_LIST_ROWS, 1, - NULL, NULL, NULL, NULL - ); - - errorOk(); -} - -errorret_t uiBackpackDraw(void) { - if(!uiMenuIsActive(&UI_BACKPACK.tabsMenu)) errorOk(); - - const float_t width = SCREEN.width; - const float_t height = SCREEN.height; - const float_t x = (float_t)SCREEN.scanX + - ((float_t)SCREEN.scanWidth - width) * 0.5f; - const float_t y = (float_t)SCREEN.scanY + - ((float_t)SCREEN.scanHeight - height) * 0.5f; - - errorChain(uiFrameDraw(x, y, width, height)); - - const float_t contentX = x + UI_FRAME_START_X; - const float_t contentY = y + UI_FRAME_START_Y; - const float_t contentWidth = width - (UI_FRAME_START_X * 2); - const float_t contentHeight = height - (UI_FRAME_START_Y * 2); - - errorChain(uiMenuDraw( - &UI_BACKPACK.tabsMenu, - contentX, - contentY, - contentWidth, - contentHeight - )); - - const float_t tabsRowHeight = (float_t)FONT_DEFAULT.tileset->tileHeight; - const float_t listY = contentY + tabsRowHeight + UI_FRAME_PADDING_Y; - - errorChain( - uiItemListDraw(&UI_BACKPACK.itemList, contentX, listY, contentWidth) - ); - - errorChain(spriteBatchFlush()); - errorOk(); -} - -bool_t uiBackpackIsOpen(void) { - return uiMenuIsActive(&UI_BACKPACK.tabsMenu); -} - -void uiBackpackOpen(void) { - uiMenuOpen(&UI_BACKPACK.tabsMenu); -} - -void uiBackpackClose(void) { - uiMenuClose(&UI_BACKPACK.tabsMenu); -} - -errorret_t uiBackpackDispose(void) { - errorOk(); -} diff --git a/src/dusk/ui/frame/backpack/uibackpack.h b/src/dusk/ui/frame/backpack/uibackpack.h deleted file mode 100644 index bbd56ee0..00000000 --- a/src/dusk/ui/frame/backpack/uibackpack.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "ui/widget/uimenu.h" -#include "ui/widget/uiitemlist.h" -#include "rpg/item/item.h" - -#define UI_BACKPACK_TAB_COUNT (ITEM_TYPE_COUNT - 1) -#define UI_BACKPACK_TAB_LABEL_MAX 32 -#define UI_BACKPACK_ITEM_LIST_COLUMNS 4 -#define UI_BACKPACK_ITEM_LIST_ROWS 5 - -typedef struct { - uimenu_t tabsMenu; - uimenuitem_t tabs[UI_BACKPACK_TAB_COUNT]; - char_t tabLabels[UI_BACKPACK_TAB_COUNT][UI_BACKPACK_TAB_LABEL_MAX]; - - uiitemlist_t itemList; -} uibackpack_t; - -extern uibackpack_t UI_BACKPACK; - -/** - * Initializes the backpack panel and its item type tabs. - * - * @return Any error that occurs. - */ -errorret_t uiBackpackInit(void); - -/** - * Draws the backpack panel. No-op when not visible. - * - * @return Any error that occurs. - */ -errorret_t uiBackpackDraw(void); - -/** - * Returns true when the backpack panel is currently open. - * - * @returns True if open. - */ -bool_t uiBackpackIsOpen(void); - -/** - * Opens the backpack panel. No-op when already open. - */ -void uiBackpackOpen(void); - -/** - * Closes the backpack panel. No-op when already closed. - */ -void uiBackpackClose(void); - -/** - * Disposes of the backpack panel. - * - * @return Any error that occurs. - */ -errorret_t uiBackpackDispose(void); diff --git a/src/dusk/ui/frame/battle/CMakeLists.txt b/src/dusk/ui/frame/battle/CMakeLists.txt deleted file mode 100644 index 4b6bd9e2..00000000 --- a/src/dusk/ui/frame/battle/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uibattlemenu.c -) diff --git a/src/dusk/ui/frame/battle/uibattlemenu.c b/src/dusk/ui/frame/battle/uibattlemenu.c deleted file mode 100644 index af947c1f..00000000 --- a/src/dusk/ui/frame/battle/uibattlemenu.c +++ /dev/null @@ -1,137 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uibattlemenu.h" -#include "ui/frame/uiframe.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" -#include "display/spritebatch/spritebatch.h" -#include "display/screen/screen.h" - -uibattlemenu_t UI_BATTLE_MENU; - -void uiBattleMenuTargetSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - battlePlayerAttack(UI_BATTLE_MENU.targetFighterIndex[index]); - uiMenuClose(&UI_BATTLE_MENU.targetMenu); - uiMenuClose(&UI_BATTLE_MENU.actionMenu); -} - -void uiBattleMenuOpenTargets(void) { - battlefighter_t *current = battleGetCurrentFighter(); - if(current == NULL) return; - - const battlefighterteam_t enemyTeam = - current->team == BATTLE_FIGHTER_TEAM_ALLY ? - BATTLE_FIGHTER_TEAM_ENEMY : BATTLE_FIGHTER_TEAM_ALLY; - - MENU_BEGIN( - &UI_BATTLE_MENU.targetMenu, UI_BATTLE_MENU.targetItems, - uiBattleMenuTargetSelected, NULL, NULL - ); - - for(uint8_t i = 0; i < BATTLE_FIGHTER_COUNT_MAX; i++) { - battlefighter_t *candidate = &BATTLE.fighters[i]; - if(candidate->team != enemyTeam) continue; - if(!battleFighterIsAlive(candidate)) continue; - - stringFormat( - UI_BATTLE_MENU.targetLabels[menuIndex], - UI_BATTLE_MENU_TARGET_LABEL_MAX - 1, - "Enemy %u (%u/%u HP)", - candidate->id, candidate->health, candidate->healthMax - ); - UI_BATTLE_MENU.targetFighterIndex[menuIndex] = i; - MENU_BUTTON(UI_BATTLE_MENU.targetLabels[menuIndex]); - } - - MENU_END(UI_BATTLE_MENU.targetItems, 1); - - uiMenuOpen(&UI_BATTLE_MENU.targetMenu); -} - -void uiBattleMenuActionSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - switch(index) { - case UI_BATTLE_MENU_ACTION_INDEX_ATTACK: - uiBattleMenuOpenTargets(); - break; - - case UI_BATTLE_MENU_ACTION_INDEX_FLEE: - battlePlayerFlee(); - uiMenuClose(&UI_BATTLE_MENU.actionMenu); - break; - - default: - break; - } -} - -errorret_t uiBattleMenuInit(void) { - memoryZero(&UI_BATTLE_MENU, sizeof(uibattlemenu_t)); - - MENU_BEGIN( - &UI_BATTLE_MENU.actionMenu, UI_BATTLE_MENU.actionItems, - uiBattleMenuActionSelected, NULL, NULL - ); - MENU_BUTTON("Attack"); - MENU_BUTTON("Flee"); - MENU_END(UI_BATTLE_MENU.actionItems, 1); - - errorOk(); -} - -errorret_t uiBattleMenuUpdate(void) { - if(uiMenuIsActive(&UI_BATTLE_MENU.actionMenu)) errorOk(); - - battlefighter_t *current = battleGetCurrentFighter(); - if(current == NULL) errorOk(); - if(current->controller != BATTLE_FIGHTER_CONTROLLER_PLAYER) errorOk(); - - uiMenuOpen(&UI_BATTLE_MENU.actionMenu); - errorOk(); -} - -errorret_t uiBattleMenuDraw(void) { - if(!uiMenuIsActive(&UI_BATTLE_MENU.actionMenu)) errorOk(); - - const float_t width = UI_BATTLE_MENU_WIDTH; - const float_t height = UI_BATTLE_MENU_HEIGHT; - const float_t x = (float_t)(SCREEN.scanX + SCREEN.scanWidth) - width; - const float_t y = (float_t)(SCREEN.scanY + SCREEN.scanHeight) - height; - - errorChain(uiFrameDraw(x, y, width, height)); - errorChain(uiMenuDraw( - &UI_BATTLE_MENU.actionMenu, - x + UI_FRAME_START_X, - y + UI_FRAME_START_Y, - width - (UI_FRAME_START_X * 2), - height - (UI_FRAME_START_Y * 2) - )); - - if(uiMenuIsActive(&UI_BATTLE_MENU.targetMenu)) { - const float_t targetY = y - height; - errorChain(uiFrameDraw(x, targetY, width, height)); - errorChain(uiMenuDraw( - &UI_BATTLE_MENU.targetMenu, - x + UI_FRAME_START_X, - targetY + UI_FRAME_START_Y, - width - (UI_FRAME_START_X * 2), - height - (UI_FRAME_START_Y * 2) - )); - } - - errorChain(spriteBatchFlush()); - errorOk(); -} diff --git a/src/dusk/ui/frame/battle/uibattlemenu.h b/src/dusk/ui/frame/battle/uibattlemenu.h deleted file mode 100644 index 024d5d6e..00000000 --- a/src/dusk/ui/frame/battle/uibattlemenu.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "ui/widget/uimenu.h" -#include "rpg/battle/battle.h" - -#define UI_BATTLE_MENU_ACTION_ITEM_COUNT 2 -#define UI_BATTLE_MENU_ACTION_INDEX_ATTACK 0 -#define UI_BATTLE_MENU_ACTION_INDEX_FLEE 1 - -#define UI_BATTLE_MENU_TARGET_ITEM_COUNT BATTLE_FIGHTER_COUNT_MAX -#define UI_BATTLE_MENU_TARGET_LABEL_MAX 32 - -#define UI_BATTLE_MENU_WIDTH 160.0f -#define UI_BATTLE_MENU_HEIGHT 96.0f - -typedef struct { - uimenu_t actionMenu; - uimenuitem_t actionItems[UI_BATTLE_MENU_ACTION_ITEM_COUNT]; - - uimenu_t targetMenu; - uimenuitem_t targetItems[UI_BATTLE_MENU_TARGET_ITEM_COUNT]; - uint8_t targetFighterIndex[UI_BATTLE_MENU_TARGET_ITEM_COUNT]; - char_t targetLabels[UI_BATTLE_MENU_TARGET_ITEM_COUNT] - [UI_BATTLE_MENU_TARGET_LABEL_MAX]; -} uibattlemenu_t; - -extern uibattlemenu_t UI_BATTLE_MENU; - -/** - * Initializes the battle action/target menus. - * - * @return Any error that occurs. - */ -errorret_t uiBattleMenuInit(void); - -/** - * Updates the battle menu: opens the action menu whenever it becomes a - * player-controlled fighter's turn. - * - * @return Any error that occurs. - */ -errorret_t uiBattleMenuUpdate(void); - -/** - * Draws the battle action menu, and the target menu above it when - * open. No-op when the action menu isn't active. - * - * @return Any error that occurs. - */ -errorret_t uiBattleMenuDraw(void); diff --git a/src/dusk/ui/frame/game/CMakeLists.txt b/src/dusk/ui/frame/game/CMakeLists.txt deleted file mode 100644 index 4b79eda6..00000000 --- a/src/dusk/ui/frame/game/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uigamemenu.c -) diff --git a/src/dusk/ui/frame/game/uigamemenu.c b/src/dusk/ui/frame/game/uigamemenu.c deleted file mode 100644 index bfdb2203..00000000 --- a/src/dusk/ui/frame/game/uigamemenu.c +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uigamemenu.h" -#include "ui/frame/uiframe.h" -#include "ui/frame/settings/uisettings.h" -#include "ui/frame/backpack/uibackpack.h" -#include "util/memory.h" -#include "display/spritebatch/spritebatch.h" -#include "display/screen/screen.h" -#include "assert/assert.h" -#include "locale/localemanager.h" -#include "asset/loader/locale/assetlocaleloader.h" - -#define UI_GAME_MENU_INDEX_CHARACTERS 0 -#define UI_GAME_MENU_INDEX_ITEMS 1 -#define UI_GAME_MENU_INDEX_SETTINGS 2 - -uigamemenu_t UI_GAME_MENU; - -void uiGameMenuSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - if(index == UI_GAME_MENU_INDEX_ITEMS) uiBackpackOpen(); - if(index == UI_GAME_MENU_INDEX_SETTINGS) uiSettingsOpen(); -} - -errorret_t uiGameMenuInit(void) { - memoryZero(&UI_GAME_MENU, sizeof(uigamemenu_t)); - - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.game_menu.characters", - 0, - UI_GAME_MENU.charactersLabel, - UI_GAME_MENU_LABEL_MAX - )); - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.game_menu.items", - 0, - UI_GAME_MENU.itemsLabel, - UI_GAME_MENU_LABEL_MAX - )); - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.game_menu.settings", - 0, - UI_GAME_MENU.settingsLabel, - UI_GAME_MENU_LABEL_MAX - )); - - MENU_BEGIN( - &UI_GAME_MENU.menu, UI_GAME_MENU.items, uiGameMenuSelected, NULL, NULL - ); - MENU_BUTTON(UI_GAME_MENU.charactersLabel); - MENU_BUTTON(UI_GAME_MENU.itemsLabel); - MENU_BUTTON(UI_GAME_MENU.settingsLabel); - - MENU_END(UI_GAME_MENU.items, 1); - - errorOk(); -} - -errorret_t uiGameMenuDraw(void) { - if(!uiMenuIsActive(&UI_GAME_MENU.menu)) errorOk(); - - const float_t width = UI_GAME_MENU_WIDTH; - const float_t height = (float_t)SCREEN.scanHeight; - const float_t x = (float_t)(SCREEN.scanX + SCREEN.scanWidth) - width; - const float_t y = (float_t)SCREEN.scanY; - - errorChain(uiFrameDraw(x, y, width, height)); - errorChain(uiMenuDraw( - &UI_GAME_MENU.menu, - x + UI_FRAME_START_X, - y + UI_FRAME_START_Y, - width - (UI_FRAME_START_X * 2), - height - (UI_FRAME_START_Y * 2) - )); - - errorChain(spriteBatchFlush()); - errorOk(); -} - -bool_t uiGameMenuIsOpen(void) { - return uiMenuIsActive(&UI_GAME_MENU.menu); -} - -void uiGameMenuOpen() { - uiMenuOpen(&UI_GAME_MENU.menu); -} - -void uiGameMenuClose() { - uiMenuClose(&UI_GAME_MENU.menu); -} - -errorret_t uiGameMenuDispose(void) { - errorOk(); -} diff --git a/src/dusk/ui/frame/game/uigamemenu.h b/src/dusk/ui/frame/game/uigamemenu.h deleted file mode 100644 index ce6307fe..00000000 --- a/src/dusk/ui/frame/game/uigamemenu.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "ui/widget/uimenu.h" - -#define UI_GAME_MENU_ITEM_COUNT 3 -#define UI_GAME_MENU_WIDTH 150.0f -#define UI_GAME_MENU_LABEL_MAX 32 - -typedef struct { - uimenu_t menu; - uimenuitem_t items[UI_GAME_MENU_ITEM_COUNT]; - char_t charactersLabel[UI_GAME_MENU_LABEL_MAX]; - char_t itemsLabel[UI_GAME_MENU_LABEL_MAX]; - char_t settingsLabel[UI_GAME_MENU_LABEL_MAX]; -} uigamemenu_t; - -extern uigamemenu_t UI_GAME_MENU; - -/** - * Initializes the game menu panel. - * - * @return Any error that occurs. - */ -errorret_t uiGameMenuInit(void); - -/** - * Draws the game menu panel. No-op when not visible. - * - * @return Any error that occurs. - */ -errorret_t uiGameMenuDraw(void); - -/** - * Returns true when the game menu panel is currently open. - * - * @returns True if open. - */ -bool_t uiGameMenuIsOpen(void); - -/** - * Opens the game menu panel. No-op when already open. - */ -void uiGameMenuOpen(); - -/** - * Closes the game menu panel. No-op when already closed. - */ -void uiGameMenuClose(); - -/** - * Disposes of the game menu panel. - * - * @return Any error that occurs. - */ -errorret_t uiGameMenuDispose(void); diff --git a/src/dusk/ui/frame/settings/CMakeLists.txt b/src/dusk/ui/frame/settings/CMakeLists.txt deleted file mode 100644 index f0e4b1c2..00000000 --- a/src/dusk/ui/frame/settings/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uisettings.c - uisettingsgeneral.c - uisettingsinput.c - uisettingsdisplay.c - uisettingsaudio.c -) diff --git a/src/dusk/ui/frame/settings/uisettings.c b/src/dusk/ui/frame/settings/uisettings.c deleted file mode 100644 index 23b496e5..00000000 --- a/src/dusk/ui/frame/settings/uisettings.c +++ /dev/null @@ -1,250 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uisettings.h" -#include "uisettingsgeneral.h" -#include "uisettingsinput.h" -#include "uisettingsdisplay.h" -#include "uisettingsaudio.h" -#include "ui/frame/uiframe.h" -#include "ui/frame/uiconfirm.h" -#include "util/memory.h" -#include "display/spritebatch/spritebatch.h" -#include "display/text/text.h" -#include "display/screen/screen.h" -#include "assert/assert.h" -#include "locale/localemanager.h" -#include "asset/loader/locale/assetlocaleloader.h" - -uisettings_t UI_SETTINGS; - -uisettingstabdef_t UI_SETTINGS_TAB_DEFS[UI_SETTINGS_TAB_COUNT] = { - { - .localeId = "ui.settings.tabs.general", - .init = uiSettingsGeneralInit, - .menu = (uimenu_t *)&UI_SETTINGS.data, - .load = uiSettingsGeneralLoad, - .apply = uiSettingsGeneralApply, - .hasChanges = uiSettingsGeneralHasChanges - }, - - { - .localeId = "ui.settings.tabs.input", - .init = uiSettingsInputInit, - .menu = (uimenu_t *)&UI_SETTINGS.data, - .load = uiSettingsInputLoad, - .apply = uiSettingsInputApply, - .hasChanges = uiSettingsInputHasChanges - }, - - { - .localeId = "ui.settings.tabs.display", - .init = uiSettingsDisplayInit, - .menu = (uimenu_t *)&UI_SETTINGS.data, - .load = uiSettingsDisplayLoad, - .apply = uiSettingsDisplayApply, - .hasChanges = uiSettingsDisplayHasChanges - }, - - { - .localeId = "ui.settings.tabs.audio", - .init = uiSettingsAudioInit, - .menu = (uimenu_t *)&UI_SETTINGS.data, - .load = uiSettingsAudioLoad, - .apply = uiSettingsAudioApply, - .hasChanges = uiSettingsAudioHasChanges - } -}; - -static uisettingstabdef_t UI_SETTINGS_TOP_DEF = { - .menu = &UI_SETTINGS.tabsMenu, - .load = uiSettingsLoad, - .hasChanges = uiSettingsHasChanges -}; - -static uisettingstabdef_t *UI_SETTINGS_PENDING_DISCARD = NULL; -static uisettingstabdef_t *UI_SETTINGS_ACTIVE_TAB = NULL; - -errorret_t uiSettingsActivateTab(uisettingstabdef_t *def) { - if(def == UI_SETTINGS_ACTIVE_TAB) errorOk(); - - errorChain(def->init(&UI_SETTINGS.data)); - def->menu->user = def; - def->load(); - UI_SETTINGS_ACTIVE_TAB = def; - - errorOk(); -} - -void uiSettingsTabChanged( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - if(index >= UI_SETTINGS_TAB_COUNT) return; - errorCatch(uiSettingsActivateTab(&UI_SETTINGS_TAB_DEFS[index])); -} - -void uiSettingsTabSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - if(index >= UI_SETTINGS_TAB_COUNT) return; - - uisettingstabdef_t *def = &UI_SETTINGS_TAB_DEFS[index]; - errorCatch(uiSettingsActivateTab(def)); - uiMenuOpen(def->menu); -} - -errorret_t uiSettingsInit(void) { - memoryZero(&UI_SETTINGS, sizeof(uisettings_t)); - UI_SETTINGS_ACTIVE_TAB = NULL; - - for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) { - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - UI_SETTINGS_TAB_DEFS[i].localeId, - 0, - UI_SETTINGS.tabLabels[i], - UI_SETTINGS_TAB_LABEL_MAX - )); - } - - MENU_BEGIN( - &UI_SETTINGS.tabsMenu, UI_SETTINGS.tabs, uiSettingsTabSelected, - uiSettingsDiscardMenuClosed, uiSettingsTabChanged - ); - for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) { - MENU_TAB(UI_SETTINGS.tabLabels[i]); - } - MENU_END(UI_SETTINGS.tabs, menuIndex); - - UI_SETTINGS.tabsMenu.user = &UI_SETTINGS_TOP_DEF; - - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.settings.apply", - 0, - UI_SETTINGS.applyLabel, - UI_SETTINGS_APPLY_LABEL_MAX - )); - - errorChain(uiSettingsActivateTab(&UI_SETTINGS_TAB_DEFS[0])); - - errorOk(); -} - -errorret_t uiSettingsDraw(void) { - if(!uiMenuIsActive(&UI_SETTINGS.tabsMenu)) errorOk(); - - const float_t width = SCREEN.width; - const float_t height = SCREEN.height; - const float_t x = (float_t)SCREEN.scanX + - ((float_t)SCREEN.scanWidth - width) * 0.5f; - const float_t y = (float_t)SCREEN.scanY + - ((float_t)SCREEN.scanHeight - height) * 0.5f; - - errorChain(uiFrameDraw(x, y, width, height)); - - const float_t contentX = x + UI_FRAME_START_X; - const float_t contentY = y + UI_FRAME_START_Y; - const float_t contentWidth = width - (UI_FRAME_START_X * 2); - const float_t contentHeight = height - (UI_FRAME_START_Y * 2); - - errorChain(uiMenuDraw( - &UI_SETTINGS.tabsMenu, - contentX, - contentY, - contentWidth, - contentHeight - )); - - const float_t tabsRowHeight = (float_t)FONT_DEFAULT.tileset->tileHeight; - const float_t pageY = contentY + tabsRowHeight + UI_FRAME_PADDING_Y; - const float_t pageHeight = contentHeight - tabsRowHeight - UI_FRAME_PADDING_Y; - - if(UI_SETTINGS_ACTIVE_TAB != NULL) { - errorChain(uiMenuDraw( - UI_SETTINGS_ACTIVE_TAB->menu, contentX, pageY, contentWidth, pageHeight - )); - } - - errorChain(spriteBatchFlush()); - errorOk(); -} - -errorret_t uiSettingsUpdate(void) { - if(!UI_SETTINGS_PENDING_DISCARD) errorOk(); - - uisettingstabdef_t *def = UI_SETTINGS_PENDING_DISCARD; - UI_SETTINGS_PENDING_DISCARD = NULL; - - return uiSettingsDiscardUpdate(def); -} - -bool_t uiSettingsIsOpen(void) { - return uiMenuIsActive(&UI_SETTINGS.tabsMenu); -} - -void uiSettingsOpen() { - uiSettingsLoad(); - uiMenuOpen(&UI_SETTINGS.tabsMenu); -} - -void uiSettingsClose() { - uiMenuClose(&UI_SETTINGS.tabsMenu); -} - -errorret_t uiSettingsDispose(void) { - errorOk(); -} - -void uiSettingsLoad(void) { - if(UI_SETTINGS_ACTIVE_TAB != NULL) UI_SETTINGS_ACTIVE_TAB->load(); -} - -void uiSettingsApply(void) { - if(UI_SETTINGS_ACTIVE_TAB != NULL) UI_SETTINGS_ACTIVE_TAB->apply(); -} - -bool_t uiSettingsHasChanges(void) { - return UI_SETTINGS_ACTIVE_TAB != NULL && UI_SETTINGS_ACTIVE_TAB->hasChanges(); -} - -void uiSettingsDiscardMenuClosed(const uimenu_t *menu) { - uisettingstabdef_t *def = (uisettingstabdef_t *)menu->user; - if(def->hasChanges()) UI_SETTINGS_PENDING_DISCARD = def; -} - -errorret_t uiSettingsDiscardUpdate(uisettingstabdef_t *def) { - #define UI_SETTINGS_DISCARD_TEXT_MAX 128 - char_t text[UI_SETTINGS_DISCARD_TEXT_MAX]; - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.confirm.discard_changes", - 0, - text, - UI_SETTINGS_DISCARD_TEXT_MAX - )); - #undef UI_SETTINGS_DISCARD_TEXT_MAX - - uiConfirmOpen(text, uiSettingsDiscardConfirmResult, def); - - errorOk(); -} - -void uiSettingsDiscardConfirmResult(const bool_t result, void *user) { - uisettingstabdef_t *def = (uisettingstabdef_t *)user; - - if(!result) { - uiMenuOpen(def->menu); - return; - } - - def->load(); -} diff --git a/src/dusk/ui/frame/settings/uisettings.h b/src/dusk/ui/frame/settings/uisettings.h deleted file mode 100644 index 6b41f568..00000000 --- a/src/dusk/ui/frame/settings/uisettings.h +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "ui/widget/uimenu.h" -#include "uisettingsdata.h" - -#define UI_SETTINGS_TAB_COUNT 4 -#define UI_SETTINGS_TAB_LABEL_MAX 32 -#define UI_SETTINGS_APPLY_LABEL_MAX 32 - -typedef struct { - const char_t *localeId; - errorret_t (*init)(uisettingsdata_t *data); - uimenu_t *menu; - void (*load)(void); - void (*apply)(void); - bool_t (*hasChanges)(void); -} uisettingstabdef_t; - -typedef struct { - uimenu_t tabsMenu; - uimenuitem_t tabs[UI_SETTINGS_TAB_COUNT]; - char_t tabLabels[UI_SETTINGS_TAB_COUNT][UI_SETTINGS_TAB_LABEL_MAX]; - char_t applyLabel[UI_SETTINGS_APPLY_LABEL_MAX]; - uisettingsdata_t data; -} uisettings_t; - -extern uisettings_t UI_SETTINGS; -extern uisettingstabdef_t UI_SETTINGS_TAB_DEFS[UI_SETTINGS_TAB_COUNT]; - -/** - * Menu closed callback that flags a pending discard-changes - * confirmation if the menu's settings page/panel reports unsaved - * changes. Pass this directly as a settings page menu's closed - * callback. The pending def is picked up by uiSettingsUpdate on the - * next tick. - * - * @param menu The menu that was just closed. - */ -void uiSettingsDiscardMenuClosed(const uimenu_t *menu); - -/** - * Shows the discard-changes confirmation dialog for def. Called once - * by uiSettingsUpdate when uiSettingsDiscardMenuClosed has flagged a - * pending def. - * - * @param def The tab/panel def to show the confirmation for. - * @return Any error that occurs. - */ -errorret_t uiSettingsDiscardUpdate(uisettingstabdef_t *def); - -/** - * Callback passed to uiConfirmOpen by uiSettingsDiscardUpdate. Reopens - * the menu if the user chose to keep editing, otherwise reloads the - * widgets back to the actual engine values. - * - * @param result True if the user confirmed discarding changes, false - * to keep editing. - * @param user The uisettingstabdef_t* this confirmation belongs to. - */ -void uiSettingsDiscardConfirmResult(const bool_t result, void *user); - -/** - * Initializes the settings panel and all of its category pages. - * - * @return Any error that occurs. - */ -errorret_t uiSettingsInit(void); - -/** - * Draws the settings panel. No-op when not visible. - * - * @return Any error that occurs. - */ -errorret_t uiSettingsDraw(void); - -/** - * Updates the settings panel. Shows a discard-changes confirmation if - * the panel was just closed with unsaved changes. - * - * @return Any error that occurs. - */ -errorret_t uiSettingsUpdate(void); - -/** - * Returns true when the settings panel is currently open. - * - * @returns True if open. - */ -bool_t uiSettingsIsOpen(void); - -/** - * Opens the settings panel. No-op when already open. - */ -void uiSettingsOpen(); - -/** - * Closes the settings panel. No-op when already closed. - */ -void uiSettingsClose(); - -/** - * Disposes of the settings panel. - * - * @return Any error that occurs. - */ -errorret_t uiSettingsDispose(void); - -/** - * Loads every category page's widgets from the current engine settings. - * Called automatically by uiSettingsOpen. - */ -void uiSettingsLoad(void); - -/** - * Applies every category page's widget values to the engine settings. - * Called automatically when a page's own Apply button is pressed. - */ -void uiSettingsApply(void); - -/** - * Returns whether any category page has a widget value that differs - * from what was loaded. - * - * @returns True if there are unsaved changes. - */ -bool_t uiSettingsHasChanges(void); diff --git a/src/dusk/ui/frame/settings/uisettingsaudio.c b/src/dusk/ui/frame/settings/uisettingsaudio.c deleted file mode 100644 index 0d968cc1..00000000 --- a/src/dusk/ui/frame/settings/uisettingsaudio.c +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uisettingsaudio.h" -#include "uisettings.h" -#include "assert/assert.h" -#include "util/memory.h" - -void uiSettingsAudioSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - if(index != UI_SETTINGS_AUDIO_INDEX_APPLY) return; - uiSettingsAudioApply(); -} - -errorret_t uiSettingsAudioInit(uisettingsdata_t *data) { - uisettingsaudio_t *audio = &data->audio; - memoryZero(audio, sizeof(uisettingsaudio_t)); - - MENU_BEGIN( - &audio->menu, audio->items, - uiSettingsAudioSelected, uiSettingsDiscardMenuClosed, NULL - ); - MENU_LABEL("No audio settings yet"); - MENU_BUTTON(UI_SETTINGS.applyLabel); - - MENU_END(audio->items, 1); - - errorOk(); -} - -void uiSettingsAudioLoad(void) { -} - -void uiSettingsAudioApply(void) { - uiMenuClose(&UI_SETTINGS.data.audio.menu); -} - -bool_t uiSettingsAudioHasChanges(void) { - return false; -} diff --git a/src/dusk/ui/frame/settings/uisettingsaudio.h b/src/dusk/ui/frame/settings/uisettingsaudio.h deleted file mode 100644 index 04f8a605..00000000 --- a/src/dusk/ui/frame/settings/uisettingsaudio.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "uisettingsdata.h" - -/** - * Initializes the audio settings page into the shared settings data - * union. - * - * @param data The shared settings data union to initialize into. - * @return Any error that occurs. - */ -errorret_t uiSettingsAudioInit(uisettingsdata_t *data); - -/** - * Loads the page's widgets from the current engine audio settings. - */ -void uiSettingsAudioLoad(void); - -/** - * Applies the page's widget values to the engine audio settings. - */ -void uiSettingsAudioApply(void); - -/** - * Returns whether any widget's value differs from what was loaded. - * - * @returns True if there are unsaved changes. - */ -bool_t uiSettingsAudioHasChanges(void); diff --git a/src/dusk/ui/frame/settings/uisettingsdata.h b/src/dusk/ui/frame/settings/uisettingsdata.h deleted file mode 100644 index 511b0f04..00000000 --- a/src/dusk/ui/frame/settings/uisettingsdata.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "ui/widget/uimenu.h" - -#define UI_SETTINGS_GENERAL_ITEM_COUNT 3 -#define UI_SETTINGS_GENERAL_INDEX_LANGUAGE 0 -#define UI_SETTINGS_GENERAL_INDEX_LANGUAGE_DETAIL 1 -#define UI_SETTINGS_GENERAL_INDEX_APPLY 2 -#define UI_SETTINGS_GENERAL_LOCALE_COUNT 3 -#define UI_SETTINGS_GENERAL_LABEL_MAX 32 -#define UI_SETTINGS_GENERAL_INFO_MAX 64 - -typedef struct { - uimenu_t menu; - uimenuitem_t items[UI_SETTINGS_GENERAL_ITEM_COUNT]; - const char_t *localeNames[UI_SETTINGS_GENERAL_LOCALE_COUNT]; - char_t languageLabel[UI_SETTINGS_GENERAL_LABEL_MAX]; - char_t labelInfo[UI_SETTINGS_GENERAL_INFO_MAX]; -} uisettingsgeneral_t; - -#define UI_SETTINGS_INPUT_ITEM_COUNT 2 -#define UI_SETTINGS_INPUT_LABEL_MAX 32 -#define UI_SETTINGS_INPUT_INDEX_DEADZONE 0 -#define UI_SETTINGS_INPUT_INDEX_APPLY 1 - -typedef struct { - uimenu_t menu; - uimenuitem_t items[UI_SETTINGS_INPUT_ITEM_COUNT]; - char_t deadzoneLabel[UI_SETTINGS_INPUT_LABEL_MAX]; -} uisettingsinput_t; - -#define UI_SETTINGS_DISPLAY_ITEM_COUNT 2 -#define UI_SETTINGS_DISPLAY_INDEX_APPLY 1 - -typedef struct { - uimenu_t menu; - uimenuitem_t items[UI_SETTINGS_DISPLAY_ITEM_COUNT]; -} uisettingsdisplay_t; - -#define UI_SETTINGS_AUDIO_ITEM_COUNT 2 -#define UI_SETTINGS_AUDIO_INDEX_APPLY 1 - -typedef struct { - uimenu_t menu; - uimenuitem_t items[UI_SETTINGS_AUDIO_ITEM_COUNT]; -} uisettingsaudio_t; - -/** - * Shared, overlapping storage for every settings tab's page data. Only - * one member is ever live at a time -- the active tab's Init writes - * into it, overwriting whatever the previously active tab left there. - * This trades simultaneous access to every tab for a memory footprint - * of only the single largest page. - */ -typedef union { - uisettingsgeneral_t general; - uisettingsinput_t input; - uisettingsdisplay_t display; - uisettingsaudio_t audio; -} uisettingsdata_t; diff --git a/src/dusk/ui/frame/settings/uisettingsdisplay.c b/src/dusk/ui/frame/settings/uisettingsdisplay.c deleted file mode 100644 index 75e60d8b..00000000 --- a/src/dusk/ui/frame/settings/uisettingsdisplay.c +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uisettingsdisplay.h" -#include "uisettings.h" -#include "assert/assert.h" -#include "util/memory.h" - -void uiSettingsDisplaySelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - if(index != UI_SETTINGS_DISPLAY_INDEX_APPLY) return; - uiSettingsDisplayApply(); -} - -errorret_t uiSettingsDisplayInit(uisettingsdata_t *data) { - uisettingsdisplay_t *display = &data->display; - memoryZero(display, sizeof(uisettingsdisplay_t)); - - MENU_BEGIN( - &display->menu, display->items, - uiSettingsDisplaySelected, uiSettingsDiscardMenuClosed, NULL - ); - MENU_LABEL("No display settings yet"); - MENU_BUTTON(UI_SETTINGS.applyLabel); - - MENU_END(display->items, 1); - - errorOk(); -} - -void uiSettingsDisplayLoad(void) { -} - -void uiSettingsDisplayApply(void) { - uiMenuClose(&UI_SETTINGS.data.display.menu); -} - -bool_t uiSettingsDisplayHasChanges(void) { - return false; -} diff --git a/src/dusk/ui/frame/settings/uisettingsdisplay.h b/src/dusk/ui/frame/settings/uisettingsdisplay.h deleted file mode 100644 index 5811db0f..00000000 --- a/src/dusk/ui/frame/settings/uisettingsdisplay.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "uisettingsdata.h" - -/** - * Initializes the display settings page into the shared settings data - * union. - * - * @param data The shared settings data union to initialize into. - * @return Any error that occurs. - */ -errorret_t uiSettingsDisplayInit(uisettingsdata_t *data); - -/** - * Loads the page's widgets from the current engine display settings. - */ -void uiSettingsDisplayLoad(void); - -/** - * Applies the page's widget values to the engine display settings. - */ -void uiSettingsDisplayApply(void); - -/** - * Returns whether any widget's value differs from what was loaded. - * - * @returns True if there are unsaved changes. - */ -bool_t uiSettingsDisplayHasChanges(void); diff --git a/src/dusk/ui/frame/settings/uisettingsgeneral.c b/src/dusk/ui/frame/settings/uisettingsgeneral.c deleted file mode 100644 index d4c44594..00000000 --- a/src/dusk/ui/frame/settings/uisettingsgeneral.c +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uisettingsgeneral.h" -#include "uisettings.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" -#include "locale/localemanager.h" -#include "locale/localeinfo.h" -#include "asset/loader/locale/assetlocaleloader.h" - -static const localeinfo_t *const UI_SETTINGS_GENERAL_LOCALES[ - UI_SETTINGS_GENERAL_LOCALE_COUNT -] = { - &LOCALE_EN_US, - &LOCALE_JP_JP, - &LOCALE_ES_MX -}; - -void uiSettingsGeneralSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - switch(index) { - case UI_SETTINGS_GENERAL_INDEX_APPLY: - uiSettingsGeneralApply(); - break; - - default: - break; - } -} - -errorret_t uiSettingsGeneralInit(uisettingsdata_t *data) { - uisettingsgeneral_t *general = &data->general; - memoryZero(general, sizeof(uisettingsgeneral_t)); - - for(uint8_t i = 0; i < UI_SETTINGS_GENERAL_LOCALE_COUNT; i++) { - general->localeNames[i] = UI_SETTINGS_GENERAL_LOCALES[i]->name; - } - - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.settings.general.language", - 0, - general->languageLabel, - UI_SETTINGS_GENERAL_LABEL_MAX - )); - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.settings.general.language_detail", - 0, - general->labelInfo, - UI_SETTINGS_GENERAL_INFO_MAX - )); - - MENU_BEGIN( - &general->menu, general->items, - uiSettingsGeneralSelected, uiSettingsDiscardMenuClosed, NULL - ); - - MENU_DROPDOWN( - general->languageLabel, general->localeNames, - UI_SETTINGS_GENERAL_LOCALE_COUNT, 0 - ); - MENU_LABEL(general->labelInfo); - - MENU_BUTTON(UI_SETTINGS.applyLabel); - MENU_END(general->items, 1); - - errorOk(); -} - -void uiSettingsGeneralLoad(void) { - uisettingsgeneral_t *general = &UI_SETTINGS.data.general; - - uint8_t index = 0; - for(uint8_t i = 0; i < UI_SETTINGS_GENERAL_LOCALE_COUNT; i++) { - if(stringCompare(LOCALE.locale->file, UI_SETTINGS_GENERAL_LOCALES[i]->file) != 0) { - continue; - } - index = i; - break; - } - - uiDropdownSetSelectedIndex( - &general->items[UI_SETTINGS_GENERAL_INDEX_LANGUAGE].dropdown, index - ); -} - -void uiSettingsGeneralApply(void) { - uisettingsgeneral_t *general = &UI_SETTINGS.data.general; - - uint8_t index = uiDropdownGetSelectedIndex( - &general->items[UI_SETTINGS_GENERAL_INDEX_LANGUAGE].dropdown - ); - errorCatch(localeManagerSetLocale(UI_SETTINGS_GENERAL_LOCALES[index])); - - uiMenuClose(&general->menu); -} - -bool_t uiSettingsGeneralHasChanges(void) { - uisettingsgeneral_t *general = &UI_SETTINGS.data.general; - - uint8_t index = uiDropdownGetSelectedIndex( - &general->items[UI_SETTINGS_GENERAL_INDEX_LANGUAGE].dropdown - ); - return stringCompare( - LOCALE.locale->file, UI_SETTINGS_GENERAL_LOCALES[index]->file - ) != 0; -} diff --git a/src/dusk/ui/frame/settings/uisettingsgeneral.h b/src/dusk/ui/frame/settings/uisettingsgeneral.h deleted file mode 100644 index 47dbf8ee..00000000 --- a/src/dusk/ui/frame/settings/uisettingsgeneral.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "uisettingsdata.h" - -/** - * Initializes the general settings page into the shared settings data - * union. - * - * @param data The shared settings data union to initialize into. - * @return Any error that occurs. - */ -errorret_t uiSettingsGeneralInit(uisettingsdata_t *data); - -/** - * Loads the page's widgets from the current engine general settings. - */ -void uiSettingsGeneralLoad(void); - -/** - * Applies the page's widget values to the engine general settings. - */ -void uiSettingsGeneralApply(void); - -/** - * Returns whether any widget's value differs from what was loaded. - * - * @returns True if there are unsaved changes. - */ -bool_t uiSettingsGeneralHasChanges(void); diff --git a/src/dusk/ui/frame/settings/uisettingsinput.c b/src/dusk/ui/frame/settings/uisettingsinput.c deleted file mode 100644 index 287329cd..00000000 --- a/src/dusk/ui/frame/settings/uisettingsinput.c +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uisettingsinput.h" -#include "uisettings.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "locale/localemanager.h" -#include "asset/loader/locale/assetlocaleloader.h" -#include "input/input.h" - -void uiSettingsInputSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - if(index != UI_SETTINGS_INPUT_INDEX_APPLY) return; - uiSettingsInputApply(); -} - -errorret_t uiSettingsInputInit(uisettingsdata_t *data) { - uisettingsinput_t *input = &data->input; - memoryZero(input, sizeof(uisettingsinput_t)); - - MENU_BEGIN( - &input->menu, input->items, - uiSettingsInputSelected, uiSettingsDiscardMenuClosed, NULL - ); - #ifdef DUSK_INPUT_GAMEPAD - errorChain(assetLocaleGetString( - &LOCALE.entry->data.locale, - "ui.settings.input.deadzone", - 0, - input->deadzoneLabel, - UI_SETTINGS_INPUT_LABEL_MAX - )); - MENU_SLIDER_FLOAT( - input->deadzoneLabel, INPUT_DEADZONE_DEFAULT, 0.0f, 1.0f, 0.05f - ); - #else - MENU_LABEL("No input settings yet"); - #endif - - MENU_BUTTON(UI_SETTINGS.applyLabel); - MENU_END(input->items, 1); - - errorOk(); -} - -void uiSettingsInputLoad(void) { - #ifdef DUSK_INPUT_GAMEPAD - uiSliderSetFloat( - &UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider, - INPUT.deadzone - ); - #endif -} - -void uiSettingsInputApply(void) { - #ifdef DUSK_INPUT_GAMEPAD - INPUT.deadzone = uiSliderGetFloat( - &UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider - ); - #endif - uiMenuClose(&UI_SETTINGS.data.input.menu); -} - -bool_t uiSettingsInputHasChanges(void) { - #ifdef DUSK_INPUT_GAMEPAD - if(uiSliderGetFloat( - &UI_SETTINGS.data.input.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider - ) != INPUT.deadzone) return true; - #endif - - return false; -} diff --git a/src/dusk/ui/frame/settings/uisettingsinput.h b/src/dusk/ui/frame/settings/uisettingsinput.h deleted file mode 100644 index 3fad214e..00000000 --- a/src/dusk/ui/frame/settings/uisettingsinput.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "uisettingsdata.h" - -/** - * Initializes the input settings page into the shared settings data - * union. - * - * @param data The shared settings data union to initialize into. - * @return Any error that occurs. - */ -errorret_t uiSettingsInputInit(uisettingsdata_t *data); - -/** - * Loads the page's widgets from the current engine input settings. - */ -void uiSettingsInputLoad(void); - -/** - * Applies the page's widget values to the engine input settings. - */ -void uiSettingsInputApply(void); - -/** - * Returns whether any widget's value differs from what was loaded. - * - * @returns True if there are unsaved changes. - */ -bool_t uiSettingsInputHasChanges(void); diff --git a/src/dusk/ui/frame/uiconfirm.c b/src/dusk/ui/frame/uiconfirm.c deleted file mode 100644 index 2fded7ce..00000000 --- a/src/dusk/ui/frame/uiconfirm.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uiconfirm.h" -#include "uiframe.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" -#include "util/math.h" -#include "display/screen/screen.h" -#include "display/text/text.h" -#include "display/color.h" -#include "display/spritebatch/spritebatch.h" -#include "display/texture/texture.h" -#include "display/shader/shaderunlit.h" - -#define UI_CONFIRM_BACKDROP_COLOR color4b(0, 0, 0, 160) - -uiconfirm_t UI_CONFIRM; - -void uiConfirmSelected( - const uimenu_t *menu, - const uint8_t index, - const uimenuitem_t *item -) { - UI_CONFIRM.result = index == UI_CONFIRM_INDEX_CONFIRM; - uiConfirmClose(); -} - -void uiConfirmClosed(const uimenu_t *menu) { - if(UI_CONFIRM.callback != NULL) { - UI_CONFIRM.callback(UI_CONFIRM.result, UI_CONFIRM.user); - } -} - -errorret_t uiConfirmInit(void) { - memoryZero(&UI_CONFIRM, sizeof(uiconfirm_t)); - - MENU_BEGIN( - &UI_CONFIRM.menu, UI_CONFIRM.items, uiConfirmSelected, uiConfirmClosed, NULL - ); - MENU_BUTTON("Confirm"); - MENU_BUTTON("Cancel"); - - MENU_END(UI_CONFIRM.items, menuIndex); - - errorOk(); -} - -errorret_t uiConfirmDraw(void) { - if(!uiMenuIsActive(&UI_CONFIRM.menu)) errorOk(); - - spritebatchsprite_t backdropSprite = { - .min = { 0.0f, 0.0f, 0.0f }, - .max = { (float_t)SCREEN.width, (float_t)SCREEN.height, 0.0f }, - .uvMin = { 0.0f, 0.0f }, - .uvMax = { 1.0f, 1.0f } - }; - shadermaterial_t backdropMaterial = { - .unlit = { - .color = UI_CONFIRM_BACKDROP_COLOR, - .texture = &TEXTURE_WHITE - } - }; - errorChain( - spriteBatchBuffer(&backdropSprite, 1, &SHADER_UNLIT, backdropMaterial) - ); - errorChain(spriteBatchFlush()); - - int32_t textW, textH; - textMeasure(UI_CONFIRM.text, &FONT_DEFAULT, &textW, &textH); - - float_t rowHeight = (float_t)FONT_DEFAULT.tileset->tileHeight; - float_t width = mathMax( - (float_t)textW + (UI_FRAME_START_X * 2), UI_CONFIRM_MIN_WIDTH - ); - float_t height = (UI_FRAME_START_Y * 2) + rowHeight + UI_FRAME_PADDING_Y + - rowHeight; - float_t x = (float_t)SCREEN.scanX + ((float_t)SCREEN.scanWidth - width) * 0.5f; - float_t y = (float_t)SCREEN.scanY + ((float_t)SCREEN.scanHeight - height) * 0.5f; - - errorChain(uiFrameDraw(x, y, width, height)); - - float_t contentX = x + UI_FRAME_START_X; - float_t contentY = y + UI_FRAME_START_Y; - float_t contentWidth = width - (UI_FRAME_START_X * 2); - - errorChain(textDraw(contentX, contentY, UI_CONFIRM.text, COLOR_WHITE, &FONT_DEFAULT)); - - float_t buttonsY = contentY + rowHeight + UI_FRAME_PADDING_Y; - errorChain(uiMenuDraw(&UI_CONFIRM.menu, contentX, buttonsY, contentWidth, rowHeight)); - - errorChain(spriteBatchFlush()); - errorOk(); -} - -bool_t uiConfirmIsOpen(void) { - return uiMenuIsActive(&UI_CONFIRM.menu); -} - -bool_t uiConfirmGetResult(void) { - return UI_CONFIRM.result; -} - -void uiConfirmOpen( - const char_t *question, - uiconfirmcallback_t callback, - void *user -) { - assertNotNull(question, "Question cannot be NULL"); - stringCopy(UI_CONFIRM.text, question, UI_CONFIRM_TEXT_MAX); - UI_CONFIRM.callback = callback; - UI_CONFIRM.user = user; - UI_CONFIRM.result = false; - uiMenuOpen(&UI_CONFIRM.menu); -} - -void uiConfirmClose(void) { - uiMenuClose(&UI_CONFIRM.menu); -} - -errorret_t uiConfirmDispose(void) { - errorOk(); -} diff --git a/src/dusk/ui/frame/uiconfirm.h b/src/dusk/ui/frame/uiconfirm.h deleted file mode 100644 index 38697048..00000000 --- a/src/dusk/ui/frame/uiconfirm.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "ui/widget/uimenu.h" - -#define UI_CONFIRM_TEXT_MAX 256 -#define UI_CONFIRM_MIN_WIDTH 160.0f -#define UI_CONFIRM_INDEX_CONFIRM 0 -#define UI_CONFIRM_INDEX_CANCEL 1 -#define UI_CONFIRM_ITEM_COUNT 2 - -/** - * Callback invoked once a confirm dialog is dismissed. - * - * @param result True if Confirm was selected, false if Cancel was - * selected or the dialog was backed out of. - * @param user Arbitrary pointer passed to uiConfirmOpen. - */ -typedef void (*uiconfirmcallback_t)(const bool_t result, void *user); - -typedef struct { - char_t text[UI_CONFIRM_TEXT_MAX]; - uimenu_t menu; - uimenuitem_t items[UI_CONFIRM_ITEM_COUNT]; - uiconfirmcallback_t callback; - void *user; - bool_t result; -} uiconfirm_t; - -extern uiconfirm_t UI_CONFIRM; - -/** - * Initializes the confirm dialog. - * - * @return Any error that occurs. - */ -errorret_t uiConfirmInit(void); - -/** - * Draws the confirm dialog: a semi-transparent black backdrop covering - * the whole screen, then its own centered frame with the question text - * and Confirm/Cancel buttons. No-op when not open. - * - * @return Any error that occurs. - */ -errorret_t uiConfirmDraw(void); - -/** - * Returns true when the confirm dialog is currently open. - * - * @returns True if open. - */ -bool_t uiConfirmIsOpen(void); - -/** - * Returns the result of the most recently dismissed confirm dialog. - * - * @returns True if Confirm was selected, false otherwise. - */ -bool_t uiConfirmGetResult(void); - -/** - * Opens the confirm dialog with the given question text. callback is - * invoked exactly once with the result, whether the dialog was - * dismissed by selecting a button or by pressing cancel/back. - * - * @param question Display text; copied internally, safe to be transient. - * @param callback Called with the result once the dialog closes. May be - * NULL. - * @param user Arbitrary pointer passed through to callback. - */ -void uiConfirmOpen( - const char_t *question, - uiconfirmcallback_t callback, - void *user -); - -/** - * Closes the confirm dialog. No-op when already closed. - */ -void uiConfirmClose(void); - -/** - * Disposes of the confirm dialog. - * - * @return Any error that occurs. - */ -errorret_t uiConfirmDispose(void); diff --git a/src/dusk/ui/frame/uiframe.c b/src/dusk/ui/frame/uiframe.c deleted file mode 100644 index 5202b3e1..00000000 --- a/src/dusk/ui/frame/uiframe.c +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uiframe.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "display/texture/texture.h" -#include "display/spritebatch/spritebatch.h" -#include "display/shader/shaderunlit.h" -#include "display/color.h" - -uiframe_t UI_FRAME; - -errorret_t uiFrameInit(void) { - memoryZero(&UI_FRAME, sizeof(uiframe_t)); - - // Init texture. - color_t border = color4b(0, 50, 255, 255); - color_t center = color4b(0, 100, 220, 240); - - for(uint8_t y = 0; y < UI_FRAME_TEXTURE_HEIGHT_POW2; y++) { - for(uint8_t x = 0; x < UI_FRAME_TEXTURE_WIDTH_POW2; x++) { - color_t c; - if(x >= UI_FRAME_TEXTURE_WIDTH || y >= UI_FRAME_TEXTURE_HEIGHT) { - c = COLOR_TRANSPARENT; - } else if( - y < UI_FRAME_TILE_HEIGHT || y >= UI_FRAME_TILE_HEIGHT * 2 || - x < UI_FRAME_TILE_WIDTH || x >= UI_FRAME_TILE_WIDTH * 2 - ) { - c = border; - } else { - c = center; - } - UI_FRAME.pixels[y * UI_FRAME_TEXTURE_WIDTH_POW2 + x] = c; - } - } - - errorChain(textureInit( - &UI_FRAME.texture, - UI_FRAME_TEXTURE_WIDTH_POW2, UI_FRAME_TEXTURE_HEIGHT_POW2, - TEXTURE_FORMAT_RGBA, - (texturedata_t){ .rgbaColors = UI_FRAME.pixels } - )); - - UI_FRAME.tileset.tileWidth = UI_FRAME_TILE_WIDTH; - UI_FRAME.tileset.tileHeight = UI_FRAME_TILE_HEIGHT; - UI_FRAME.tileset.columns = 3; - UI_FRAME.tileset.rows = 3; - UI_FRAME.tileset.tileCount = 9; - UI_FRAME.tileset.uv[0] = - (float_t)UI_FRAME_TILE_WIDTH / UI_FRAME_TEXTURE_WIDTH_POW2; - UI_FRAME.tileset.uv[1] = - (float_t)UI_FRAME_TILE_HEIGHT / UI_FRAME_TEXTURE_HEIGHT_POW2; - - errorOk(); -} - -errorret_t uiFrameDraw( - const float_t x, - const float_t y, - const float_t width, - const float_t height -) { - shadermaterial_t material = { - .unlit = { - .color = COLOR_WHITE, - .texture = &UI_FRAME.texture - } - }; - spritebatchsprite_t sprites[9]; - float_t tileW = (float_t)UI_FRAME_BORDER_WIDTH; - float_t tileH = (float_t)UI_FRAME_BORDER_HEIGHT; - - sprites[0] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 0, 0, - x, y, tileW, tileH - ); - sprites[1] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 1, 0, - x + tileW, y, width - (tileW * 2.0f), tileH - ); - sprites[2] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 2, 0, - x + width - tileW, y, tileW, tileH - ); - sprites[3] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 0, 1, - x, y + tileH, tileW, height - (tileH * 2.0f) - ); - sprites[4] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 1, 1, - x + tileW, y + tileH, - width - (tileW * 2.0f), height - (tileH * 2.0f) - ); - sprites[5] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 2, 1, - x + width - tileW, y + tileH, tileW, height - (tileH * 2.0f) - ); - sprites[6] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 0, 2, - x, y + height - tileH, tileW, tileH - ); - sprites[7] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 1, 2, - x + tileW, y + height - tileH, width - (tileW * 2.0f), tileH - ); - sprites[8] = spriteBatchSpriteTilesetPosition( - &UI_FRAME.tileset, 2, 2, - x + width - tileW, y + height - tileH, tileW, tileH - ); - - return spriteBatchBuffer(sprites, 9, &SHADER_UNLIT, material); -} - -errorret_t uiFrameDispose(void) { - return textureDispose(&UI_FRAME.texture); -} diff --git a/src/dusk/ui/frame/uiframe.h b/src/dusk/ui/frame/uiframe.h deleted file mode 100644 index 626afd64..00000000 --- a/src/dusk/ui/frame/uiframe.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "display/texture/texture.h" -#include "display/texture/tileset.h" - -#define UI_FRAME_BORDER_WIDTH 6 -#define UI_FRAME_BORDER_HEIGHT 6 -#define UI_FRAME_PADDING_X 2 -#define UI_FRAME_PADDING_Y 2 -#define UI_FRAME_START_X (UI_FRAME_BORDER_WIDTH + UI_FRAME_PADDING_X) -#define UI_FRAME_START_Y (UI_FRAME_BORDER_HEIGHT + UI_FRAME_PADDING_Y) -#define UI_FRAME_TILE_WIDTH 1 -#define UI_FRAME_TILE_HEIGHT 1 -#define UI_FRAME_TEXTURE_WIDTH (UI_FRAME_TILE_WIDTH * 3) -#define UI_FRAME_TEXTURE_HEIGHT (UI_FRAME_TILE_HEIGHT * 3) -#define UI_FRAME_TEXTURE_WIDTH_POW2 4 -#define UI_FRAME_TEXTURE_HEIGHT_POW2 4 - -typedef struct { - tileset_t tileset; - texture_t texture; - color_t pixels[UI_FRAME_BORDER_WIDTH * UI_FRAME_BORDER_HEIGHT]; -} uiframe_t; - -extern uiframe_t UI_FRAME; - -/** - * Initializes the global UI_FRAME: builds the dummy texture and - * configures the tileset. Call once after displayInit(). - * - * @return Any error that occurs. - */ -errorret_t uiFrameInit(void); - -/** - * Draws UI_FRAME using 9-slice rendering from its 3x3 tileset. - * Pushes quads to the sprite batch without flushing. - * - * @param x Screen x position. - * @param y Screen y position. - * @param width Total width of the frame. - * @param height Total height of the frame. - * @return Any error that occurs. - */ -errorret_t uiFrameDraw( - const float_t x, - const float_t y, - const float_t width, - const float_t height -); - -/** - * Disposes of the global UI_FRAME, releasing its GPU texture. - * - * @return Any error that occurs. - */ -errorret_t uiFrameDispose(void); diff --git a/src/dusk/ui/overlay/CMakeLists.txt b/src/dusk/ui/overlay/CMakeLists.txt index d6c051b3..11f2217d 100644 --- a/src/dusk/ui/overlay/CMakeLists.txt +++ b/src/dusk/ui/overlay/CMakeLists.txt @@ -6,6 +6,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC uicrop.c - uifullbox.c - uiloading.c ) diff --git a/src/dusk/ui/overlay/uifullbox.c b/src/dusk/ui/overlay/uifullbox.c deleted file mode 100644 index 0fdb6e74..00000000 --- a/src/dusk/ui/overlay/uifullbox.c +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uifullbox.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "time/time.h" -#include "display/screen/screen.h" -#include "display/texture/texture.h" -#include "display/spritebatch/spritebatch.h" -#include "display/shader/shaderunlit.h" - -uifullbox_t UI_FULLBOX_UNDER; -uifullbox_t UI_FULLBOX_OVER; - -void uiFullboxInit(uifullbox_t *fullbox) { - assertNotNull(fullbox, "fullbox must not be NULL"); - memoryZero(fullbox, sizeof(uifullbox_t)); - eventInit( - &fullbox->onTransitionEnd, - fullbox->onTransitionEndCallbacks, - fullbox->onTransitionEndUsers, - 4 - ); -} - -void uiFullboxUpdate(uifullbox_t *fullbox, float_t delta) { - assertNotNull(fullbox, "fullbox must not be NULL"); - if(fullbox->duration <= 0.0f || fullbox->time >= fullbox->duration) return; - - fullbox->time += delta; - if(fullbox->time >= fullbox->duration) { - fullbox->time = fullbox->duration; - eventInvoke(&fullbox->onTransitionEnd, fullbox); - } -} - -static color_t uiFullboxGetColor(const uifullbox_t *fullbox) { - if(fullbox->duration <= 0.0f || fullbox->time >= fullbox->duration) { - return fullbox->toColor; - } - float_t t = easingApply(fullbox->easing, fullbox->time / fullbox->duration); - return color4b( - (uint8_t)((float_t)fullbox->fromColor.r + - ((float_t)fullbox->toColor.r - (float_t)fullbox->fromColor.r) * t), - (uint8_t)((float_t)fullbox->fromColor.g + - ((float_t)fullbox->toColor.g - (float_t)fullbox->fromColor.g) * t), - (uint8_t)((float_t)fullbox->fromColor.b + - ((float_t)fullbox->toColor.b - (float_t)fullbox->fromColor.b) * t), - (uint8_t)((float_t)fullbox->fromColor.a + - ((float_t)fullbox->toColor.a - (float_t)fullbox->fromColor.a) * t) - ); -} - -errorret_t uiFullboxDraw(uifullbox_t *fullbox) { - assertNotNull(fullbox, "fullbox must not be NULL"); - - color_t color = uiFullboxGetColor(fullbox); - if(color.a == 0) errorOk(); - - spritebatchsprite_t sprite = { - .min = { 0.0f, 0.0f, 0.0f }, - .max = { (float_t)SCREEN.width, (float_t)SCREEN.height, 0.0f }, - .uvMin = { 0.0f, 0.0f }, - .uvMax = { 1.0f, 1.0f } - }; - shadermaterial_t material = { - .unlit = { - .color = color, - .texture = &TEXTURE_WHITE - } - }; - errorChain(spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, material)); - return spriteBatchFlush(); -} - -void uiFullboxTransition( - uifullbox_t *fullbox, - color_t from, - color_t to, - float_t duration, - easingtype_t easing -) { - assertNotNull(fullbox, "fullbox must not be NULL"); - fullbox->fromColor = from; - fullbox->toColor = to; - fullbox->duration = duration; - fullbox->time = 0.0f; - fullbox->easing = easing; -} - -errorret_t uiFullboxUnderInit(void) { - uiFullboxInit(&UI_FULLBOX_UNDER); - errorOk(); -} - -errorret_t uiFullboxUnderUpdate(void) { - uiFullboxUpdate(&UI_FULLBOX_UNDER, TIME.delta); - errorOk(); -} - -errorret_t uiFullboxUnderDraw(void) { - return uiFullboxDraw(&UI_FULLBOX_UNDER); -} - -errorret_t uiFullboxOverInit(void) { - uiFullboxInit(&UI_FULLBOX_OVER); - errorOk(); -} - -errorret_t uiFullboxOverUpdate(void) { - uiFullboxUpdate(&UI_FULLBOX_OVER, TIME.delta); - errorOk(); -} - -errorret_t uiFullboxOverDraw(void) { - return uiFullboxDraw(&UI_FULLBOX_OVER); -} diff --git a/src/dusk/ui/overlay/uifullbox.h b/src/dusk/ui/overlay/uifullbox.h deleted file mode 100644 index 5c1accd3..00000000 --- a/src/dusk/ui/overlay/uifullbox.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "display/color.h" -#include "animation/easing.h" -#include "event/event.h" - -typedef struct { - color_t fromColor; - color_t toColor; - float_t duration; - float_t time; - easingtype_t easing; - eventcallback_t onTransitionEndCallbacks[4]; - void *onTransitionEndUsers[4]; - event_t onTransitionEnd; -} uifullbox_t; - -extern uifullbox_t UI_FULLBOX_UNDER; -extern uifullbox_t UI_FULLBOX_OVER; - -/** - * Initializes a fullbox, zeroing all fields. - * - * @param fullbox The fullbox to initialize. - */ -void uiFullboxInit(uifullbox_t *fullbox); - -/** - * Advances the fullbox transition. Fires onTransitionEnd once when the - * transition completes. Safe to call when no transition is running. - * - * @param fullbox The fullbox to update. - * @param delta Seconds elapsed since last update. - */ -void uiFullboxUpdate(uifullbox_t *fullbox, float_t delta); - -/** - * Renders the fullbox. Skipped entirely when the current alpha is zero. - * - * @param fullbox The fullbox to draw. - * @return Any error that occurs. - */ -errorret_t uiFullboxDraw(uifullbox_t *fullbox); - -/** - * Begins a color transition. - * - * @param fullbox The fullbox to transition. - * @param from Start color. - * @param to End color. - * @param duration Transition duration in seconds. - * @param easing Easing function to apply. - */ -void uiFullboxTransition( - uifullbox_t *fullbox, - color_t from, - color_t to, - float_t duration, - easingtype_t easing -); - -/** - * Init function for UI_FULLBOX_UNDER (registered in UI_ELEMENTS). - * - * @return Any error that occurs. - */ -errorret_t uiFullboxUnderInit(void); - -/** - * Update function for UI_FULLBOX_UNDER (registered in UI_ELEMENTS). - * - * @return Any error that occurs. - */ -errorret_t uiFullboxUnderUpdate(void); - -/** - * Draw function for UI_FULLBOX_UNDER (registered in UI_ELEMENTS). - * - * @return Any error that occurs. - */ -errorret_t uiFullboxUnderDraw(void); - -/** - * Init function for UI_FULLBOX_OVER (registered in UI_ELEMENTS). - * - * @return Any error that occurs. - */ -errorret_t uiFullboxOverInit(void); - -/** - * Update function for UI_FULLBOX_OVER (registered in UI_ELEMENTS). - * - * @return Any error that occurs. - */ -errorret_t uiFullboxOverUpdate(void); - -/** - * Draw function for UI_FULLBOX_OVER (registered in UI_ELEMENTS). - * - * @return Any error that occurs. - */ -errorret_t uiFullboxOverDraw(void); diff --git a/src/dusk/ui/overlay/uiloading.c b/src/dusk/ui/overlay/uiloading.c deleted file mode 100644 index 4dc86e3b..00000000 --- a/src/dusk/ui/overlay/uiloading.c +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uiloading.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "time/time.h" -#include "display/text/text.h" -#include "display/screen/screen.h" -#include "display/spritebatch/spritebatch.h" -#include "uifullbox.h" - -#define UI_LOADING_TEXT "loading" - -uiloading_t UI_LOADING; - -errorret_t uiLoadingInit(void) { - memoryZero(&UI_LOADING, sizeof(uiloading_t)); - eventInit( - &UI_LOADING.onTransitionEnd, - UI_LOADING.onTransitionEndCallbacks, - UI_LOADING.onTransitionEndUsers, - 4 - ); - errorOk(); -} - -errorret_t uiLoadingUpdate(void) { - if(UI_LOADING.duration > 0.0f && UI_LOADING.time < UI_LOADING.duration) { - UI_LOADING.time += TIME.delta; - if(UI_LOADING.time >= UI_LOADING.duration) { - UI_LOADING.time = UI_LOADING.duration; - eventInvoke(&UI_LOADING.onTransitionEnd, &UI_LOADING); - } - } - errorOk(); -} - -errorret_t uiLoadingDraw(void) { - float_t alpha; - if(UI_LOADING.duration <= 0.0f || UI_LOADING.time >= UI_LOADING.duration) { - alpha = UI_LOADING.toAlpha; - } else { - float_t t = UI_LOADING.time / UI_LOADING.duration; - alpha = UI_LOADING.fromAlpha + - (UI_LOADING.toAlpha - UI_LOADING.fromAlpha) * t; - } - - if(alpha <= 0.0f) errorOk(); - - int32_t textW, textH; - textMeasure(UI_LOADING_TEXT, &FONT_DEFAULT, &textW, &textH); - - float_t x = (float_t)(SCREEN.scanX + SCREEN.scanWidth) - - (float_t)textW - UI_LOADING_MARGIN; - float_t y = (float_t)(SCREEN.scanY + SCREEN.scanHeight) - - (float_t)textH - UI_LOADING_MARGIN; - - color_t color = COLOR_WHITE; - color.a = (uint8_t)(alpha * 255.0f); - - errorChain(textDraw(x, y, UI_LOADING_TEXT, color, &FONT_DEFAULT)); - return spriteBatchFlush(); -} - -static void uiLoadingTransition( - const float_t from, - const float_t to, - const eventcallback_t callback, - void *user -) { - UI_LOADING.fromAlpha = from; - UI_LOADING.toAlpha = to; - UI_LOADING.duration = UI_LOADING_FADE_DURATION; - UI_LOADING.time = 0.0f; - eventInit( - &UI_LOADING.onTransitionEnd, - UI_LOADING.onTransitionEndCallbacks, - UI_LOADING.onTransitionEndUsers, - 4 - ); - if(callback) eventSubscribe(&UI_LOADING.onTransitionEnd, callback, user); -} - -void uiLoadingShow(eventcallback_t callback, void *user) { - uiLoadingTransition(0.0f, 1.0f, callback, user); - uiFullboxTransition( - &UI_FULLBOX_OVER, - COLOR_TRANSPARENT_BLACK, - COLOR_BLACK, - UI_LOADING_FADE_DURATION, - EASING_LINEAR - ); -} - -void uiLoadingHide(eventcallback_t callback, void *user) { - uiLoadingTransition(1.0f, 0.0f, callback, user); - uiFullboxTransition( - &UI_FULLBOX_OVER, - COLOR_BLACK, - COLOR_TRANSPARENT_BLACK, - UI_LOADING_FADE_DURATION, - EASING_LINEAR - ); -} diff --git a/src/dusk/ui/overlay/uiloading.h b/src/dusk/ui/overlay/uiloading.h deleted file mode 100644 index af67db6c..00000000 --- a/src/dusk/ui/overlay/uiloading.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "event/event.h" - -#define UI_LOADING_FADE_DURATION 0.5f -#define UI_LOADING_MARGIN 8.0f - -typedef struct { - float_t fromAlpha; - float_t toAlpha; - float_t duration; - float_t time; - eventcallback_t onTransitionEndCallbacks[4]; - void *onTransitionEndUsers[4]; - event_t onTransitionEnd; -} uiloading_t; - -extern uiloading_t UI_LOADING; - -/** - * Initializes the loading indicator. - * - * @return Any error that occurs. - */ -errorret_t uiLoadingInit(void); - -/** - * Advances the loading indicator fade transition. Fires onTransitionEnd once - * when the transition completes. - * - * @return Any error that occurs. - */ -errorret_t uiLoadingUpdate(void); - -/** - * Draws the loading indicator. No-op when fully transparent. - * - * @return Error state. - */ -errorret_t uiLoadingDraw(void); - -/** - * Fades the loading indicator in. Invokes callback when fully visible. - * - * @param callback Called when the fade-in completes. May be NULL. - * @param user Forwarded to the callback unchanged. - */ -void uiLoadingShow(eventcallback_t callback, void *user); - -/** - * Fades the loading indicator out. Invokes callback when fully hidden. - * - * @param callback Called when the fade-out completes. May be NULL. - * @param user Forwarded to the callback unchanged. - */ -void uiLoadingHide(eventcallback_t callback, void *user); diff --git a/src/dusk/ui/rpg/CMakeLists.txt b/src/dusk/ui/rpg/CMakeLists.txt deleted file mode 100644 index eb3441de..00000000 --- a/src/dusk/ui/rpg/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uiemoji.c -) - - -add_subdirectory(textbox) \ No newline at end of file diff --git a/src/dusk/ui/rpg/textbox/CMakeLists.txt b/src/dusk/ui/rpg/textbox/CMakeLists.txt deleted file mode 100644 index e7787f2d..00000000 --- a/src/dusk/ui/rpg/textbox/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uitextbox.c - uitextboxmain.c - uitextboxmini.c - uitextboxminilist.c -) diff --git a/src/dusk/ui/rpg/textbox/uitextbox.c b/src/dusk/ui/rpg/textbox/uitextbox.c deleted file mode 100644 index 47bdbdf6..00000000 --- a/src/dusk/ui/rpg/textbox/uitextbox.c +++ /dev/null @@ -1,244 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uitextbox.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" -#include "time/time.h" -#include "display/text/text.h" -#include "display/color.h" -#include "display/spritebatch/spritebatch.h" -#include "display/shader/shaderunlit.h" -#include "ui/frame/uiframe.h" - -void uiTextboxInit( - uitextbox_t *box, - char_t *text, - const uint32_t maxLength, - uitextboxline_t *lines, - const uint32_t linesMax -) { - assertNotNull(box, "Textbox cannot be NULL"); - assertNotNull(text, "Text buffer cannot be NULL"); - assertTrue(maxLength >= 1, "maxLength must be at least 1"); - assertNotNull(lines, "Lines buffer cannot be NULL"); - assertTrue(linesMax >= 1, "linesMax must be at least 1"); - memoryZero(box, sizeof(uitextbox_t)); - box->text = text; - box->maxLength = maxLength; - box->lines = lines; - box->linesMax = linesMax; -} - -void uiTextboxSetText(uitextbox_t *box, const char_t *text) { - assertNotNull(box, "Textbox cannot be NULL"); - assertNotNull(text, "Text cannot be NULL"); - stringCopy(box->text, text, box->maxLength); - box->currentPage = 0; - box->scroll = 0; - box->layoutWidth = 0.0f; - box->layoutHeight = 0.0f; -} - -void uiTextboxBuildLayout( - uitextbox_t *box, - const float_t width, - const float_t height -) { - assertNotNull(box, "Textbox cannot be NULL"); - - box->layoutWidth = width; - box->layoutHeight = height; - box->lineCount = 0; - box->pageCount = 1; - - float_t fontW = (float_t)FONT_DEFAULT.tileset->tileWidth; - float_t fontH = (float_t)FONT_DEFAULT.tileset->tileHeight; - - if(fontW <= 0.0f || fontH <= 0.0f) return; - - box->charsPerLine = (int32_t)(width / fontW); - box->linesPerPage = (int32_t)(height / (fontH + UI_TEXTBOX_LINE_SPACING)); - if(box->linesPerPage > UI_TEXTBOX_LINES_PER_PAGE_MAX) { - box->linesPerPage = UI_TEXTBOX_LINES_PER_PAGE_MAX; - } - - if(box->charsPerLine <= 0 || box->linesPerPage <= 0) return; - if(box->text[0] == '\0') return; - - char_t *src = box->text; - int32_t i = 0; - - while(src[i] != '\0' && box->lineCount < (int32_t)box->linesMax) { - if(src[i] == '\t') { - i++; - int32_t rem = box->lineCount % box->linesPerPage; - int32_t pad = rem > 0 ? box->linesPerPage - rem : 0; - while(pad > 0 && box->lineCount < (int32_t)box->linesMax) { - box->lines[box->lineCount].start = i; - box->lines[box->lineCount].count = 0; - box->lineCount++; - pad--; - } - continue; - } - - int32_t lineStart = i; - int32_t lineWidth = 0; - - while(src[i] != '\0') { - char_t c = src[i]; - - if(c == '\n') { i++; break; } - if(c == '\t') break; - - if(c == ' ') { - int32_t wordLen = 0; - int32_t j = i + 1; - while( - src[j] != ' ' && src[j] != '\n' && - src[j] != '\t' && src[j] != '\0' - ) { - wordLen++; - j++; - } - - if(lineWidth > 0 && lineWidth + 1 + wordLen > box->charsPerLine) { - i++; - break; - } - - lineWidth++; - i++; - } else { - if(lineWidth >= box->charsPerLine) break; - lineWidth++; - i++; - } - } - - box->lines[box->lineCount].start = lineStart; - box->lines[box->lineCount].count = lineWidth; - box->lineCount++; - } - - if(box->lineCount == 0) { - box->pageCount = 1; - } else { - box->pageCount = - (box->lineCount + box->linesPerPage - 1) / box->linesPerPage; - } -} - -errorret_t uiTextboxUpdate(uitextbox_t *box) { - assertNotNull(box, "Textbox cannot be NULL"); - -#ifdef DUSK_TIME_DYNAMIC - if(TIME.dynamicUpdate) errorOk(); -#endif - - if(!uiTextboxPageIsComplete(box)) { - box->scroll += UI_TEXTBOX_SCROLL_CHARS_PER_TICK; - } - - errorOk(); -} - -errorret_t uiTextboxDraw( - uitextbox_t *box, - const float_t x, - const float_t y, - const float_t width, - const float_t height -) { - assertNotNull(box, "Textbox cannot be NULL"); - - float_t startX = (float_t)UI_FRAME_START_X; - float_t startY = (float_t)UI_FRAME_START_Y; - float_t contentX = x + startX; - float_t contentY = y + startY; - float_t contentW = width - 2.0f * startX; - float_t contentH = height - 2.0f * startY; - - if(contentW != box->layoutWidth || contentH != box->layoutHeight) { - uiTextboxBuildLayout(box, contentW, contentH); - } - - errorChain(uiFrameDraw(x, y, width, height)); - errorChain(spriteBatchFlush()); - - if(box->lineCount == 0 || box->text[0] == '\0') errorOk(); - - float_t fontW = (float_t)FONT_DEFAULT.tileset->tileWidth; - float_t fontH = (float_t)FONT_DEFAULT.tileset->tileHeight; - - shadermaterial_t material = { - .unlit = { - .color = COLOR_WHITE, - .texture = FONT_DEFAULT.texture - } - }; - - int32_t pageFirst = box->currentPage * box->linesPerPage; - int32_t pageLast = pageFirst + box->linesPerPage; - if(pageLast > box->lineCount) pageLast = box->lineCount; - - int32_t charsLeft = box->scroll; - - for(int32_t li = pageFirst; li < pageLast && charsLeft > 0; li++) { - uitextboxline_t *line = &box->lines[li]; - int32_t visible = line->count < charsLeft ? line->count : charsLeft; - float_t lineY = contentY + - (float_t)(li - pageFirst) * (fontH + UI_TEXTBOX_LINE_SPACING); - - for(int32_t ci = 0; ci < visible; ci++) { - char_t c = box->text[line->start + ci]; - if(c == ' ') continue; - spritebatchsprite_t sprite = textGetSprite( - (vec2){ contentX + (float_t)ci * fontW, lineY }, - c, - &FONT_DEFAULT - ); - errorChain(spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, material)); - } - - charsLeft -= visible; - } - - errorChain(spriteBatchFlush()); - errorOk(); -} - -int32_t uiTextboxGetPageCharCount(const uitextbox_t *box) { - assertNotNull(box, "Textbox cannot be NULL"); - int32_t first = box->currentPage * box->linesPerPage; - int32_t last = first + box->linesPerPage; - if(last > box->lineCount) last = box->lineCount; - int32_t total = 0; - for(int32_t i = first; i < last; i++) { - total += box->lines[i].count; - } - return total; -} - -bool_t uiTextboxPageIsComplete(const uitextbox_t *box) { - assertNotNull(box, "Textbox cannot be NULL"); - return box->scroll >= uiTextboxGetPageCharCount(box); -} - -bool_t uiTextboxHasNextPage(const uitextbox_t *box) { - assertNotNull(box, "Textbox cannot be NULL"); - return box->currentPage + 1 < box->pageCount; -} - -void uiTextboxNextPage(uitextbox_t *box) { - assertNotNull(box, "Textbox cannot be NULL"); - if(!uiTextboxHasNextPage(box)) return; - box->currentPage++; - box->scroll = 0; -} diff --git a/src/dusk/ui/rpg/textbox/uitextbox.h b/src/dusk/ui/rpg/textbox/uitextbox.h deleted file mode 100644 index 047e7e1f..00000000 --- a/src/dusk/ui/rpg/textbox/uitextbox.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" - -#define UI_TEXTBOX_LINES_PER_PAGE_MAX 4 -#define UI_TEXTBOX_SCROLL_CHARS_PER_TICK 1 -#define UI_TEXTBOX_LINE_SPACING 0.0f - -typedef struct { - int32_t start; - int32_t count; -} uitextboxline_t; - -typedef struct { - char_t *text; - uint32_t maxLength; - - uitextboxline_t *lines; - uint32_t linesMax; - int32_t lineCount; - int32_t charsPerLine; - int32_t linesPerPage; - int32_t pageCount; - - // last dimensions used for layout; rebuild triggers when these change - float_t layoutWidth; - float_t layoutHeight; - - int32_t currentPage; - int32_t scroll; -} uitextbox_t; - -/** - * Initializes a textbox, zeroing all state and binding it to caller-owned - * text and line storage. - * - * @param box The textbox to initialize. - * @param text Caller-owned buffer the textbox copies its text into. - * @param maxLength Capacity of text, in characters. - * @param lines Caller-owned buffer the textbox lays lines out into. - * @param linesMax Capacity of lines, in entries. - */ -void uiTextboxInit( - uitextbox_t *box, - char_t *text, - const uint32_t maxLength, - uitextboxline_t *lines, - const uint32_t linesMax -); - -/** - * Copies text into the textbox and marks layout as dirty. - * Resets currentPage and scroll to 0. - * - * @param box The textbox to update. - * @param text Null-terminated source string. - */ -void uiTextboxSetText(uitextbox_t *box, const char_t *text); - -/** - * Rebuilds word-wrap and page layout for the given draw dimensions. - * Called automatically by uiTextboxDraw when width or height changes. - * - * @param box The textbox to rebuild. - * @param width Available content width in pixels. - * @param height Available content height in pixels. - */ -void uiTextboxBuildLayout( - uitextbox_t *box, - const float_t width, - const float_t height -); - -/** - * Advances the typewriter scroll by UI_TEXTBOX_SCROLL_CHARS_PER_TICK. - * Skipped on dynamic ticks. - * - * @param box The textbox to update. - * @returns Any error that occurs. - */ -errorret_t uiTextboxUpdate(uitextbox_t *box); - -/** - * Draws the textbox frame and visible text. Rebuilds layout automatically - * if width or height differs from the last draw call. - * - * @param box The textbox to draw. - * @param x Screen x position. - * @param y Screen y position. - * @param width Draw width in pixels. - * @param height Draw height in pixels. - * @returns Any error that occurs. - */ -errorret_t uiTextboxDraw( - uitextbox_t *box, - const float_t x, - const float_t y, - const float_t width, - const float_t height -); - -/** - * Returns the total visible char count for the current page. - * - * @param box The textbox to query. - * @returns Total chars on the current page. - */ -int32_t uiTextboxGetPageCharCount(const uitextbox_t *box); - -/** - * Returns true when scroll has fully revealed the current page. - * - * @param box The textbox to query. - * @returns True if the current page is fully visible. - */ -bool_t uiTextboxPageIsComplete(const uitextbox_t *box); - -/** - * Returns true when there is at least one more page after the current one. - * - * @param box The textbox to query. - * @returns True if a next page exists. - */ -bool_t uiTextboxHasNextPage(const uitextbox_t *box); - -/** - * Advances to the next page and resets scroll to 0. - * Has no effect if already on the last page. - * - * @param box The textbox to advance. - */ -void uiTextboxNextPage(uitextbox_t *box); diff --git a/src/dusk/ui/rpg/textbox/uitextboxmain.c b/src/dusk/ui/rpg/textbox/uitextboxmain.c deleted file mode 100644 index e65892ea..00000000 --- a/src/dusk/ui/rpg/textbox/uitextboxmain.c +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uitextboxmain.h" -#include "ui/focus/uifocus.h" -#include "display/screen/screen.h" -#include "display/text/text.h" -#include "display/color.h" -#include "display/spritebatch/spritebatch.h" -#include "display/shader/shaderunlit.h" -#include "ui/frame/uiframe.h" - -uitextboxmain_t UI_TEXTBOX_MAIN; -static uifocusitem_t *focusItem = NULL; - -errorret_t uiTextboxMainInit(void) { - uiTextboxInit( - &UI_TEXTBOX_MAIN.box, - UI_TEXTBOX_MAIN.text, UI_TEXTBOX_MAIN_TEXT_MAX, - UI_TEXTBOX_MAIN.lines, UI_TEXTBOX_MAIN_LINES_MAX - ); - errorOk(); -} - -void uiTextboxMainSetText(const char_t *text) { - uiTextboxSetText(&UI_TEXTBOX_MAIN.box, text); - if(focusItem != NULL) return; - focusItem = uiFocusPush( - 1, 1, - uiTextboxMainFocusSelected, - NULL, - uiTextboxMainFocusClosed, - NULL, - NULL - ); -} - -errorret_t uiTextboxMainUpdate(void) { - if(focusItem == NULL) errorOk(); - return uiTextboxUpdate(&UI_TEXTBOX_MAIN.box); -} - -errorret_t uiTextboxMainDraw(void) { - if(focusItem == NULL) errorOk(); - float_t fontH = (float_t)FONT_DEFAULT.tileset->tileHeight; - float_t h = (float_t)UI_TEXTBOX_MAIN_LINES * fontH + - (float_t)(UI_TEXTBOX_MAIN_LINES - 1) * UI_TEXTBOX_LINE_SPACING + - 2.0f * (float_t)UI_FRAME_START_Y; - float_t w = (float_t)SCREEN.scanWidth; - float_t x = (float_t)SCREEN.scanX; - float_t y = (float_t)(SCREEN.scanY + SCREEN.scanHeight) - h; - errorChain(uiTextboxDraw(&UI_TEXTBOX_MAIN.box, x, y, w, h)); - - if(!uiTextboxPageIsComplete(&UI_TEXTBOX_MAIN.box)) errorOk(); - - float_t fontW = (float_t)FONT_DEFAULT.tileset->tileWidth; - float_t contentX = x + (float_t)UI_FRAME_START_X; - float_t contentY = y + (float_t)UI_FRAME_START_Y; - float_t contentW = w - 2.0f * (float_t)UI_FRAME_START_X; - float_t contentH = h - 2.0f * (float_t)UI_FRAME_START_Y; - - shadermaterial_t material = { - .unlit = { - .color = COLOR_WHITE, - .texture = FONT_DEFAULT.texture - } - }; - - spritebatchsprite_t caret = textGetSprite( - (vec2){ - contentX + contentW - fontW, - contentY + contentH - fontH - }, - 'v', - &FONT_DEFAULT - ); - errorChain(spriteBatchBuffer(&caret, 1, &SHADER_UNLIT, material)); - errorChain(spriteBatchFlush()); - - errorOk(); -} - -bool_t uiTextboxMainPageIsComplete(void) { - return uiTextboxPageIsComplete(&UI_TEXTBOX_MAIN.box); -} - -bool_t uiTextboxMainHasNextPage(void) { - return uiTextboxHasNextPage(&UI_TEXTBOX_MAIN.box); -} - -void uiTextboxMainNextPage(void) { - uiTextboxNextPage(&UI_TEXTBOX_MAIN.box); -} - -bool_t uiTextboxMainIsActive(void) { - return focusItem != NULL; -} - -bool_t uiTextboxMainFocusSelected(const uifocusitem_t *item) { - if(!uiTextboxPageIsComplete(&UI_TEXTBOX_MAIN.box)) { - UI_TEXTBOX_MAIN.box.scroll = - uiTextboxGetPageCharCount(&UI_TEXTBOX_MAIN.box); - return true; - } - - if(uiTextboxHasNextPage(&UI_TEXTBOX_MAIN.box)) { - uiTextboxNextPage(&UI_TEXTBOX_MAIN.box); - return true; - } - - uiFocusPopItem(focusItem); - return true; -} - -bool_t uiTextboxMainFocusClosed(const uifocusitem_t *item) { - focusItem = NULL; - return true; -} diff --git a/src/dusk/ui/rpg/textbox/uitextboxmain.h b/src/dusk/ui/rpg/textbox/uitextboxmain.h deleted file mode 100644 index e7eb83f6..00000000 --- a/src/dusk/ui/rpg/textbox/uitextboxmain.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "ui/rpg/textbox/uitextbox.h" -#include "ui/focus/uifocusitem.h" - -#define UI_TEXTBOX_MAIN_LINES 4 -#define UI_TEXTBOX_MAIN_TEXT_MAX 1024 -#define UI_TEXTBOX_MAIN_LINES_MAX 64 - -typedef struct { - uitextbox_t box; - char_t text[UI_TEXTBOX_MAIN_TEXT_MAX]; - uitextboxline_t lines[UI_TEXTBOX_MAIN_LINES_MAX]; -} uitextboxmain_t; - -extern uitextboxmain_t UI_TEXTBOX_MAIN; - -/** - * Initializes UI_TEXTBOX_MAIN. - * - * @returns Any error that occurs. - */ -errorret_t uiTextboxMainInit(void); - -/** - * Copies text into UI_TEXTBOX_MAIN and resets page and scroll. - * - * @param text Null-terminated source string. - */ -void uiTextboxMainSetText(const char_t *text); - -/** - * Advances the typewriter scroll for UI_TEXTBOX_MAIN. - * - * @returns Any error that occurs. - */ -errorret_t uiTextboxMainUpdate(void); - -/** - * Draws UI_TEXTBOX_MAIN full-width at the bottom of the screen. - * Position and size are derived from SCREEN each call. - * - * @returns Any error that occurs. - */ -errorret_t uiTextboxMainDraw(void); - -/** - * Returns true when the current page is fully scrolled in. - * - * @returns True if the current page is complete. - */ -bool_t uiTextboxMainPageIsComplete(void); - -/** - * Returns true when at least one more page follows the current one. - * - * @returns True if a next page exists. - */ -bool_t uiTextboxMainHasNextPage(void); - -/** - * Advances UI_TEXTBOX_MAIN to the next page and resets scroll. - * Has no effect if already on the last page. - */ -void uiTextboxMainNextPage(void); - -/** - * Returns true when UI_TEXTBOX_MAIN has focus (is visible and active). - * - * @returns True if the textbox is currently active. - */ -bool_t uiTextboxMainIsActive(void); - -/** - * Internal focus callback - skip scroll or advance page or dismiss. - * - * @param item The active focus item. - * @returns True. - */ -bool_t uiTextboxMainFocusSelected(const uifocusitem_t *item); - -/** - * Internal focus callback - clears the focus item pointer on dismiss. - * - * @param item The focus item being closed. - * @returns True. - */ -bool_t uiTextboxMainFocusClosed(const uifocusitem_t *item); diff --git a/src/dusk/ui/rpg/textbox/uitextboxmini.c b/src/dusk/ui/rpg/textbox/uitextboxmini.c deleted file mode 100644 index f04515c6..00000000 --- a/src/dusk/ui/rpg/textbox/uitextboxmini.c +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uitextboxmini.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "time/time.h" -#include "rpg/rpgcamera.h" -#include "display/text/text.h" -#include "display/screen/screen.h" -#include "ui/frame/uiframe.h" - -void uiTextboxMiniInit(uitextboxmini_t *mini) { - assertNotNull(mini, "Mini textbox cannot be NULL"); - memoryZero(mini, sizeof(uitextboxmini_t)); - uiTextboxInit( - &mini->box, - mini->text, UI_TEXTBOX_MINI_TEXT_MAX, - mini->lines, UI_TEXTBOX_MINI_LINES_MAX - ); -} - -void uiTextboxMiniShow( - uitextboxmini_t *mini, - const char_t *text, - vec3 position, - const float_t duration, - uitextboxminiclosedcallback_t closed, - void *user -) { - assertNotNull(mini, "Mini textbox cannot be NULL"); - assertNotNull(text, "Text cannot be NULL"); - uiTextboxSetText(&mini->box, text); - glm_vec3_copy(position, mini->position); - - int32_t textWidth, textHeight; - textMeasure(text, &FONT_DEFAULT, &textWidth, &textHeight); - float_t width = (float_t)textWidth + 2.0f * (float_t)UI_FRAME_START_X; - mini->width = width < UI_TEXTBOX_MINI_WIDTH_MAX - ? width : UI_TEXTBOX_MINI_WIDTH_MAX; - - float_t fontH = (float_t)FONT_DEFAULT.tileset->tileHeight; - float_t maxHeight = (float_t)UI_TEXTBOX_MINI_LINES_MAX * fontH + - (float_t)(UI_TEXTBOX_MINI_LINES_MAX - 1) * UI_TEXTBOX_LINE_SPACING + - 2.0f * (float_t)UI_FRAME_START_Y; - uiTextboxBuildLayout( - &mini->box, - mini->width - 2.0f * (float_t)UI_FRAME_START_X, - maxHeight - 2.0f * (float_t)UI_FRAME_START_Y - ); - int32_t lineCount = mini->box.lineCount > 0 ? mini->box.lineCount : 1; - mini->height = (float_t)lineCount * fontH + - (float_t)(lineCount - 1) * UI_TEXTBOX_LINE_SPACING + - 2.0f * (float_t)UI_FRAME_START_Y; - - mini->active = true; - mini->timer = duration; - mini->closed = closed; - mini->user = user; -} - -errorret_t uiTextboxMiniUpdate(uitextboxmini_t *mini) { - assertNotNull(mini, "Mini textbox cannot be NULL"); - if(!mini->active) errorOk(); - - errorChain(uiTextboxUpdate(&mini->box)); - - if(mini->timer != UI_TEXTBOX_MINI_DURATION_INFINITE) { - mini->timer -= TIME.delta; - if(mini->timer <= 0.0f) uiTextboxMiniClose(mini); - } - - errorOk(); -} - -errorret_t uiTextboxMiniDraw(uitextboxmini_t *mini) { - assertNotNull(mini, "Mini textbox cannot be NULL"); - if(!mini->active) errorOk(); - - vec2 screenPos; - rpgCameraToScreen(mini->position, screenPos); - - if( - mini->clamp == UI_TEXTBOX_MINI_CLAMP_X || - mini->clamp == UI_TEXTBOX_MINI_CLAMP_BOTH - ) { - float_t minX = (float_t)SCREEN.scanX; - float_t maxX = (float_t)(SCREEN.scanX + SCREEN.scanWidth) - mini->width; - if(screenPos[0] < minX) screenPos[0] = minX; - if(screenPos[0] > maxX) screenPos[0] = maxX; - } - - if( - mini->clamp == UI_TEXTBOX_MINI_CLAMP_Y || - mini->clamp == UI_TEXTBOX_MINI_CLAMP_BOTH - ) { - float_t minY = (float_t)SCREEN.scanY; - float_t maxY = (float_t)(SCREEN.scanY + SCREEN.scanHeight) - mini->height; - if(screenPos[1] < minY) screenPos[1] = minY; - if(screenPos[1] > maxY) screenPos[1] = maxY; - } - - return uiTextboxDraw( - &mini->box, screenPos[0], screenPos[1], mini->width, mini->height - ); -} - -bool_t uiTextboxMiniIsActive(const uitextboxmini_t *mini) { - assertNotNull(mini, "Mini textbox cannot be NULL"); - return mini->active; -} - -void uiTextboxMiniClose(uitextboxmini_t *mini) { - assertNotNull(mini, "Mini textbox cannot be NULL"); - if(!mini->active) return; - mini->active = false; - if(mini->closed != NULL) mini->closed(mini); -} diff --git a/src/dusk/ui/rpg/textbox/uitextboxmini.h b/src/dusk/ui/rpg/textbox/uitextboxmini.h deleted file mode 100644 index f173b3c5..00000000 --- a/src/dusk/ui/rpg/textbox/uitextboxmini.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "ui/rpg/textbox/uitextbox.h" - -#define UI_TEXTBOX_MINI_TEXT_MAX 128 -#define UI_TEXTBOX_MINI_LINES_MAX 2 -#define UI_TEXTBOX_MINI_WIDTH_MAX 160.0f - -// Magic duration value that keeps a mini textbox visible indefinitely -// instead of counting down and auto-closing. -#define UI_TEXTBOX_MINI_DURATION_INFINITE -1.0f - -typedef struct uitextboxmini_s uitextboxmini_t; -typedef void (*uitextboxminiclosedcallback_t)(const uitextboxmini_t *mini); - -/** - * Determines whether a mini textbox's screen position is clamped to stay - * fully on screen. Defaults to UI_TEXTBOX_MINI_CLAMP_NONE. - */ -typedef enum { - UI_TEXTBOX_MINI_CLAMP_NONE, - UI_TEXTBOX_MINI_CLAMP_X, - UI_TEXTBOX_MINI_CLAMP_Y, - UI_TEXTBOX_MINI_CLAMP_BOTH -} uitextboxminiclamp_t; - -typedef struct uitextboxmini_s { - uitextbox_t box; - char_t text[UI_TEXTBOX_MINI_TEXT_MAX]; - uitextboxline_t lines[UI_TEXTBOX_MINI_LINES_MAX]; - - vec3 position; - float_t width; - float_t height; - uitextboxminiclamp_t clamp; - bool_t active; - float_t timer; - - uitextboxminiclosedcallback_t closed; - void *user; -} uitextboxmini_t; - -/** - * Initializes a mini textbox, zeroing all state and binding its internal - * uitextbox_t to its own fixed-size text and line storage. - * - * @param mini The mini textbox to initialize. - */ -void uiTextboxMiniInit(uitextboxmini_t *mini); - -/** - * Shows a mini textbox with the given text at the given world position for - * the given duration. Resets the typewriter scroll, measures the text to - * size the box (width capped at UI_TEXTBOX_MINI_WIDTH_MAX, height derived - * from the resulting wrapped line count), and starts the visibility timer. - * - * @param mini The mini textbox to show. - * @param text Null-terminated source string. - * @param position World-space position the box is anchored to on screen. - * @param duration How long the mini textbox stays visible, in seconds, or - * UI_TEXTBOX_MINI_DURATION_INFINITE to never auto-close. - * @param closed Called once the timer elapses and the box closes. May be - * NULL. - * @param user Opaque pointer passed back through the closed callback. - */ -void uiTextboxMiniShow( - uitextboxmini_t *mini, - const char_t *text, - vec3 position, - const float_t duration, - uitextboxminiclosedcallback_t closed, - void *user -); - -/** - * Advances the typewriter scroll and counts down the visibility timer. - * Closes the mini textbox and fires its closed callback once the timer - * elapses. Has no effect if not active or if the duration was set to - * UI_TEXTBOX_MINI_DURATION_INFINITE. - * - * @param mini The mini textbox to update. - * @returns Any error that occurs. - */ -errorret_t uiTextboxMiniUpdate(uitextboxmini_t *mini); - -/** - * Draws the mini textbox at its text-measured size, anchored on screen to - * its world-space position via the RPG camera. Has no effect if not - * active. - * - * @param mini The mini textbox to draw. - * @returns Any error that occurs. - */ -errorret_t uiTextboxMiniDraw(uitextboxmini_t *mini); - -/** - * Returns true when the mini textbox is currently visible. - * - * @param mini The mini textbox to query. - * @returns True if active. - */ -bool_t uiTextboxMiniIsActive(const uitextboxmini_t *mini); - -/** - * Immediately closes the mini textbox and fires its closed callback. - * Has no effect if not active. - * - * @param mini The mini textbox to close. - */ -void uiTextboxMiniClose(uitextboxmini_t *mini); diff --git a/src/dusk/ui/rpg/textbox/uitextboxminilist.c b/src/dusk/ui/rpg/textbox/uitextboxminilist.c deleted file mode 100644 index 070bc817..00000000 --- a/src/dusk/ui/rpg/textbox/uitextboxminilist.c +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uitextboxminilist.h" - -uitextboxmini_t UI_TEXTBOX_MINI_LIST[UI_TEXTBOX_MINI_LIST_COUNT]; -uint8_t UI_TEXTBOX_MINI_LIST_NEXT; - -errorret_t uiTextboxMiniListInit(void) { - for(uint8_t i = 0; i < UI_TEXTBOX_MINI_LIST_COUNT; i++) { - uiTextboxMiniInit(&UI_TEXTBOX_MINI_LIST[i]); - } - UI_TEXTBOX_MINI_LIST_NEXT = 0; - errorOk(); -} - -uint8_t uiTextboxMiniListGetNext(void) { - uint8_t index = UI_TEXTBOX_MINI_LIST_NEXT; - UI_TEXTBOX_MINI_LIST_NEXT = - (UI_TEXTBOX_MINI_LIST_NEXT + 1) % UI_TEXTBOX_MINI_LIST_COUNT; - return index; -} - -errorret_t uiTextboxMiniListUpdate(void) { - for(uint8_t i = 0; i < UI_TEXTBOX_MINI_LIST_COUNT; i++) { - errorChain(uiTextboxMiniUpdate(&UI_TEXTBOX_MINI_LIST[i])); - } - errorOk(); -} - -errorret_t uiTextboxMiniListDraw(void) { - for(uint8_t i = 0; i < UI_TEXTBOX_MINI_LIST_COUNT; i++) { - errorChain(uiTextboxMiniDraw(&UI_TEXTBOX_MINI_LIST[i])); - } - errorOk(); -} diff --git a/src/dusk/ui/rpg/textbox/uitextboxminilist.h b/src/dusk/ui/rpg/textbox/uitextboxminilist.h deleted file mode 100644 index f3040b2c..00000000 --- a/src/dusk/ui/rpg/textbox/uitextboxminilist.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "ui/rpg/textbox/uitextboxmini.h" - -#define UI_TEXTBOX_MINI_LIST_COUNT 4 - -extern uitextboxmini_t UI_TEXTBOX_MINI_LIST[UI_TEXTBOX_MINI_LIST_COUNT]; -extern uint8_t UI_TEXTBOX_MINI_LIST_NEXT; - -/** - * Initializes all UI_TEXTBOX_MINI_LIST slots and resets - * UI_TEXTBOX_MINI_LIST_NEXT. - * - * @returns Any error that occurs. - */ -errorret_t uiTextboxMiniListInit(void); - -/** - * Returns the index of the next UI_TEXTBOX_MINI_LIST slot to use, cycling - * through all slots in round-robin order via UI_TEXTBOX_MINI_LIST_NEXT. - * - * @returns The next slot index. - */ -uint8_t uiTextboxMiniListGetNext(void); - -/** - * Updates all UI_TEXTBOX_MINI_LIST slots. - * - * @returns Any error that occurs. - */ -errorret_t uiTextboxMiniListUpdate(void); - -/** - * Draws all active UI_TEXTBOX_MINI_LIST slots. - * - * @returns Any error that occurs. - */ -errorret_t uiTextboxMiniListDraw(void); diff --git a/src/dusk/ui/rpg/uiemoji.c b/src/dusk/ui/rpg/uiemoji.c deleted file mode 100644 index 21a3cbf2..00000000 --- a/src/dusk/ui/rpg/uiemoji.c +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uiemoji.h" -#include "display/spritebatch/spritebatch.h" -#include "time/time.h" -#include "util/memory.h" -#include "display/shader/shaderunlit.h" -#include "rpg/entity/entity.h" -#include "rpg/rpgcamera.h" - -uiemoji_t UI_EMOJI; - -errorret_t uiEmojiInit(void) { - memoryZero(&UI_EMOJI, sizeof(UI_EMOJI)); - errorOk(); -} - -void uiEmojiAdd( - const uint8_t entity, - const float_t duration, - const uiemojitype_t type -) { - uint8_t slot = 0xFF; - // Find an available slot if any - for(uint8_t i = 0; i < UI_EMOJI_ACTIVE_COUNT; i++) { - if(UI_EMOJI.items[i].time <= 0.0f) { - slot = i; - break; - } - - if(UI_EMOJI.items[i].entity == entity) { - slot = i; - break; - } - - if(UI_EMOJI.items[i].type == UI_EMOJI_NULL) { - slot = i; - break; - } - } - - if(slot == 0xFF) { - // Whichever ends soonest - float_t minTime = UI_EMOJI.items[0].time; - slot = 0; - for(uint8_t i = 1; i < UI_EMOJI_ACTIVE_COUNT; i++) { - if(UI_EMOJI.items[i].time >= minTime) continue; - minTime = UI_EMOJI.items[i].time; - slot = i; - } - } - - uiemojiitem_t *item = &UI_EMOJI.items[slot]; - item->entity = entity; - item->time = duration; - item->type = type; -} - -errorret_t uiEmojiUpdate(void) { - for(uint8_t i = 0; i < UI_EMOJI_ACTIVE_COUNT; i++) { - uiemojiitem_t *item = &UI_EMOJI.items[i]; - if(item->type == UI_EMOJI_NULL) continue; - - item->time -= TIME.delta; - - if(item->time <= 0.0f) { - item->type = UI_EMOJI_NULL; - item->entity = 0xFF; - } - } - - errorOk(); -} - -errorret_t uiEmojiDraw(void) { - spritebatchsprite_t sprites[UI_EMOJI_ACTIVE_COUNT]; - uint8_t count = 0; - - for(uint8_t i = 0; i < UI_EMOJI_ACTIVE_COUNT; i++) { - uiemojiitem_t *item = &UI_EMOJI.items[i]; - if(item->type == UI_EMOJI_NULL) continue; - - vec2 screenPos; - rpgCameraToScreen(ENTITIES[item->entity].renderPosition, screenPos); - - spritebatchsprite_t *sprite = &sprites[count++]; - sprite->min[0] = screenPos[0]; - sprite->min[1] = screenPos[1] - UI_EMOJI_SIZE; - sprite->min[2] = 0.0f; - sprite->max[0] = screenPos[0] + UI_EMOJI_SIZE; - sprite->max[1] = screenPos[1]; - sprite->max[2] = 0.0f; - sprite->uvMin[0] = 0.0f; - sprite->uvMin[1] = 0.0f; - sprite->uvMax[0] = 1.0f; - sprite->uvMax[1] = 1.0f; - } - - if(count == 0) errorOk(); - - shadermaterial_t mat = { - .unlit = { - .color = COLOR_WHITE, - .texture = NULL - } - }; - errorChain(spriteBatchBuffer(sprites, count, &SHADER_UNLIT, mat)); - errorChain(spriteBatchFlush()); - errorOk(); -} - -errorret_t uiEmojiDispose(void) { - errorOk(); -} diff --git a/src/dusk/ui/rpg/uiemoji.h b/src/dusk/ui/rpg/uiemoji.h deleted file mode 100644 index 6dc8cc00..00000000 --- a/src/dusk/ui/rpg/uiemoji.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" - -#define UI_EMOJI_ACTIVE_COUNT 4 -#define UI_EMOJI_SIZE 32.0f - -typedef enum { - UI_EMOJI_NULL, - - UI_EMOJI_QUESTION_MARK, - UI_EMOJI_EXCLAMATION_MARK, - - UI_EMOJI_COUNT, -} uiemojitype_t; - -typedef struct { - uint8_t entity; - float_t time; - uiemojitype_t type; -} uiemojiitem_t; - -typedef struct { - uiemojiitem_t items[UI_EMOJI_ACTIVE_COUNT]; -} uiemoji_t; - -extern uiemoji_t UI_EMOJI; - -/** - * Initialize the UI emoji. - */ -errorret_t uiEmojiInit(void); - -/** - * Show a UI emoji for a specific entity. - * - * @param entity The entity to show the emoji for. - * @param duration The duration to display the emoji. - * @param type The type of emoji to display. - */ -void uiEmojiAdd( - const uint8_t entity, - const float_t duration, - const uiemojitype_t type -); - -/** - * Update the UI emoji. - */ -errorret_t uiEmojiUpdate(void); - -/** - * Draw the UI emoji. - */ -errorret_t uiEmojiDraw(void); - -/** - * Dispose of the UI emoji. - */ -errorret_t uiEmojiDispose(void); \ No newline at end of file diff --git a/src/dusk/ui/transition/CMakeLists.txt b/src/dusk/ui/transition/CMakeLists.txt deleted file mode 100644 index 0e365038..00000000 --- a/src/dusk/ui/transition/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - uitransition.c - uitransitionfade.c -) diff --git a/src/dusk/ui/transition/uitransition.c b/src/dusk/ui/transition/uitransition.c deleted file mode 100644 index 4ed0026e..00000000 --- a/src/dusk/ui/transition/uitransition.c +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uitransition.h" -#include "uitransitionfade.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "time/time.h" -#include "util/math.h" - -uitransition_t UI_TRANSITION; - -uitransitiondrawfunc_t UI_TRANSITION_TYPE_DRAW[UI_TRANSITION_TYPE_COUNT] = { - [UI_TRANSITION_TYPE_FADE] = uiTransitionFadeDraw -}; - -errorret_t uiTransitionInit(void) { - memoryZero(&UI_TRANSITION, sizeof(uitransition_t)); - - // uiTransitionStart((uitransitionstartparams_t){ - // .duration = 5.0f, - // .type = UI_TRANSITION_TYPE_FADE, - // .params = { - // .fade = { - // .easing = EASING_OUT_QUART, - // .fromColor = COLOR_TRANSPARENT_BLACK, - // .toColor = COLOR_BLACK - // } - // }, - // .finished = NULL, - // .user = NULL - // }); - - errorOk(); -} - -errorret_t uiTransitionUpdate(void) { - // Update time. - float_t newTime = UI_TRANSITION.data.time + TIME.delta; - - UI_TRANSITION.data.time = mathClamp( - newTime, - 0.0f, - UI_TRANSITION.data.duration - ); - UI_TRANSITION.data.t = ( - (UI_TRANSITION.data.duration <= 0.0f) ? - 1.0f : - (UI_TRANSITION.data.time / UI_TRANSITION.data.duration) - ); - - if(UI_TRANSITION.data.t >= 1.0f && UI_TRANSITION.finished) { - UI_TRANSITION.finished(UI_TRANSITION.user); - } - - errorOk(); -} - -errorret_t uiTransitionDraw(void) { - uitransitiondrawfunc_t draw = UI_TRANSITION_TYPE_DRAW[UI_TRANSITION.type]; - if(!draw) errorOk(); - return draw(&UI_TRANSITION.data); -} - -void uiTransitionStart(const uitransitionstartparams_t info) { - assertTrue(info.type > UI_TRANSITION_TYPE_NULL, "Invalid type"); - assertTrue(info.type < UI_TRANSITION_TYPE_COUNT, "Invalid type"); - assertTrue(info.duration >= 0.0f, "Duration must be non-negative"); - - memoryZero(&UI_TRANSITION, sizeof(uitransition_t)); - - UI_TRANSITION.data.duration = info.duration; - UI_TRANSITION.type = info.type; - UI_TRANSITION.data.params = info.params; - UI_TRANSITION.finished = info.finished; - UI_TRANSITION.user = info.user; -} \ No newline at end of file diff --git a/src/dusk/ui/transition/uitransition.h b/src/dusk/ui/transition/uitransition.h deleted file mode 100644 index 305ec5c3..00000000 --- a/src/dusk/ui/transition/uitransition.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "display/color.h" -#include "animation/easing.h" -#include "uitransitiondata.h" - -typedef void (*uitransitioncallback_t)(void *user); - -typedef enum { - UI_TRANSITION_TYPE_NULL, - - UI_TRANSITION_TYPE_FADE, - - UI_TRANSITION_TYPE_COUNT -} uitransitiontype_t; - -extern uitransitiondrawfunc_t UI_TRANSITION_TYPE_DRAW[UI_TRANSITION_TYPE_COUNT]; - - -typedef struct { - uitransitiondata_t data; - uitransitiontype_t type; - uitransitioncallback_t finished; - void *user; -} uitransition_t; - -extern uitransition_t UI_TRANSITION; - -/** - * Initializes the transition overlay, zeroing all fields and wiring the - * onTransitionEnd event. - * - * @return Any error that occurs. - */ -errorret_t uiTransitionInit(void); - -/** - * Advances the transition. Fires onTransitionEnd once when it completes. - * Safe to call when no transition is running. - * - * @return Any error that occurs. - */ -errorret_t uiTransitionUpdate(void); - -/** - * Renders the transition overlay. Skipped entirely when the current alpha - * is zero. - * - * @return Any error that occurs. - */ -errorret_t uiTransitionDraw(void); - -typedef struct { - float_t duration; - uitransitiontype_t type; - uitransitionparams_t params; - uitransitioncallback_t finished; - void *user; -} uitransitionstartparams_t; - -/** - * Starts a transition described by an info struct. - * - * @param info Transition parameters. - */ -void uiTransitionStart(const uitransitionstartparams_t info); - diff --git a/src/dusk/ui/transition/uitransitiondata.h b/src/dusk/ui/transition/uitransitiondata.h deleted file mode 100644 index 37e8430f..00000000 --- a/src/dusk/ui/transition/uitransitiondata.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "uitransitionfade.h" - -typedef union uitransitionparams_u { - uitransitionfade_t fade; -} uitransitionparams_t; - -typedef struct uitransitiondata_s { - float_t time; - float_t duration; - float_t t; - uitransitionparams_t params; -} uitransitiondata_t; - -typedef errorret_t (*uitransitiondrawfunc_t)(const uitransitiondata_t *data); diff --git a/src/dusk/ui/transition/uitransitionfade.c b/src/dusk/ui/transition/uitransitionfade.c deleted file mode 100644 index 45e3168d..00000000 --- a/src/dusk/ui/transition/uitransitionfade.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uitransition.h" -#include "assert/assert.h" -#include "display/screen/screen.h" -#include "display/texture/texture.h" -#include "display/spritebatch/spritebatch.h" -#include "display/shader/shaderunlit.h" - -errorret_t uiTransitionFadeDraw(const uitransitiondata_t *data) { - assertNotNull(data, "data must not be NULL"); - - float_t e = easingApply(data->params.fade.easing, data->t); - - float_t r = (float_t)( - data->params.fade.toColor.r - data->params.fade.fromColor.r - ) * e; - float_t g = (float_t)( - data->params.fade.toColor.g - data->params.fade.fromColor.g - ) * e; - float_t b = (float_t)( - data->params.fade.toColor.b - data->params.fade.fromColor.b - ) * e; - float_t a = (float_t)( - data->params.fade.toColor.a - data->params.fade.fromColor.a - ) * e; - - color_t color = color4b( - data->params.fade.fromColor.r + (uint8_t)r, - data->params.fade.fromColor.g + (uint8_t)g, - data->params.fade.fromColor.b + (uint8_t)b, - data->params.fade.fromColor.a + (uint8_t)a - ); - - if(color.a == 0) errorOk(); - - spritebatchsprite_t sprite = { - .min = { 0.0f, 0.0f, 0.0f }, - .max = { (float_t)SCREEN.width, (float_t)SCREEN.height, 0.0f }, - .uvMin = { 0.0f, 0.0f }, - .uvMax = { 1.0f, 1.0f } - }; - shadermaterial_t material = { - .unlit = { - .color = color, - .texture = NULL - } - }; - errorChain(spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, material)); - return spriteBatchFlush(); -} diff --git a/src/dusk/ui/transition/uitransitionfade.h b/src/dusk/ui/transition/uitransitionfade.h deleted file mode 100644 index a1b2475a..00000000 --- a/src/dusk/ui/transition/uitransitionfade.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "display/color.h" -#include "animation/easing.h" - -typedef struct uitransitiondata_s uitransitiondata_t; - -typedef struct { - color_t fromColor; - color_t toColor; - easingtype_t easing; -} uitransitionfade_t; - -/** - * Renders a full-screen color overlay interpolated between fade->fromColor - * and fade->toColor using fade->easing. t is the raw normalized progress - * in [0, 1] before easing is applied. No-op when the resulting alpha is zero. - * - * @param fade The fade parameters. - * @return Any error that occurs. - */ -errorret_t uiTransitionFadeDraw(const uitransitiondata_t *fade); diff --git a/src/dusk/ui/uielement.c b/src/dusk/ui/uielement.c index ce39a599..14977dd6 100644 --- a/src/dusk/ui/uielement.c +++ b/src/dusk/ui/uielement.c @@ -7,109 +7,12 @@ #include "uielement.h" #include "assert/assert.h" -#include "ui/frame/uiframe.h" #include "ui/debug/uifps.h" #include "engine/engine.h" -#include "ui/overlay/uifullbox.h" -#include "ui/overlay/uiloading.h" -#include "ui/debug/uiplayerpos.h" #include "ui/overlay/uicrop.h" -#include "ui/transition/uitransition.h" #include "ui/debug/uiconsole.h" -#include "ui/frame/settings/uisettings.h" -#include "ui/frame/game/uigamemenu.h" -#include "ui/frame/battle/uibattlemenu.h" -#include "ui/frame/backpack/uibackpack.h" -#include "ui/frame/uiconfirm.h" -#include "ui/rpg/textbox/uitextboxmain.h" -#include "ui/rpg/textbox/uitextboxminilist.h" -#include "ui/rpg/uiemoji.h" uielement_t UI_ELEMENTS[] = { - { - .init = uiFrameInit, - .dispose = uiFrameDispose - }, - - // Fullbox under: above scene, below system UI. - { - .init = uiFullboxUnderInit, - .update = uiFullboxUnderUpdate, - .draw = uiFullboxUnderDraw - }, - - // in world stuff - { - .init = uiEmojiInit, - .update = uiEmojiUpdate, - .draw = uiEmojiDraw, - .dispose = uiEmojiDispose - }, - - // Ingame menus - { - .init = uiGameMenuInit, - .draw = uiGameMenuDraw, - .dispose = uiGameMenuDispose - }, - - { - .init = uiBattleMenuInit, - .update = uiBattleMenuUpdate, - .draw = uiBattleMenuDraw - }, - - { - .init = uiBackpackInit, - .draw = uiBackpackDraw, - .dispose = uiBackpackDispose - }, - - { - .init = uiSettingsInit, - .update = uiSettingsUpdate, - .draw = uiSettingsDraw, - .dispose = uiSettingsDispose - }, - - // Text stuffs - { - .init = uiConfirmInit, - .draw = uiConfirmDraw, - .dispose = uiConfirmDispose - }, - - { - .init = uiTextboxMainInit, - .update = uiTextboxMainUpdate, - .draw = uiTextboxMainDraw - }, - - { - .init = uiTextboxMiniListInit, - .update = uiTextboxMiniListUpdate, - .draw = uiTextboxMiniListDraw - }, - - { - .init = uiTransitionInit, - .update = uiTransitionUpdate, - .draw = uiTransitionDraw - }, - - // Fullbox over: above absolutely everything. - { - .init = uiFullboxOverInit, - .update = uiFullboxOverUpdate, - .draw = uiFullboxOverDraw - }, - - { - .init = uiLoadingInit, - .update = uiLoadingUpdate, - .draw = uiLoadingDraw - }, - { .init = uiCropInit, .draw = uiCropDraw @@ -118,8 +21,7 @@ uielement_t UI_ELEMENTS[] = { // Debug items { .draw = uiConsoleDraw }, { .draw = uiFPSDraw }, - { .draw = uiPlayerPosDraw }, - + { 0 } // Null terminator }; @@ -132,7 +34,6 @@ bool_t uiElementIsNull(const uielement_t *element) { errorret_t uiElementInit(uielement_t *element) { assertNotNull(element, "element must not be NULL"); - errorChain(uiFrameInit()); if(element->init != NULL) errorChain(element->init()); errorOk(); } @@ -152,6 +53,5 @@ errorret_t uiElementDraw(const uielement_t *element) { errorret_t uiElementDispose(uielement_t *element) { assertNotNull(element, "element must not be NULL"); if(element->dispose != NULL) errorChain(element->dispose()); - errorChain(uiFrameDispose()); errorOk(); } \ No newline at end of file diff --git a/src/dusk/ui/widget/CMakeLists.txt b/src/dusk/ui/widget/CMakeLists.txt index 2e3eaf06..77cd1ebd 100644 --- a/src/dusk/ui/widget/CMakeLists.txt +++ b/src/dusk/ui/widget/CMakeLists.txt @@ -11,7 +11,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} uislider.c uidropdown.c uiscrolling.c - uiitem.c - uiitemlist.c uimenu.c ) diff --git a/src/dusk/ui/widget/uiitem.c b/src/dusk/ui/widget/uiitem.c deleted file mode 100644 index 9e73b676..00000000 --- a/src/dusk/ui/widget/uiitem.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uiitem.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "util/string.h" -#include "display/text/text.h" -#include "display/color.h" - -#define UI_ITEM_LABEL_MAX 48 - -errorret_t uiItemInit( - uiitem_t *item, - const itemid_t itemId, - const uint8_t quantity -) { - assertNotNull(item, "Item cannot be NULL"); - memoryZero(item, sizeof(uiitem_t)); - item->item = itemId; - item->quantity = quantity; - - if(itemId == ITEM_ID_NULL) errorOk(); - - errorChain(itemGetName(itemId, item->nameLabel, UI_ITEM_NAME_LABEL_MAX)); - - errorOk(); -} - -itemid_t uiItemGetItem(const uiitem_t *item) { - assertNotNull(item, "Item cannot be NULL"); - return item->item; -} - -uint8_t uiItemGetQuantity(const uiitem_t *item) { - assertNotNull(item, "Item cannot be NULL"); - return item->quantity; -} - -void uiItemSetQuantity(uiitem_t *item, const uint8_t quantity) { - assertNotNull(item, "Item cannot be NULL"); - item->quantity = quantity; -} - -bool_t uiItemIsHighlighted(const uiitem_t *item) { - assertNotNull(item, "Item cannot be NULL"); - return item->highlighted; -} - -void uiItemSetHighlighted(uiitem_t *item, const bool_t highlighted) { - assertNotNull(item, "Item cannot be NULL"); - item->highlighted = highlighted; -} - -errorret_t uiItemDraw( - const uiitem_t *item, - const float_t x, - const float_t y -) { - assertNotNull(item, "Item cannot be NULL"); - if(item->item == ITEM_ID_NULL) errorOk(); - - const color_t color = item->highlighted ? COLOR_RED : COLOR_WHITE; - - char_t text[UI_ITEM_LABEL_MAX]; - stringFormat( - text, UI_ITEM_LABEL_MAX - 1, - "%s x%u", item->nameLabel, item->quantity - ); - - errorChain(textDraw(x, y, text, color, &FONT_DEFAULT)); - errorOk(); -} diff --git a/src/dusk/ui/widget/uiitem.h b/src/dusk/ui/widget/uiitem.h deleted file mode 100644 index 787884c8..00000000 --- a/src/dusk/ui/widget/uiitem.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "rpg/item/item.h" - -#define UI_ITEM_NAME_LABEL_MAX 32 - -typedef struct { - itemid_t item; - uint8_t quantity; - bool_t highlighted; - char_t nameLabel[UI_ITEM_NAME_LABEL_MAX]; -} uiitem_t; - -/** - * Initializes an item widget, resolving the item's localized name. - * - * @param item The item widget to initialize. - * @param itemId The item ID to display. ITEM_ID_NULL renders as an - * empty slot. - * @param quantity The stack quantity to display. - * @return Any error that occurs. - */ -errorret_t uiItemInit( - uiitem_t *item, - const itemid_t itemId, - const uint8_t quantity -); - -/** - * Returns the item ID this widget displays. - * - * @param item The item widget to query. - * @returns The item ID. - */ -itemid_t uiItemGetItem(const uiitem_t *item); - -/** - * Returns the stack quantity this widget displays. - * - * @param item The item widget to query. - * @returns The quantity. - */ -uint8_t uiItemGetQuantity(const uiitem_t *item); - -/** - * Sets the stack quantity this widget displays. - * - * @param item The item widget to update. - * @param quantity The new quantity. - */ -void uiItemSetQuantity(uiitem_t *item, const uint8_t quantity); - -/** - * Returns whether the item widget is highlighted. - * - * @param item The item widget to query. - * @returns True if highlighted. - */ -bool_t uiItemIsHighlighted(const uiitem_t *item); - -/** - * Sets the highlighted state of the item widget. - * - * @param item The item widget to update. - * @param highlighted The new highlighted state. - */ -void uiItemSetHighlighted(uiitem_t *item, const bool_t highlighted); - -/** - * Draws the item widget at the given screen position: item name and - * quantity. No-op for an empty (ITEM_ID_NULL) slot. - * - * @param item The item widget to draw. - * @param x Screen x position. - * @param y Screen y position. - * @return Any error that occurs. - */ -errorret_t uiItemDraw( - const uiitem_t *item, - const float_t x, - const float_t y -); diff --git a/src/dusk/ui/widget/uiitemlist.c b/src/dusk/ui/widget/uiitemlist.c deleted file mode 100644 index 2ab2f62a..00000000 --- a/src/dusk/ui/widget/uiitemlist.c +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uiitemlist.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "display/text/text.h" - -void uiItemListInit( - uiitemlist_t *list, - const uint8_t columns, - const uint8_t rows, - const uint8_t itemColumns, - uiitemlistselectedcallback_t selected, - uiitemlistchangedcallback_t changed, - uiitemlistclosedcallback_t closed, - uiitemlistcolumncallback_t columnDraw -) { - assertNotNull(list, "Item list cannot be NULL"); - assertTrue(columns > 0, "Item list columns must be > 0"); - assertTrue(rows > 0, "Item list rows must be > 0"); - assertTrue(itemColumns > 0, "Item list itemColumns must be > 0"); - - memoryZero(list, sizeof(uiitemlist_t)); - list->columns = columns; - list->rows = rows; - list->itemColumns = itemColumns; - list->selected = selected; - list->changed = changed; - list->closed = closed; - list->columnDraw = columnDraw; - - uiScrollingInit(&list->scroll); -} - -void uiItemListSetItems( - uiitemlist_t *list, - const uiitem_t *items, - const uint8_t itemCount -) { - assertNotNull(list, "Item list cannot be NULL"); - assertTrue( - itemCount <= UI_ITEM_LIST_CAPACITY_MAX, "Too many items for list" - ); - - memoryCopy(list->items, items, sizeof(uiitem_t) * itemCount); - list->itemCount = itemCount; -} - -errorret_t uiItemListSetItemStacks( - uiitemlist_t *list, - const inventorystack_t *stacks, - const uint8_t stackCount -) { - assertNotNull(list, "Item list cannot be NULL"); - assertTrue( - stackCount <= UI_ITEM_LIST_CAPACITY_MAX, "Too many items for list" - ); - - for(uint8_t i = 0; i < stackCount; i++) { - errorChain( - uiItemInit(&list->items[i], stacks[i].item, stacks[i].quantity) - ); - } - list->itemCount = stackCount; - - errorOk(); -} - -void uiItemListOpen(uiitemlist_t *list) { - assertNotNull(list, "Item list cannot be NULL"); - if(list->focusItem != NULL) return; - - list->focusItem = uiFocusPush( - list->columns, list->rows, - uiItemListFocusSelected, - uiItemListFocusChanged, - uiItemListFocusClosed, - NULL, - list - ); -} - -void uiItemListClose(uiitemlist_t *list) { - assertNotNull(list, "Item list cannot be NULL"); - if(list->focusItem == NULL) return; - uiFocusPopItem(list->focusItem); - list->focusItem = NULL; -} - -bool_t uiItemListIsActive(const uiitemlist_t *list) { - assertNotNull(list, "Item list cannot be NULL"); - return list->focusItem != NULL; -} - -errorret_t uiItemListDraw( - const uiitemlist_t *list, - const float_t x, - const float_t y, - const float_t width -) { - assertNotNull(list, "Item list cannot be NULL"); - if(list->itemCount == 0) errorOk(); - - const float_t colStep = width / (float_t)list->columns; - const float_t rowHeight = (float_t)FONT_DEFAULT.tileset->tileHeight; - const float_t itemColStep = colStep / (float_t)list->itemColumns; - - const uint8_t visibleMax = list->columns * list->rows; - const uint8_t drawCount = - list->itemCount < visibleMax ? list->itemCount : visibleMax; - - for(uint8_t i = 0; i < drawCount; i++) { - const uint8_t col = i % list->columns; - const uint8_t row = i / list->columns; - - const float_t ix = x + (float_t)col * colStep; - const float_t iy = y + (float_t)row * rowHeight; - - errorChain(uiItemDraw(&list->items[i], ix, iy)); - - for(uint8_t c = 1; c < list->itemColumns; c++) { - if(list->columnDraw == NULL) continue; - errorChain(list->columnDraw( - list, &list->items[i], c, ix + (float_t)c * itemColStep, iy - )); - } - } - - errorOk(); -} - -bool_t uiItemListFocusSelected(const uifocusitem_t *focusItem) { - assertNotNull(focusItem, "Focus item cannot be NULL"); - assertNotNull(focusItem->user, "Focus item user cannot be NULL"); - uiitemlist_t *list = (uiitemlist_t *)focusItem->user; - if(list->selected == NULL) return true; - - const uint8_t index = focusItem->y * list->columns + focusItem->x; - if(index >= list->itemCount) return true; - - list->selected(list, index, &list->items[index]); - return true; -} - -bool_t uiItemListFocusChanged(const uifocusitem_t *focusItem) { - assertNotNull(focusItem, "Focus item cannot be NULL"); - assertNotNull(focusItem->user, "Focus item user cannot be NULL"); - uiitemlist_t *list = (uiitemlist_t *)focusItem->user; - - const uint8_t focusIndex = focusItem->y * list->columns + focusItem->x; - for(uint8_t i = 0; i < list->itemCount; i++) { - uiItemSetHighlighted(&list->items[i], i == focusIndex); - } - - if(list->changed == NULL) return true; - if(focusIndex >= list->itemCount) return true; - - list->changed(list, focusIndex, &list->items[focusIndex]); - return true; -} - -bool_t uiItemListFocusClosed(const uifocusitem_t *focusItem) { - assertNotNull(focusItem, "Focus item cannot be NULL"); - assertNotNull(focusItem->user, "Focus item user cannot be NULL"); - uiitemlist_t *list = (uiitemlist_t *)focusItem->user; - list->focusItem = NULL; - - for(uint8_t i = 0; i < list->itemCount; i++) { - uiItemSetHighlighted(&list->items[i], false); - } - - if(list->closed != NULL) list->closed(list); - return true; -} diff --git a/src/dusk/ui/widget/uiitemlist.h b/src/dusk/ui/widget/uiitemlist.h deleted file mode 100644 index 26b3e350..00000000 --- a/src/dusk/ui/widget/uiitemlist.h +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "ui/widget/uiitem.h" -#include "ui/widget/uiscrolling.h" -#include "ui/focus/uifocus.h" -#include "rpg/item/inventory.h" - -#define UI_ITEM_LIST_CAPACITY_MAX 40 - -typedef struct uiitemlist_s uiitemlist_t; - -typedef void (*uiitemlistselectedcallback_t)( - const uiitemlist_t *list, - const uint8_t index, - const uiitem_t *item -); - -typedef void (*uiitemlistchangedcallback_t)( - const uiitemlist_t *list, - const uint8_t index, - const uiitem_t *item -); - -typedef void (*uiitemlistclosedcallback_t)(const uiitemlist_t *list); - -/** - * Called to draw an extra per-item info column (columnIndex >= 1) - * beyond the item's own default uiItemDraw rendering -- e.g. a shop - * menu drawing a price alongside the item name. - * - * @param list The item list being drawn. - * @param item The item slot being drawn. - * @param columnIndex The info column being drawn (>= 1). - * @param x Screen x position for this column. - * @param y Screen y position for this column. - * @return Any error that occurs. - */ -typedef errorret_t (*uiitemlistcolumncallback_t)( - const uiitemlist_t *list, - const uiitem_t *item, - const uint8_t columnIndex, - const float_t x, - const float_t y -); - -struct uiitemlist_s { - uiitem_t items[UI_ITEM_LIST_CAPACITY_MAX]; - uint8_t itemCount; - - // Grid layout: how many item slots wide/tall the list displays. - uint8_t columns; - uint8_t rows; - - // How many info columns are rendered per item slot. 1 means only the - // item's own default name/quantity is drawn; anything beyond that is - // rendered via columnDraw. - uint8_t itemColumns; - - uiscrolling_t scroll; - uifocusitem_t *focusItem; - - uiitemlistselectedcallback_t selected; - uiitemlistchangedcallback_t changed; - uiitemlistclosedcallback_t closed; - uiitemlistcolumncallback_t columnDraw; - - void *user; -}; - -/** - * Initializes an item list. - * - * @param list The item list to initialize. - * @param columns Number of item slots per row. - * @param rows Number of item slot rows. - * @param itemColumns Number of info columns rendered per item slot. - * @param selected Called when an item slot is selected. - * @param changed Called when the focused item slot changes. - * @param closed Called when the item list is closed. - * @param columnDraw Called to draw each extra info column (index >= 1); - * may be NULL if itemColumns is 1. - */ -void uiItemListInit( - uiitemlist_t *list, - const uint8_t columns, - const uint8_t rows, - const uint8_t itemColumns, - uiitemlistselectedcallback_t selected, - uiitemlistchangedcallback_t changed, - uiitemlistclosedcallback_t closed, - uiitemlistcolumncallback_t columnDraw -); - -/** - * Sets the items displayed by the list directly, copying them into - * the list's own storage. - * - * @param list The item list to update. - * @param items The items to display. - * @param itemCount Number of entries in items. Must be <= - * UI_ITEM_LIST_CAPACITY_MAX. - */ -void uiItemListSetItems( - uiitemlist_t *list, - const uiitem_t *items, - const uint8_t itemCount -); - -/** - * Sets the items displayed by the list from an array of item stacks, - * internally creating a uiitem_t for each stack. - * - * @param list The item list to update. - * @param stacks The item stacks to display. - * @param stackCount Number of entries in stacks. Must be <= - * UI_ITEM_LIST_CAPACITY_MAX. - * @return Any error that occurs. - */ -errorret_t uiItemListSetItemStacks( - uiitemlist_t *list, - const inventorystack_t *stacks, - const uint8_t stackCount -); - -/** - * Pushes the item list onto the UI focus stack, making it navigable. - * No-op if already open. - * - * @param list The item list to open. - */ -void uiItemListOpen(uiitemlist_t *list); - -/** - * Pops the item list from the UI focus stack. No-op if already closed. - * - * @param list The item list to close. - */ -void uiItemListClose(uiitemlist_t *list); - -/** - * Returns whether the item list is currently on the UI focus stack. - * - * @param list The item list to query. - * @returns True if active. - */ -bool_t uiItemListIsActive(const uiitemlist_t *list); - -/** - * Draws the item list's grid of item slots at the given position. - * Only the first columns * rows items are drawn. - * - * @param list The item list to draw. - * @param x Screen x position. - * @param y Screen y position. - * @param width Content width, used to lay out columns. - * @return Any error that occurs. - */ -errorret_t uiItemListDraw( - const uiitemlist_t *list, - const float_t x, - const float_t y, - const float_t width -); - -/** - * Internal focus callback -- forwards selection to the list's selected - * handler. - * - * @param focusItem The active focus item; user field must point to - * uiitemlist_t. - * @returns True. - */ -bool_t uiItemListFocusSelected(const uifocusitem_t *focusItem); - -/** - * Internal focus callback -- updates item highlights and fires - * changed. - * - * @param focusItem The active focus item; user field must point to - * uiitemlist_t. - * @returns True. - */ -bool_t uiItemListFocusChanged(const uifocusitem_t *focusItem); - -/** - * Internal focus callback -- clears focusItem and fires the closed - * handler. - * - * @param focusItem The active focus item; user field must point to - * uiitemlist_t. - * @returns True. - */ -bool_t uiItemListFocusClosed(const uifocusitem_t *focusItem); diff --git a/src/duskdolphin/CMakeLists.txt b/src/duskdolphin/CMakeLists.txt index 818635ee..78be2119 100644 --- a/src/duskdolphin/CMakeLists.txt +++ b/src/duskdolphin/CMakeLists.txt @@ -20,6 +20,5 @@ add_subdirectory(log) add_subdirectory(display) add_subdirectory(input) add_subdirectory(network) -add_subdirectory(save) add_subdirectory(system) add_subdirectory(time) \ No newline at end of file diff --git a/src/duskdolphin/save/CMakeLists.txt b/src/duskdolphin/save/CMakeLists.txt deleted file mode 100644 index 95b853df..00000000 --- a/src/duskdolphin/save/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - savedolphin.c - savestreamdolphin.c -) diff --git a/src/duskdolphin/save/savedolphin.c b/src/duskdolphin/save/savedolphin.c deleted file mode 100644 index 0d1694a7..00000000 --- a/src/duskdolphin/save/savedolphin.c +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" -#include "util/memory.h" -#include "util/string.h" - -static void _saveGetFileName( - const uint8_t slot, char_t *out, const size_t max -) { - snprintf(out, max, "%s_%u", SAVE_DOLPHIN_GAME_CODE, (uint32_t)slot); -} - -errorret_t saveInitDolphin(void) { - SAVE.platform.mounted = false; - - int32_t result = CARD_Mount( - SAVE_DOLPHIN_CHANNEL, - SAVE.platform.cardBuffer, - NULL - ); - - if(result < 0) { - errorThrow("Failed to mount memory card (error %d)", result); - } - - SAVE.platform.mounted = true; - errorOk(); -} - -errorret_t saveDisposeDolphin(void) { - if(SAVE.platform.mounted) { - CARD_Unmount(SAVE_DOLPHIN_CHANNEL); - SAVE.platform.mounted = false; - } - errorOk(); -} - -errorret_t saveLoadDolphin(const uint8_t slot, savefile_t *file) { - char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; - _saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX); - - int32_t result = CARD_Open( - SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile - ); - if(result == CARD_ERROR_NOFILE) { - file->exists = false; - errorOk(); - } - if(result < 0) { - file->exists = false; - errorThrow("Failed to open memory card file for slot %u (error %d)", - (uint32_t)slot, result - ); - } - - void *buffer = memoryAlign(32, SAVE_DOLPHIN_SECTOR_SIZE); - if(!buffer) { - CARD_Close(&SAVE.platform.cardFile); - errorThrow("Failed to allocate memory card read buffer"); - } - - result = CARD_Read( - &SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0 - ); - CARD_Close(&SAVE.platform.cardFile); - - if(result < 0) { - memoryFree(buffer); - file->exists = false; - errorThrow("Failed to read memory card data for slot %u (error %d)", - (uint32_t)slot, result - ); - } - - memoryCopy(file, buffer, sizeof(savefile_t)); - memoryFree(buffer); - - file->exists = true; - errorOk(); -} - -errorret_t saveWriteDolphin(const uint8_t slot, const savefile_t *file) { - char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; - _saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX); - - void *buffer = memoryAlign(32, SAVE_DOLPHIN_SECTOR_SIZE); - if(!buffer) { - errorThrow("Failed to allocate memory card write buffer"); - } - memoryZero(buffer, SAVE_DOLPHIN_SECTOR_SIZE); - memoryCopy(buffer, file, sizeof(savefile_t)); - - // Try open existing file first; create if absent. - int32_t result = CARD_Open( - SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile - ); - if(result == CARD_ERROR_NOFILE) { - result = CARD_Create( - SAVE_DOLPHIN_CHANNEL, - fileName, - SAVE_DOLPHIN_SECTOR_SIZE, - &SAVE.platform.cardFile - ); - } - - if(result < 0) { - memoryFree(buffer); - errorThrow("Failed to open/create memory card file for slot %u (error %d)", - (uint32_t)slot, result - ); - } - - result = CARD_Write( - &SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0 - ); - CARD_Close(&SAVE.platform.cardFile); - memoryFree(buffer); - - if(result < 0) { - errorThrow("Failed to write memory card data for slot %u (error %d)", - (uint32_t)slot, result - ); - } - - errorOk(); -} - -errorret_t saveDeleteDolphin(const uint8_t slot) { - char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; - _saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX); - - int32_t result = CARD_Delete(SAVE_DOLPHIN_CHANNEL, fileName); - if(result < 0 && result != CARD_ERROR_NOFILE) { - errorThrow("Failed to delete memory card file for slot %u (error %d)", - (uint32_t)slot, result - ); - } - - errorOk(); -} diff --git a/src/duskdolphin/save/savedolphin.h b/src/duskdolphin/save/savedolphin.h deleted file mode 100644 index 1408ba89..00000000 --- a/src/duskdolphin/save/savedolphin.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "save/savefile.h" -#include - -#define SAVE_DOLPHIN_FILE_NAME_MAX 32 -#define SAVE_DOLPHIN_SECTOR_SIZE 8192 - -#ifndef SAVE_DOLPHIN_GAME_CODE - #define SAVE_DOLPHIN_GAME_CODE "DUSK" -#endif - -#ifndef SAVE_DOLPHIN_CHANNEL - #define SAVE_DOLPHIN_CHANNEL CARD_SLOTA -#endif - -typedef struct { - card_file cardFile; - uint8_t cardBuffer[CARD_WORKAREA] __attribute__((aligned(32))); - bool_t mounted; -} savedolphin_t; - -/** - * Initializes the save system on GameCube (memory card slot A by default). - * - * @return An error code if initialization fails. - */ -errorret_t saveInitDolphin(void); - -/** - * Disposes of the save system on GameCube. - * - * @return An error code if disposal fails. - */ -errorret_t saveDisposeDolphin(void); - -/** - * Loads a save file from the memory card for the given slot. - * - * @param slot The save slot index. - * @param file Output save file data. - * @return An error code if the load fails. - */ -errorret_t saveLoadDolphin(const uint8_t slot, savefile_t *file); - -/** - * Writes a save file to the memory card for the given slot. - * - * @param slot The save slot index. - * @param file Save file data to write. - * @return An error code if the write fails. - */ -errorret_t saveWriteDolphin(const uint8_t slot, const savefile_t *file); - -/** - * Deletes the save file for the given slot from the memory card. - * - * @param slot The save slot index. - * @return An error code if the delete fails. - */ -errorret_t saveDeleteDolphin(const uint8_t slot); diff --git a/src/duskdolphin/save/saveplatform.h b/src/duskdolphin/save/saveplatform.h deleted file mode 100644 index 510b5d26..00000000 --- a/src/duskdolphin/save/saveplatform.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "save/savedolphin.h" -#include "save/savestreamdolphin.h" - -typedef savedolphin_t saveplatform_t; -typedef savestreamdolphin_t saveplatformstream_t; - -#define saveInitPlatform saveInitDolphin -#define saveDisposePlatform saveDisposeDolphin -#define saveDeletePlatform saveDeleteDolphin - -#define saveStreamOpenReadPlatform(stream, slot) \ - saveStreamOpenReadDolphin(&(stream)->platform, &(stream)->found, slot) -#define saveStreamOpenWritePlatform(stream, slot) \ - saveStreamOpenWriteDolphin(&(stream)->platform, slot) -#define saveStreamClosePlatform(stream) \ - saveStreamCloseDolphin(&(stream)->platform) -#define saveStreamReadBytesPlatform(stream, buf, len) \ - saveStreamReadBytesDolphin(&(stream)->platform, buf, len) -#define saveStreamWriteBytesPlatform(stream, buf, len) \ - saveStreamWriteBytesDolphin(&(stream)->platform, buf, len) -#define saveStreamSeekPlatform(stream, pos) \ - saveStreamSeekDolphin(&(stream)->platform, pos) diff --git a/src/duskdolphin/save/savestreamdolphin.c b/src/duskdolphin/save/savestreamdolphin.c deleted file mode 100644 index 45411c1b..00000000 --- a/src/duskdolphin/save/savestreamdolphin.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" -#include "save/savestreamdolphin.h" -#include "util/memory.h" -#include "util/string.h" - -static void _saveStreamGetFileName( - char_t *out, const size_t max, const uint8_t slot -) { - snprintf(out, max, "%s_%u", SAVE_DOLPHIN_GAME_CODE, (uint32_t)slot); -} - -errorret_t saveStreamOpenReadDolphin( - savestreamdolphin_t *p, bool_t *found, const uint8_t slot -) { - char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; - _saveStreamGetFileName(fileName, SAVE_DOLPHIN_FILE_NAME_MAX, slot); - - int32_t result = CARD_Open( - SAVE_DOLPHIN_CHANNEL, fileName, &p->cardFile - ); - if(result == CARD_ERROR_NOFILE) { - *found = false; - p->position = 0; - p->writing = false; - errorOk(); - } - if(result < 0) { - *found = false; - errorThrow("Failed to open memory card file for slot %u (error %d)", - (uint32_t)slot, result - ); - } - - result = CARD_Read(&p->cardFile, p->buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0); - CARD_Close(&p->cardFile); - if(result < 0) { - *found = false; - errorThrow("Failed to read memory card data for slot %u (error %d)", - (uint32_t)slot, result - ); - } - - *found = true; - p->position = 0; - p->writing = false; - p->slot = slot; - errorOk(); -} - -errorret_t saveStreamOpenWriteDolphin( - savestreamdolphin_t *p, const uint8_t slot -) { - memoryZero(p->buffer, SAVE_DOLPHIN_SECTOR_SIZE); - p->position = 0; - p->writing = true; - p->slot = slot; - errorOk(); -} - -void saveStreamCloseDolphin(savestreamdolphin_t *p) { - if(!p->writing) return; - - char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; - _saveStreamGetFileName(fileName, SAVE_DOLPHIN_FILE_NAME_MAX, p->slot); - - int32_t result = CARD_Open(SAVE_DOLPHIN_CHANNEL, fileName, &p->cardFile); - if(result == CARD_ERROR_NOFILE) { - CARD_Create( - SAVE_DOLPHIN_CHANNEL, fileName, SAVE_DOLPHIN_SECTOR_SIZE, &p->cardFile - ); - } - - CARD_Write(&p->cardFile, p->buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0); - CARD_Close(&p->cardFile); -} - -errorret_t saveStreamReadBytesDolphin( - savestreamdolphin_t *p, void *buf, const size_t len -) { - if(p->position + len > SAVE_DOLPHIN_SECTOR_SIZE) { - errorThrow("Save stream read exceeds sector size"); - } - memoryCopy(buf, p->buffer + p->position, len); - p->position += len; - errorOk(); -} - -errorret_t saveStreamWriteBytesDolphin( - savestreamdolphin_t *p, const void *buf, const size_t len -) { - if(p->position + len > SAVE_DOLPHIN_SECTOR_SIZE) { - errorThrow("Save stream write exceeds sector size"); - } - memoryCopy(p->buffer + p->position, buf, len); - p->position += len; - errorOk(); -} - -errorret_t saveStreamSeekDolphin(savestreamdolphin_t *p, const size_t pos) { - if(pos >= SAVE_DOLPHIN_SECTOR_SIZE) { - errorThrow("Save stream seek out of range"); - } - p->position = pos; - errorOk(); -} diff --git a/src/duskdolphin/save/savestreamdolphin.h b/src/duskdolphin/save/savestreamdolphin.h deleted file mode 100644 index 2b351fe6..00000000 --- a/src/duskdolphin/save/savestreamdolphin.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "save/savedolphin.h" -#include -#include - -typedef struct { - /** libogc memory card file handle. */ - card_file cardFile; - /** In-memory sector buffer; all reads and writes operate on this. */ - uint8_t buffer[SAVE_DOLPHIN_SECTOR_SIZE] __attribute__((aligned(32))); - /** Current read/write position within buffer. */ - size_t position; - /** True when opened for writing; flushes buffer to card on close. */ - bool_t writing; - /** Slot index stored at open time so Close can derive the filename. */ - uint8_t slot; -} savestreamdolphin_t; - -/** - * Opens a memory card slot for reading by loading its sector into buffer. - * - * @param p Stream to initialize. - * @param found Set to true if the file exists, false if it does not. - * @param slot Save slot index. - * @return An error if reading the card fails for a reason other than - * missing file. - */ -errorret_t saveStreamOpenReadDolphin( - savestreamdolphin_t *p, bool_t *found, const uint8_t slot -); - -/** - * Opens a memory card slot for writing by zeroing the sector buffer. - * The buffer is flushed to the card when savestreamCloseDolphin is called. - * - * @param p Stream to initialize. - * @param slot Save slot index. - * @return An error if initialization fails. - */ -errorret_t saveStreamOpenWriteDolphin( - savestreamdolphin_t *p, const uint8_t slot -); - -/** - * Flushes the sector buffer to the memory card (write mode only) and - * releases the card file handle. - * - * @param p Stream to close. - */ -void saveStreamCloseDolphin(savestreamdolphin_t *p); - -/** - * Copies len bytes from the sector buffer at the current position into buf. - * - * @param p Active stream. - * @param buf Destination buffer. - * @param len Number of bytes to read. - * @return An error if the read would exceed the sector size. - */ -errorret_t saveStreamReadBytesDolphin( - savestreamdolphin_t *p, void *buf, const size_t len -); - -/** - * Copies len bytes from buf into the sector buffer at the current position. - * - * @param p Active stream. - * @param buf Source buffer. - * @param len Number of bytes to write. - * @return An error if the write would exceed the sector size. - */ -errorret_t saveStreamWriteBytesDolphin( - savestreamdolphin_t *p, const void *buf, const size_t len -); - -/** - * Sets the current read/write position within the sector buffer. - * - * @param p Active stream. - * @param pos Target byte offset from the start of the sector. - * @return An error if pos is out of range. - */ -errorret_t saveStreamSeekDolphin(savestreamdolphin_t *p, const size_t pos); diff --git a/src/dusklinux/CMakeLists.txt b/src/dusklinux/CMakeLists.txt index af0e8acb..7771e18d 100644 --- a/src/dusklinux/CMakeLists.txt +++ b/src/dusklinux/CMakeLists.txt @@ -14,6 +14,5 @@ add_subdirectory(asset) add_subdirectory(log) add_subdirectory(input) add_subdirectory(network) -add_subdirectory(save) add_subdirectory(system) add_subdirectory(time) \ No newline at end of file diff --git a/src/dusklinux/save/CMakeLists.txt b/src/dusklinux/save/CMakeLists.txt deleted file mode 100644 index 74b1dcc7..00000000 --- a/src/dusklinux/save/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - savelinux.c - savestreamlinux.c -) diff --git a/src/dusklinux/save/savelinux.c b/src/dusklinux/save/savelinux.c deleted file mode 100644 index 0b672464..00000000 --- a/src/dusklinux/save/savelinux.c +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" -#include "util/string.h" -#include -#include -#include - -errorret_t saveInitLinux(void) { - stringCopy(SAVE.platform.savePath, SAVE_LINUX_PATH, SAVE_LINUX_PATH_MAX); - - if(mkdir(SAVE.platform.savePath, 0755) != 0 && errno != EEXIST) { - errorThrow("Failed to create save directory: %s", SAVE.platform.savePath); - } - - errorOk(); -} - -errorret_t saveDisposeLinux(void) { - errorOk(); -} - -errorret_t saveLoadLinux(const uint8_t slot, savefile_t *file) { - char_t path[SAVE_LINUX_PATH_MAX]; - snprintf(path, SAVE_LINUX_PATH_MAX, SAVE_LINUX_FILE_FORMAT, - SAVE.platform.savePath, (uint32_t)slot - ); - - FILE *f = fopen(path, "rb"); - if(!f) { - file->exists = false; - errorOk(); - } - - size_t read = fread(file, sizeof(savefile_t), 1, f); - fclose(f); - - if(read != 1) { - file->exists = false; - errorThrow("Failed to read save data for slot %u", (uint32_t)slot); - } - - file->exists = true; - errorOk(); -} - -errorret_t saveWriteLinux(const uint8_t slot, const savefile_t *file) { - char_t path[SAVE_LINUX_PATH_MAX]; - snprintf(path, SAVE_LINUX_PATH_MAX, SAVE_LINUX_FILE_FORMAT, - SAVE.platform.savePath, (uint32_t)slot - ); - - FILE *f = fopen(path, "wb"); - if(!f) { - errorThrow("Failed to open save file for writing: slot %u", (uint32_t)slot); - } - - size_t written = fwrite(file, sizeof(savefile_t), 1, f); - fclose(f); - - if(written != 1) { - errorThrow("Failed to write save data for slot %u", (uint32_t)slot); - } - - errorOk(); -} - -errorret_t saveDeleteLinux(const uint8_t slot) { - char_t path[SAVE_LINUX_PATH_MAX]; - snprintf(path, SAVE_LINUX_PATH_MAX, SAVE_LINUX_FILE_FORMAT, - SAVE.platform.savePath, (uint32_t)slot - ); - - if(remove(path) != 0 && errno != ENOENT) { - errorThrow("Failed to delete save file for slot %u", (uint32_t)slot); - } - - errorOk(); -} diff --git a/src/dusklinux/save/savelinux.h b/src/dusklinux/save/savelinux.h deleted file mode 100644 index 1f99066e..00000000 --- a/src/dusklinux/save/savelinux.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "save/savefile.h" - -#define SAVE_LINUX_PATH_MAX FILENAME_MAX -#define SAVE_LINUX_FILE_FORMAT "%s/save_%u.dat" - -#ifndef SAVE_LINUX_PATH - #define SAVE_LINUX_PATH "./saves" -#endif - -typedef struct { - char_t savePath[SAVE_LINUX_PATH_MAX]; -} savelinux_t; - -/** - * Initializes the save system on Linux. - * - * @return An error code if initialization fails. - */ -errorret_t saveInitLinux(void); - -/** - * Disposes of the save system on Linux. - * - * @return An error code if disposal fails. - */ -errorret_t saveDisposeLinux(void); - -/** - * Loads a save file from disk for the given slot. - * - * @param slot The save slot index. - * @param file Output save file data. - * @return An error code if the load fails. - */ -errorret_t saveLoadLinux(const uint8_t slot, savefile_t *file); - -/** - * Writes a save file to disk for the given slot. - * - * @param slot The save slot index. - * @param file Save file data to write. - * @return An error code if the write fails. - */ -errorret_t saveWriteLinux(const uint8_t slot, const savefile_t *file); - -/** - * Deletes the save file for the given slot from disk. - * - * @param slot The save slot index. - * @return An error code if the delete fails. - */ -errorret_t saveDeleteLinux(const uint8_t slot); diff --git a/src/dusklinux/save/saveplatform.h b/src/dusklinux/save/saveplatform.h deleted file mode 100644 index 24f80972..00000000 --- a/src/dusklinux/save/saveplatform.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "save/savelinux.h" -#include "save/savestreamlinux.h" - -typedef savelinux_t saveplatform_t; -typedef savestreamlinux_t saveplatformstream_t; - -#define saveInitPlatform saveInitLinux -#define saveDisposePlatform saveDisposeLinux -#define saveDeletePlatform saveDeleteLinux - -#define saveStreamOpenReadPlatform(stream, slot) \ - saveStreamOpenReadLinux(&(stream)->platform, &(stream)->found, slot) -#define saveStreamOpenWritePlatform(stream, slot) \ - saveStreamOpenWriteLinux(&(stream)->platform, slot) -#define saveStreamClosePlatform(stream) \ - saveStreamCloseLinux(&(stream)->platform) -#define saveStreamReadBytesPlatform(stream, buf, len) \ - saveStreamReadBytesLinux(&(stream)->platform, buf, len) -#define saveStreamWriteBytesPlatform(stream, buf, len) \ - saveStreamWriteBytesLinux(&(stream)->platform, buf, len) -#define saveStreamSeekPlatform(stream, pos) \ - saveStreamSeekLinux(&(stream)->platform, pos) diff --git a/src/dusklinux/save/savestreamlinux.c b/src/dusklinux/save/savestreamlinux.c deleted file mode 100644 index e4879ad4..00000000 --- a/src/dusklinux/save/savestreamlinux.c +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" -#include "save/savestreamlinux.h" -#include "util/string.h" -#include -#include - -static void _saveStreamGetPath( - char_t *out, const size_t max, const uint8_t slot -) { - snprintf( - out, max, SAVE_LINUX_FILE_FORMAT, - SAVE.platform.savePath, (uint32_t)slot - ); -} - -errorret_t saveStreamOpenReadLinux( - savestreamlinux_t *p, bool_t *found, const uint8_t slot -) { - char_t path[SAVE_LINUX_PATH_MAX]; - _saveStreamGetPath(path, SAVE_LINUX_PATH_MAX, slot); - - p->file = fopen(path, "rb"); - *found = (p->file != NULL); - errorOk(); -} - -errorret_t saveStreamOpenWriteLinux(savestreamlinux_t *p, const uint8_t slot) { - char_t path[SAVE_LINUX_PATH_MAX]; - _saveStreamGetPath(path, SAVE_LINUX_PATH_MAX, slot); - - p->file = fopen(path, "wb"); - if(!p->file) { - errorThrow("Failed to open save file for writing: slot %u", (uint32_t)slot); - } - errorOk(); -} - -void saveStreamCloseLinux(savestreamlinux_t *p) { - if(p->file) { - fclose(p->file); - p->file = NULL; - } -} - -errorret_t saveStreamReadBytesLinux( - savestreamlinux_t *p, void *buf, const size_t len -) { - if(fread(buf, 1, len, p->file) != len) { - errorThrow("Unexpected end of save file"); - } - errorOk(); -} - -errorret_t saveStreamWriteBytesLinux( - savestreamlinux_t *p, const void *buf, const size_t len -) { - if(fwrite(buf, 1, len, p->file) != len) { - errorThrow("Failed to write save data"); - } - errorOk(); -} - -errorret_t saveStreamSeekLinux(savestreamlinux_t *p, const size_t pos) { - if(fseek(p->file, (long)pos, SEEK_SET) != 0) { - errorThrow("Failed to seek in save file"); - } - errorOk(); -} diff --git a/src/dusklinux/save/savestreamlinux.h b/src/dusklinux/save/savestreamlinux.h deleted file mode 100644 index 3d8a1f58..00000000 --- a/src/dusklinux/save/savestreamlinux.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include -#include - -typedef struct { - FILE *file; -} savestreamlinux_t; - -/** - * Opens a save slot file for reading. - * - * @param p Stream to initialize. - * @param found Set to true if the file exists, false if it does not. - * @param slot Save slot index. - * @return An error if the open fails for a reason other than missing file. - */ -errorret_t saveStreamOpenReadLinux( - savestreamlinux_t *p, bool_t *found, const uint8_t slot -); - -/** - * Opens a save slot file for writing, creating or truncating it. - * - * @param p Stream to initialize. - * @param slot Save slot index. - * @return An error if the file cannot be opened for writing. - */ -errorret_t saveStreamOpenWriteLinux( - savestreamlinux_t *p, const uint8_t slot -); - -/** - * Closes the file handle held by the stream. - * - * @param p Stream to close. - */ -void saveStreamCloseLinux(savestreamlinux_t *p); - -/** - * Reads len bytes from the stream into buf. - * - * @param p Active stream. - * @param buf Destination buffer. - * @param len Number of bytes to read. - * @return An error if fewer than len bytes are available. - */ -errorret_t saveStreamReadBytesLinux( - savestreamlinux_t *p, void *buf, const size_t len -); - -/** - * Writes len bytes from buf into the stream. - * - * @param p Active stream. - * @param buf Source buffer. - * @param len Number of bytes to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteBytesLinux( - savestreamlinux_t *p, const void *buf, const size_t len -); - -/** - * Seeks to an absolute byte position within the stream. - * - * @param p Active stream. - * @param pos Target byte offset from the start of the file. - * @return An error if the seek fails. - */ -errorret_t saveStreamSeekLinux(savestreamlinux_t *p, const size_t pos); diff --git a/src/duskpsp/CMakeLists.txt b/src/duskpsp/CMakeLists.txt index ca661aa5..1bdee020 100644 --- a/src/duskpsp/CMakeLists.txt +++ b/src/duskpsp/CMakeLists.txt @@ -19,6 +19,5 @@ add_subdirectory(asset) add_subdirectory(input) add_subdirectory(log) add_subdirectory(network) -add_subdirectory(save) add_subdirectory(system) add_subdirectory(time) \ No newline at end of file diff --git a/src/duskpsp/save/CMakeLists.txt b/src/duskpsp/save/CMakeLists.txt deleted file mode 100644 index ee6cc44a..00000000 --- a/src/duskpsp/save/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - savepsp.c - savestreampsp.c -) diff --git a/src/duskpsp/save/saveplatform.h b/src/duskpsp/save/saveplatform.h deleted file mode 100644 index 44db5a7f..00000000 --- a/src/duskpsp/save/saveplatform.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "save/savepsp.h" -#include "save/savestreampsp.h" - -typedef savepsp_t saveplatform_t; -typedef savestreampsp_t saveplatformstream_t; - -#define saveInitPlatform saveInitPSP -#define saveDisposePlatform saveDisposePSP -#define saveDeletePlatform saveDeletePSP - -#define saveStreamOpenReadPlatform(stream, slot) \ - saveStreamOpenReadPSP(&(stream)->platform, &(stream)->found, slot) -#define saveStreamOpenWritePlatform(stream, slot) \ - saveStreamOpenWritePSP(&(stream)->platform, slot) -#define saveStreamClosePlatform(stream) \ - saveStreamClosePSP(&(stream)->platform) -#define saveStreamReadBytesPlatform(stream, buf, len) \ - saveStreamReadBytesPSP(&(stream)->platform, buf, len) -#define saveStreamWriteBytesPlatform(stream, buf, len) \ - saveStreamWriteBytesPSP(&(stream)->platform, buf, len) -#define saveStreamSeekPlatform(stream, pos) \ - saveStreamSeekPSP(&(stream)->platform, pos) diff --git a/src/duskpsp/save/savepsp.c b/src/duskpsp/save/savepsp.c deleted file mode 100644 index 2038292b..00000000 --- a/src/duskpsp/save/savepsp.c +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" - -errorret_t saveInitPSP(void) { - errorOk(); -} - -errorret_t saveDisposePSP(void) { - errorOk(); -} - -errorret_t saveLoadPSP(const uint8_t slot, savefile_t *file) { - char_t path[SAVE_PSP_PATH_MAX]; - snprintf(path, SAVE_PSP_PATH_MAX, SAVE_PSP_FILE_FORMAT, - SAVE_PSP_TITLE_ID, (uint32_t)slot - ); - - SceUID fd = sceIoOpen(path, PSP_O_RDONLY, 0); - if(fd < 0) { - file->exists = false; - errorOk(); - } - - int32_t read = sceIoRead(fd, file, sizeof(savefile_t)); - sceIoClose(fd); - - if(read != (int32_t)sizeof(savefile_t)) { - file->exists = false; - errorThrow("Failed to read save data for slot %u", (uint32_t)slot); - } - - file->exists = true; - errorOk(); -} - -errorret_t saveWritePSP(const uint8_t slot, const savefile_t *file) { - char_t dir[SAVE_PSP_PATH_MAX]; - snprintf(dir, SAVE_PSP_PATH_MAX, SAVE_PSP_DIR_FORMAT, - SAVE_PSP_TITLE_ID, (uint32_t)slot - ); - sceIoMkdir(dir, 0777); - - char_t path[SAVE_PSP_PATH_MAX]; - snprintf(path, SAVE_PSP_PATH_MAX, SAVE_PSP_FILE_FORMAT, - SAVE_PSP_TITLE_ID, (uint32_t)slot - ); - - SceUID fd = sceIoOpen(path, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777); - if(fd < 0) { - errorThrow("Failed to open save file for writing: slot %u", (uint32_t)slot); - } - - int32_t written = sceIoWrite(fd, file, sizeof(savefile_t)); - sceIoClose(fd); - - if(written != (int32_t)sizeof(savefile_t)) { - errorThrow("Failed to write save data for slot %u", (uint32_t)slot); - } - - errorOk(); -} - -errorret_t saveDeletePSP(const uint8_t slot) { - char_t path[SAVE_PSP_PATH_MAX]; - snprintf(path, SAVE_PSP_PATH_MAX, SAVE_PSP_FILE_FORMAT, - SAVE_PSP_TITLE_ID, (uint32_t)slot - ); - - int32_t result = sceIoRemove(path); - if(result < 0 && result != (int32_t)0x80010002) { - errorThrow("Failed to delete save file for slot %u", (uint32_t)slot); - } - - errorOk(); -} diff --git a/src/duskpsp/save/savepsp.h b/src/duskpsp/save/savepsp.h deleted file mode 100644 index c498f89a..00000000 --- a/src/duskpsp/save/savepsp.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "save/savefile.h" -#include - -#define SAVE_PSP_PATH_MAX 256 -#define SAVE_PSP_FILE_FORMAT "ms0:/PSP/SAVEDATA/%s%02u/save.dat" -#define SAVE_PSP_DIR_FORMAT "ms0:/PSP/SAVEDATA/%s%02u" - -#ifndef SAVE_PSP_TITLE_ID - #define SAVE_PSP_TITLE_ID "DUSK00001" -#endif - -typedef struct { - uint8_t unused; -} savepsp_t; - -/** - * Initializes the save system on PSP. - * - * @return An error code if initialization fails. - */ -errorret_t saveInitPSP(void); - -/** - * Disposes of the save system on PSP. - * - * @return An error code if disposal fails. - */ -errorret_t saveDisposePSP(void); - -/** - * Loads a save file from PSP save data for the given slot. - * - * @param slot The save slot index. - * @param file Output save file data. - * @return An error code if the load fails. - */ -errorret_t saveLoadPSP(const uint8_t slot, savefile_t *file); - -/** - * Writes a save file to PSP save data for the given slot. - * - * @param slot The save slot index. - * @param file Save file data to write. - * @return An error code if the write fails. - */ -errorret_t saveWritePSP(const uint8_t slot, const savefile_t *file); - -/** - * Deletes the save file for the given slot from PSP save data. - * - * @param slot The save slot index. - * @return An error code if the delete fails. - */ -errorret_t saveDeletePSP(const uint8_t slot); diff --git a/src/duskpsp/save/savestreampsp.c b/src/duskpsp/save/savestreampsp.c deleted file mode 100644 index 5adef148..00000000 --- a/src/duskpsp/save/savestreampsp.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" -#include "save/savestreampsp.h" - -errorret_t saveStreamOpenReadPSP( - savestreampsp_t *p, bool_t *found, const uint8_t slot -) { - char_t path[SAVE_PSP_PATH_MAX]; - snprintf(path, SAVE_PSP_PATH_MAX, SAVE_PSP_FILE_FORMAT, - SAVE_PSP_TITLE_ID, (uint32_t)slot - ); - - p->fd = sceIoOpen(path, PSP_O_RDONLY, 0); - *found = (p->fd >= 0); - errorOk(); -} - -errorret_t saveStreamOpenWritePSP(savestreampsp_t *p, const uint8_t slot) { - char_t dir[SAVE_PSP_PATH_MAX]; - snprintf(dir, SAVE_PSP_PATH_MAX, SAVE_PSP_DIR_FORMAT, - SAVE_PSP_TITLE_ID, (uint32_t)slot - ); - sceIoMkdir(dir, 0777); - - char_t path[SAVE_PSP_PATH_MAX]; - snprintf(path, SAVE_PSP_PATH_MAX, SAVE_PSP_FILE_FORMAT, - SAVE_PSP_TITLE_ID, (uint32_t)slot - ); - - p->fd = sceIoOpen(path, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777); - if(p->fd < 0) { - errorThrow( - "Failed to open PSP save file for writing: slot %u", (uint32_t)slot - ); - } - errorOk(); -} - -void saveStreamClosePSP(savestreampsp_t *p) { - if(p->fd >= 0) { - sceIoClose(p->fd); - p->fd = -1; - } -} - -errorret_t saveStreamReadBytesPSP( - savestreampsp_t *p, void *buf, const size_t len -) { - int32_t read = sceIoRead(p->fd, buf, (SceSize)len); - if(read != (int32_t)len) { - errorThrow("Unexpected end of PSP save file"); - } - errorOk(); -} - -errorret_t saveStreamWriteBytesPSP( - savestreampsp_t *p, const void *buf, const size_t len -) { - int32_t written = sceIoWrite(p->fd, buf, (SceSize)len); - if(written != (int32_t)len) { - errorThrow("Failed to write PSP save data"); - } - errorOk(); -} - -errorret_t saveStreamSeekPSP(savestreampsp_t *p, const size_t pos) { - if(sceIoLseek(p->fd, (SceOff)pos, PSP_SEEK_SET) < 0) { - errorThrow("Failed to seek in PSP save file"); - } - errorOk(); -} diff --git a/src/duskpsp/save/savestreampsp.h b/src/duskpsp/save/savestreampsp.h deleted file mode 100644 index 2574833b..00000000 --- a/src/duskpsp/save/savestreampsp.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include -#include - -typedef struct { - SceUID fd; -} savestreampsp_t; - -/** - * Opens a PSP save data file for reading. - * - * @param p Stream to initialize. - * @param found Set to true if the file exists, false if it does not. - * @param slot Save slot index. - * @return An error if the open fails for a reason other than missing file. - */ -errorret_t saveStreamOpenReadPSP( - savestreampsp_t *p, bool_t *found, const uint8_t slot -); - -/** - * Opens a PSP save data file for writing, creating or truncating it. - * Creates the save data directory if it does not already exist. - * - * @param p Stream to initialize. - * @param slot Save slot index. - * @return An error if the file cannot be opened for writing. - */ -errorret_t saveStreamOpenWritePSP(savestreampsp_t *p, const uint8_t slot); - -/** - * Closes the file descriptor held by the stream. - * - * @param p Stream to close. - */ -void saveStreamClosePSP(savestreampsp_t *p); - -/** - * Reads len bytes from the stream into buf. - * - * @param p Active stream. - * @param buf Destination buffer. - * @param len Number of bytes to read. - * @return An error if fewer than len bytes are available. - */ -errorret_t saveStreamReadBytesPSP( - savestreampsp_t *p, void *buf, const size_t len -); - -/** - * Writes len bytes from buf into the stream. - * - * @param p Active stream. - * @param buf Source buffer. - * @param len Number of bytes to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteBytesPSP( - savestreampsp_t *p, const void *buf, const size_t len -); - -/** - * Seeks to an absolute byte position within the stream. - * - * @param p Active stream. - * @param pos Target byte offset from the start of the file. - * @return An error if the seek fails. - */ -errorret_t saveStreamSeekPSP(savestreampsp_t *p, const size_t pos); diff --git a/src/duskvita/CMakeLists.txt b/src/duskvita/CMakeLists.txt index 8e31820d..ab5edee9 100644 --- a/src/duskvita/CMakeLists.txt +++ b/src/duskvita/CMakeLists.txt @@ -18,4 +18,3 @@ target_sources(${DUSK_BINARY_TARGET_NAME} add_subdirectory(asset) add_subdirectory(input) add_subdirectory(log) -add_subdirectory(save) diff --git a/src/duskvita/save/CMakeLists.txt b/src/duskvita/save/CMakeLists.txt deleted file mode 100644 index ffa8c58f..00000000 --- a/src/duskvita/save/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - savevita.c - savestreamvita.c -) diff --git a/src/duskvita/save/saveplatform.h b/src/duskvita/save/saveplatform.h deleted file mode 100644 index 47dfeb6d..00000000 --- a/src/duskvita/save/saveplatform.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "save/savevita.h" -#include "save/savestreamvita.h" - -typedef savevita_t saveplatform_t; -typedef savestreamvita_t saveplatformstream_t; - -#define saveInitPlatform saveInitVita -#define saveDisposePlatform saveDisposeVita -#define saveDeletePlatform saveDeleteVita - -#define saveStreamOpenReadPlatform(stream, slot) \ - saveStreamOpenReadVita(&(stream)->platform, &(stream)->found, slot) -#define saveStreamOpenWritePlatform(stream, slot) \ - saveStreamOpenWriteVita(&(stream)->platform, slot) -#define saveStreamClosePlatform(stream) \ - saveStreamCloseVita(&(stream)->platform) -#define saveStreamReadBytesPlatform(stream, buf, len) \ - saveStreamReadBytesVita(&(stream)->platform, buf, len) -#define saveStreamWriteBytesPlatform(stream, buf, len) \ - saveStreamWriteBytesVita(&(stream)->platform, buf, len) -#define saveStreamSeekPlatform(stream, pos) \ - saveStreamSeekVita(&(stream)->platform, pos) diff --git a/src/duskvita/save/savestreamvita.c b/src/duskvita/save/savestreamvita.c deleted file mode 100644 index f3db7aa6..00000000 --- a/src/duskvita/save/savestreamvita.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "save/save.h" -#include "save/savestreamvita.h" - -errorret_t saveStreamOpenReadVita( - savestreamvita_t *p, bool_t *found, const uint8_t slot -) { - char_t path[SAVE_VITA_PATH_MAX]; - snprintf(path, SAVE_VITA_PATH_MAX, SAVE_VITA_FILE_FORMAT, - SAVE_VITA_TITLE_ID, (uint32_t)slot - ); - - p->fd = sceIoOpen(path, SCE_O_RDONLY, 0); - *found = (p->fd >= 0); - errorOk(); -} - -errorret_t saveStreamOpenWriteVita(savestreamvita_t *p, const uint8_t slot) { - char_t dir[SAVE_VITA_PATH_MAX]; - snprintf(dir, SAVE_VITA_PATH_MAX, SAVE_VITA_DIR_FORMAT, - SAVE_VITA_TITLE_ID, (uint32_t)slot - ); - sceIoMkdir(dir, 0777); - - char_t path[SAVE_VITA_PATH_MAX]; - snprintf(path, SAVE_VITA_PATH_MAX, SAVE_VITA_FILE_FORMAT, - SAVE_VITA_TITLE_ID, (uint32_t)slot - ); - - p->fd = sceIoOpen(path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); - if(p->fd < 0) { - errorThrow( - "Failed to open Vita save file for writing: slot %u", (uint32_t)slot - ); - } - errorOk(); -} - -void saveStreamCloseVita(savestreamvita_t *p) { - if(p->fd >= 0) { - sceIoClose(p->fd); - p->fd = -1; - } -} - -errorret_t saveStreamReadBytesVita( - savestreamvita_t *p, void *buf, const size_t len -) { - int32_t read = sceIoRead(p->fd, buf, (SceSize)len); - if(read != (int32_t)len) { - errorThrow("Unexpected end of Vita save file"); - } - errorOk(); -} - -errorret_t saveStreamWriteBytesVita( - savestreamvita_t *p, const void *buf, const size_t len -) { - int32_t written = sceIoWrite(p->fd, buf, (SceSize)len); - if(written != (int32_t)len) { - errorThrow("Failed to write Vita save data"); - } - errorOk(); -} - -errorret_t saveStreamSeekVita(savestreamvita_t *p, const size_t pos) { - if(sceIoLseek(p->fd, (SceOff)pos, SCE_SEEK_SET) < 0) { - errorThrow("Failed to seek in Vita save file"); - } - errorOk(); -} diff --git a/src/duskvita/save/savestreamvita.h b/src/duskvita/save/savestreamvita.h deleted file mode 100644 index dcd9ec90..00000000 --- a/src/duskvita/save/savestreamvita.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include -#include -#include - -typedef struct { - SceUID fd; -} savestreamvita_t; - -/** - * Opens a Vita save data file for reading. - * - * @param p Stream to initialize. - * @param found Set to true if the file exists, false if it does not. - * @param slot Save slot index. - * @return An error if the open fails for a reason other than missing file. - */ -errorret_t saveStreamOpenReadVita( - savestreamvita_t *p, bool_t *found, const uint8_t slot -); - -/** - * Opens a Vita save data file for writing, creating or truncating it. - * Creates the save data directory if it does not already exist. - * - * @param p Stream to initialize. - * @param slot Save slot index. - * @return An error if the file cannot be opened for writing. - */ -errorret_t saveStreamOpenWriteVita(savestreamvita_t *p, const uint8_t slot); - -/** - * Closes the file descriptor held by the stream. - * - * @param p Stream to close. - */ -void saveStreamCloseVita(savestreamvita_t *p); - -/** - * Reads len bytes from the stream into buf. - * - * @param p Active stream. - * @param buf Destination buffer. - * @param len Number of bytes to read. - * @return An error if fewer than len bytes are available. - */ -errorret_t saveStreamReadBytesVita( - savestreamvita_t *p, void *buf, const size_t len -); - -/** - * Writes len bytes from buf into the stream. - * - * @param p Active stream. - * @param buf Source buffer. - * @param len Number of bytes to write. - * @return An error if the write fails. - */ -errorret_t saveStreamWriteBytesVita( - savestreamvita_t *p, const void *buf, const size_t len -); - -/** - * Seeks to an absolute byte position within the stream. - * - * @param p Active stream. - * @param pos Target byte offset from the start of the file. - * @return An error if the seek fails. - */ -errorret_t saveStreamSeekVita(savestreamvita_t *p, const size_t pos);