Compare commits

..

47 Commits

Author SHA1 Message Date
minjaesong
fbe887b039 0.4.1 release 2024-03-03 17:53:35 +09:00
minjaesong
91798436cb new fixture: table 2024-03-03 17:06:10 +09:00
minjaesong
34415f720d hiding the crafting guide again 2024-03-03 14:04:01 +09:00
minjaesong
33b739f34f fix typo in crafting recipe 2024-03-03 12:32:02 +09:00
minjaesong
f3825c0bfb itemdesc for wire rolling mill 2024-03-03 03:35:23 +09:00
minjaesong
84f1c48159 did i fix the crafting-unequip bug? 2024-03-03 03:20:42 +09:00
minjaesong
514a972bcf fix: savegame playtime was calculated wrongly 2024-03-03 03:15:35 +09:00
minjaesong
f19a27065e this should track the total playtime better? 2024-03-03 02:56:43 +09:00
minjaesong
324128e86a using gpu render for savegame list wipeout eff 2024-03-03 02:47:55 +09:00
minjaesong
39fca59ea7 larger tree takes double time to chop down 2024-03-03 02:11:18 +09:00
minjaesong
f07a6f6430 scaffoldings recipe change 2024-03-02 19:41:00 +09:00
minjaesong
6c5ee14402 platforms are lighter in weight 2024-03-02 18:24:58 +09:00
minjaesong
ec7ff3199d fix: techtree button not working if craftingUI is loaded independently 2024-03-02 17:16:02 +09:00
minjaesong
f400a5afe7 multicolour storage chests 2024-03-02 03:03:31 +09:00
minjaesong
ea1702ace4 wire rolling mill 2024-03-02 02:42:31 +09:00
minjaesong
01b5569169 bulb now requires walls to spawn 2024-03-02 01:11:02 +09:00
minjaesong
374cd5d4f7 changing recipe of gunpowder 2024-03-02 00:38:30 +09:00
minjaesong
c0cf9ab17d changing recipe of gunpowder 2024-03-02 00:34:01 +09:00
minjaesong
db0d3379cc trajectory to draw at the world edge 2024-03-02 00:09:57 +09:00
minjaesong
42e7da2a4a copper ingot sprite colour adjustment 2024-03-01 23:56:16 +09:00
minjaesong
30caac283a fix: torches can be placed anywhere 2024-03-01 22:15:39 +09:00
minjaesong
5da4cee22e tools now cost 5 bars 2024-03-01 19:16:48 +09:00
minjaesong
ddfa2f5bf0 fix: zooming would not properly center the cam if streamers mode is on (2) 2024-03-01 18:21:22 +09:00
minjaesong
7d38ba866c fix: zooming would not properly center the cam if streamers mode is on 2024-03-01 18:14:12 +09:00
minjaesong
a773786c9e changed iron ore distribution 2024-03-01 16:14:03 +09:00
minjaesong
43e16bf785 copper bulbs 2024-03-01 15:29:11 +09:00
minjaesong
7906de1711 fix: two clashing signal switches confusing the wire sim 2024-03-01 03:17:16 +09:00
minjaesong
6c3ec20b3d signal switches 2024-03-01 03:05:55 +09:00
minjaesong
902a086a4f better trajectory view 2024-02-29 14:22:16 +09:00
minjaesong
91bf11a3e0 better trajectory sim 2024-02-29 13:41:14 +09:00
minjaesong
410456e173 aim helper wip 2024-02-29 00:57:57 +09:00
minjaesong
9caf2a0d7e hopefully fixed a bug where crafting item sometimes enequips an item in the quickslot? 2024-02-23 04:48:54 +09:00
minjaesong
9525441dc0 a debug print 2024-02-21 21:47:35 +09:00
minjaesong
f7b0dfb5bb fix: getFreeTrack() would return a track it just returned when the timing coincides 2024-02-21 21:43:55 +09:00
minjaesong
549c03c2b4 fianlly found the culprit of repeated audio stopping but have no idea how to fix 2024-02-21 16:53:51 +09:00
minjaesong
91c5105a12 trying to fix glitchy audio after load 2024-02-21 14:06:49 +09:00
minjaesong
063483cfda inventory encumberment now takes player scale into account 2024-02-20 15:49:11 +09:00
minjaesong
a5953b8c87 more informative 'update available' ticker 2024-02-20 04:35:07 +09:00
minjaesong
c568276df6 fix deepstones had density of 24600 instead of 2400 2024-02-20 01:30:45 +09:00
minjaesong
19405b7f8d fix: acorn were 10 kilos each 2024-02-20 01:28:43 +09:00
minjaesong
2e89dcc73a more attempts 2024-02-19 21:11:34 +09:00
minjaesong
d3fe2e2bc6 trying to debug why fullscreen is borked on macOS 2024-02-19 21:04:37 +09:00
minjaesong
5c18e03bad apparently longer sleep time doesn't hurt 2024-02-19 16:31:03 +09:00
minjaesong
11a7a1f48d slightly improved audio processing performance by giving some time to the CPU 2024-02-19 16:07:34 +09:00
minjaesong
d24ec8296f fix: paste from clipboard would crash the game if the clipboard is empty 2024-02-19 14:52:31 +09:00
minjaesong
2c1727e495 fix: config change of chat overlay would not be reflected to GUI variables 2024-02-19 03:16:50 +09:00
minjaesong
b9e7a4ba84 gems item sprite change 2024-02-19 03:16:16 +09:00
106 changed files with 2005 additions and 855 deletions

View File

@@ -10,7 +10,6 @@
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Build Version Number" run_configuration_type="Application" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="Build Version Number" run_configuration_type="Application" />
<option name="BuildArtifacts" enabled="true"> <option name="BuildArtifacts" enabled="true">
<artifact name="ModuleComputers" /> <artifact name="ModuleComputers" />
<artifact name="MusicPlayer" />
<artifact name="TerrarumBuild" /> <artifact name="TerrarumBuild" />
</option> </option>
<option name="RunConfigurationTask" enabled="true" run_configuration_name="QuickDirtyLint" run_configuration_type="Application" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="QuickDirtyLint" run_configuration_type="Application" />

Binary file not shown.

View File

@@ -7,7 +7,7 @@
"17";"17";"17";"BLOCK_STONE_QUARRIED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL,OREBEARING,SHALLOWROCK" "17";"17";"17";"BLOCK_STONE_QUARRIED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURAL,OREBEARING,SHALLOWROCK"
"18";"18";"18";"BLOCK_STONE_TILE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.18";"STONE,NORANDTILE" "18";"18";"18";"BLOCK_STONE_TILE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.18";"STONE,NORANDTILE"
"19";"19";"19";"BLOCK_STONE_BRICKS";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"STONE,NORANDTILE" "19";"19";"19";"BLOCK_STONE_BRICKS";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"STONE,NORANDTILE"
"20";"20";"20";"BLOCK_STONE_DEEP";"0.1252";"0.1252";"0.1252";"0.1252";"80";"24600";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURA,OREBEARING,DEEPROCK" "20";"20";"20";"BLOCK_STONE_DEEP";"0.1252";"0.1252";"0.1252";"0.1252";"80";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ROCK,NATURA,OREBEARING,DEEPROCK"
"21";"21";"21";"BLOCK_STONE_MARBLE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.1";"ROCK,NATURAL,DEEPROCK" "21";"21";"21";"BLOCK_STONE_MARBLE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.1";"ROCK,NATURAL,DEEPROCK"
# dirts # dirts
@@ -67,7 +67,7 @@
"149";"149";"149";"BLOCK_GLASS_CLEAN";"0.0424";"0.0424";"0.0424";"0.0636";"5";"2203";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS,NORANDTILE" "149";"149";"149";"BLOCK_GLASS_CLEAN";"0.0424";"0.0424";"0.0424";"0.0636";"5";"2203";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS,NORANDTILE"
# platforms # platforms
"160";"160";"160";"BLOCK_PLATFORM_STONE";"0.0312";"0.0312";"0.0312";"0.0312";"5";"2400";"ROCK";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM" "160";"160";"160";"BLOCK_PLATFORM_STONE";"0.0312";"0.0312";"0.0312";"0.0312";"5";"2400";"ROCK";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM,"
"161";"161";"161";"BLOCK_PLATFORM_WOODEN";"0.0312";"0.0312";"0.0312";"0.0312";"5";"740";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM,WOODEN" "161";"161";"161";"BLOCK_PLATFORM_WOODEN";"0.0312";"0.0312";"0.0312";"0.0312";"5";"740";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM,WOODEN"
"162";"162";"162";"BLOCK_PLATFORM_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"5";"1200";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM,WOODEN" "162";"162";"162";"BLOCK_PLATFORM_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"5";"1200";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM,WOODEN"
"163";"163";"163";"BLOCK_PLATFORM_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"5";"670";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM,WOODEN" "163";"163";"163";"BLOCK_PLATFORM_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"5";"670";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM,WOODEN"
@@ -125,10 +125,10 @@
"258";"258";"258";"BLOCK_DAYLIGHT_CAPACITOR";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"0";"N/A";"3";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE" "258";"258";"258";"BLOCK_DAYLIGHT_CAPACITOR";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"0";"N/A";"3";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
# more platforms # more platforms
"272";"272";"272";"BLOCK_SCAFFOLDING_NORMAL";"0.0312";"0.0312";"0.0312";"0.0312";"1";"740";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,NORANDTILE,WOODEN" "272";"272";"272";"BLOCK_SCAFFOLDING_NORMAL";"0.0312";"0.0312";"0.0312";"0.0312";"1";"740";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,SCAFFOLDING,NORANDTILE,WOODEN"
"273";"273";"273";"BLOCK_SCAFFOLDING_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1400";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,NORANDTILE,WOODEN" "273";"273";"273";"BLOCK_SCAFFOLDING_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1400";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,SCAFFOLDING,NORANDTILE,WOODEN"
"274";"274";"274";"BLOCK_SCAFFOLDING_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"1";"670";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,NORANDTILE,WOODEN" "274";"274";"274";"BLOCK_SCAFFOLDING_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"1";"670";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,SCAFFOLDING,NORANDTILE,WOODEN"
"275";"275";"275";"BLOCK_SCAFFOLDING_ROSEWOOD";"0.0312";"0.0312";"0.0312";"0.0312";"1";"900";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,NORANDTILE,WOODEN" "275";"275";"275";"BLOCK_SCAFFOLDING_ROSEWOOD";"0.0312";"0.0312";"0.0312";"0.0312";"1";"900";"WOOD";"0";"0";"6";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"PLATFORM,SCAFFOLDING,NORANDTILE,WOODEN"
# for future use # for future use
"288";"288";"288";"BLOCK_PLASTIC_WHITE"; "0.0903";"0.0903";"0.0903";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.06";"THERMOPLASTIC,NORANDTILE" "288";"288";"288";"BLOCK_PLASTIC_WHITE"; "0.0903";"0.0903";"0.0903";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.06";"THERMOPLASTIC,NORANDTILE"
Can't render this file because it contains an unexpected character in line 18 and column 2.

View File

@@ -1,3 +1,6 @@
->Lang:MENU_OPTIONS_GAMEPLAY->h1 ->Lang:MENU_OPTIONS_GAMEPLAY->h1
gameplay_max_crafting->Lang:MENU_OPTIONS_MAX_CRAFTING->spinner,100,1000,100 gameplay_max_crafting->Lang:MENU_OPTIONS_MAX_CRAFTING->spinner,100,1000,100
showpickaxetooltip->Lang:MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING->toggle showpickaxetooltip->Lang:MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING->toggle
->Lang:MENU_OPTIONS_UNIT_OF_MEASUREMENT->h1
gameplay_unit_distance->Lang:MENU_OPTIONS_DISTANCE_UNIT->textsel,meter=MENU_OPTIONS_UNIT_METRIC,foot=MENU_OPTIONS_UNIT_FEET,block=MENU_OPTIONS_UNIT_BLOCKS
gameplay_unit_temperature->Lang:MENU_OPTIONS_TEMPERATURE_UNIT->textsel,celsius=MENU_OPTIONS_UNIT_CELSIUS_DNT,fahrenheit=MENU_OPTIONS_UNIT_FAHRENHEIT_DNT,kelvin=MENU_OPTIONS_UNIT_KELVIN_DNT
1 ->Lang:MENU_OPTIONS_GAMEPLAY->h1
2 gameplay_max_crafting->Lang:MENU_OPTIONS_MAX_CRAFTING->spinner,100,1000,100
3 showpickaxetooltip->Lang:MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING->toggle
4 ->Lang:MENU_OPTIONS_UNIT_OF_MEASUREMENT->h1
5 gameplay_unit_distance->Lang:MENU_OPTIONS_DISTANCE_UNIT->textsel,meter=MENU_OPTIONS_UNIT_METRIC,foot=MENU_OPTIONS_UNIT_FEET,block=MENU_OPTIONS_UNIT_BLOCKS
6 gameplay_unit_temperature->Lang:MENU_OPTIONS_TEMPERATURE_UNIT->textsel,celsius=MENU_OPTIONS_UNIT_CELSIUS_DNT,fahrenheit=MENU_OPTIONS_UNIT_FAHRENHEIT_DNT,kelvin=MENU_OPTIONS_UNIT_KELVIN_DNT

View File

@@ -32,25 +32,25 @@
"basegame:272": { /* scaffolding */ "basegame:272": { /* scaffolding */
"workbench": "", "workbench": "",
"ingredients": [ "ingredients": [
[1, 2, "item@basegame:18", 2, "basegame:161"] /* 2 sticks and 2 platform */ [2, 2, "item@basegame:18", 2, "basegame:48"] /* 2 sticks and 2 wood */
] ]
}, },
"basegame:273": { /* scaffolding */ "basegame:273": { /* scaffolding */
"workbench": "", "workbench": "",
"ingredients": [ "ingredients": [
[1, 2, "item@basegame:18", 2, "basegame:162"] /* 2 sticks and 2 platform */ [2, 2, "item@basegame:18", 2, "basegame:49"] /* 2 sticks and 2 wood */
] ]
}, },
"basegame:274": { /* scaffolding */ "basegame:274": { /* scaffolding */
"workbench": "", "workbench": "",
"ingredients": [ "ingredients": [
[1, 2, "item@basegame:18", 2, "basegame:163"] /* 2 sticks and 2 platform */ [2, 2, "item@basegame:18", 2, "basegame:50"] /* 2 sticks and 2 wood */
] ]
}, },
"basegame:275": { /* scaffolding */ "basegame:275": { /* scaffolding */
"workbench": "", "workbench": "",
"ingredients": [ "ingredients": [
[1, 2, "item@basegame:18", 2, "basegame:164"] /* 2 sticks and 2 platform */ [2, 2, "item@basegame:18", 2, "basegame:51"] /* 2 sticks and 2 wood */
] ]
} }
} }

View File

@@ -31,6 +31,12 @@
[1, 20, "$ROCK", 10, "item@basegame:25", 10, "item@basegame:113"] /* 1 smelter = 20 rocks, 10 clay balls, 10 iron ingots */ [1, 20, "$ROCK", 10, "item@basegame:25", 10, "item@basegame:113"] /* 1 smelter = 20 rocks, 10 clay balls, 10 iron ingots */
] ]
}, },
"item@basegame:36": { /* wire rolling mill */
"workbench": "basiccrafting",
"ingredients": [
[1, 1, "$WOOD", 2, "$ROCK", 5, "item@basegame:113"] /* 1 plank, 2 stone, 5 iron ingot */
]
},
"item@basegame:256": { /* oak door */ "item@basegame:256": { /* oak door */
"workbench": "basiccrafting", "workbench": "basiccrafting",
@@ -59,7 +65,25 @@
"item@basegame:6": { /* storage chest */ "item@basegame:6": { /* storage chest */
"workbench": "basiccrafting", "workbench": "basiccrafting",
"ingredients": [ "ingredients": [
[1, 20, "$WOOD"] /* 1 chest = 20 wood */ [1, 20, "basegame:48"] /* 1 chest = 20 wood */
]
},
"item@basegame:37": { /* storage chest */
"workbench": "basiccrafting",
"ingredients": [
[1, 20, "basegame:49"] /* 1 chest = 20 wood */
]
},
"item@basegame:38": { /* storage chest */
"workbench": "basiccrafting",
"ingredients": [
[1, 20, "basegame:50"] /* 1 chest = 20 wood */
]
},
"item@basegame:39": { /* storage chest */
"workbench": "basiccrafting",
"ingredients": [
[1, 20, "basegame:51"] /* 1 chest = 20 wood */
] ]
}, },
@@ -68,5 +92,30 @@
"ingredients": [ "ingredients": [
[1, 4, "item@basegame:144", 14, "$WOOD", 10, "item@basegame:113"] /* 1 turntable = 4 quartz, 14 wood, 10 iron */ [1, 4, "item@basegame:144", 14, "$WOOD", 10, "item@basegame:113"] /* 1 turntable = 4 quartz, 14 wood, 10 iron */
] ]
},
"item@basegame:40": { /* table */
"workbench": "basiccrafting",
"ingredients": [
[1, 10, "basegame:48"] /* 10 wood */
]
},
"item@basegame:41": { /* table */
"workbench": "basiccrafting",
"ingredients": [
[1, 10, "basegame:49"] /* 10 wood */
]
},
"item@basegame:42": { /* table */
"workbench": "basiccrafting",
"ingredients": [
[1, 10, "basegame:50"] /* 10 wood */
]
},
"item@basegame:43": { /* table */
"workbench": "basiccrafting",
"ingredients": [
[1, 10, "basegame:51"] /* 10 wood */
]
} }
} }

View File

@@ -1,10 +1,14 @@
{ {
"item@basegame:31": { /* gunpowder */ "item@basegame:31": { /* gunpowder */
"workbench": "basiccrafting", "workbench": "basiccrafting",
"ingredients": [[3, 1, "item@basegame:147", 1, "item@basegame:29", 1, "item@basegame:129"]] /* 1 nitre, 1 charcoal, 1 iron ore */ "ingredients": [[8, 3, "item@basegame:147", 1, "item@basegame:29"]] /* 3 nitre, 1 charcoal */
}, },
"item@basegame:32": { /* cherry bomb */ "item@basegame:32": { /* cherry bomb */
"workbench": "", "workbench": "",
"ingredients": [[1, 1, "item@basegame:31", 1, "item@basegame:25"]] /* 1 gunpowder, 1 clay ball */ "ingredients": [[1, 1, "item@basegame:31", 1, "item@basegame:25"]] /* 1 gunpowder, 1 clay ball */
},
"item@basegame:34": { /* signal switch */
"workbench": "",
"ingredients": [[2, 1, "item@basegame:112", 1, "$ROCK", 1, "$WOOD"]] /* 1 copper ingot, 1 rock, 1 planks */
} }
} }

View File

@@ -1,61 +1,65 @@
{ {
"item@basegame:14": { /* wooden pick */ "item@basegame:14": { /* wooden pick */
"workbench": "basiccrafting", "workbench": "basiccrafting",
"ingredients": [[1, 6, "$WOOD", 2, "item@basegame:18"]] /* 6 woods, 2 sticks */ "ingredients": [[1, 5, "$WOOD", 2, "item@basegame:18"]] /* 5 woods, 2 sticks */
}, },
/*"item@basegame:22": { /*"item@basegame:22": {
"workbench": "basiccrafting", "workbench": "basiccrafting",
"ingredients": [[1, 6, "$WOOD", 2, "item@basegame:18"]] "ingredients": [[1, 5, "$WOOD", 2, "item@basegame:18"]]
},*/ },*/
"item@basegame:15": { /* wooden mallet */ "item@basegame:15": { /* wooden mallet */
"workbench": "basiccrafting", "workbench": "basiccrafting",
"ingredients": [[1, 6, "$WOOD", 2, "item@basegame:18"]] "ingredients": [[1, 5, "$WOOD", 2, "item@basegame:18"]]
}, },
"item@basegame:23": { /* stone pick */ "item@basegame:23": { /* stone pick */
"workbench": "basiccrafting", "workbench": "basiccrafting",
"ingredients": [[1, 6, "$ROCK", 2, "item@basegame:18"]] "ingredients": [[1, 5, "$ROCK", 2, "item@basegame:18"]]
}, },
"item@basegame:24": { /* stone axe */ "item@basegame:24": { /* stone axe */
"workbench": "basiccrafting", "workbench": "basiccrafting",
"ingredients": [[1, 6, "$ROCK", 2, "item@basegame:18"]] "ingredients": [[1, 5, "$ROCK", 2, "item@basegame:18"]]
}, },
"item@basegame:1": { /* copper pick */ "item@basegame:1": { /* copper pick */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:112", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:112", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:2": { /* iron pick */ "item@basegame:2": { /* iron pick */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:113", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:113", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:3": { /* steel pick */ "item@basegame:3": { /* steel pick */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:26", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:26", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:12": { /* copper sledgehammer */ "item@basegame:12": { /* copper sledgehammer */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:112", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:112", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:4": { /* iron sledgehammer */ "item@basegame:4": { /* iron sledgehammer */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:113", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:113", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:13": { /* steel sledgehammer */ "item@basegame:13": { /* steel sledgehammer */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:26", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:26", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:19": { /* copper sledgehammer */ "item@basegame:19": { /* copper sledgehammer */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:112", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:112", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:20": { /* iron sledgehammer */ "item@basegame:20": { /* iron sledgehammer */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:113", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:113", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
}, },
"item@basegame:21": { /* steel sledgehammer */ "item@basegame:21": { /* steel sledgehammer */
"workbench": "basiccrafting,metalworking", "workbench": "basiccrafting,metalworking",
"ingredients": [[1, 6, "item@basegame:26", 2, "item@basegame:18"]] /* 6 bars, 2 sticks */ "ingredients": [[1, 5, "item@basegame:26", 2, "item@basegame:18"]] /* 5 bars, 2 sticks */
},
"item@basegame:9": { /* wire cutter */
"workbench": "basiccrafting,metalworking",
"ingredients": [[1, 1, "item@basegame:112", 1, "item@basegame:113"]] /* 1 copper ingot, 1 iron ingot */
} }
} }

View File

@@ -0,0 +1,44 @@
{
"wire@basegame:8192": { /* signal wire red */
"workbench": "",
"ingredients": [
[1, 1, "$SIGNALWIRE"] /* 1 other signal wire */
]
},
"wire@basegame:8193": { /* signal wire green */
"workbench": "",
"ingredients": [
[1, 1, "$SIGNALWIRE"] /* 1 other signal wire */
] },
"wire@basegame:8194": { /* signal wire blue */
"workbench": "",
"ingredients": [
[1, 1, "$SIGNALWIRE"] /* 1 other signal wire */
]
},
"wire@basegame:8192": { /* signal wire red */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
]
},
"wire@basegame:8193": { /* signal wire green */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
] },
"wire@basegame:8194": { /* signal wire blue */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
]
},
"item@basegame:35": { /* copper bulb */
"workbench": "basiccrafting",
"ingredients": [
[2, 1, "item@basegame:112", 1, "item@basegame:113"] /* 1 copper, 1 iron */
]
}
}

View File

@@ -1,4 +1,6 @@
{ {
"gameplay_max_crafting": 100, "gameplay_max_crafting": 100,
"showpickaxetooltip": true "showpickaxetooltip": true,
"gameplay_unit_distance": "meter",
"gameplay_unit_temperature": "celsius"
} }

View File

@@ -6,7 +6,7 @@ id;classname;tags
5;net.torvald.terrarum.modulebasegame.gameitems.ItemTikiTorch;FIXTURE,LIGHT 5;net.torvald.terrarum.modulebasegame.gameitems.ItemTikiTorch;FIXTURE,LIGHT
6;net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChest;FIXTURE,STORAGE 6;net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChest;FIXTURE,STORAGE
7;net.torvald.terrarum.modulebasegame.gameitems.WireGraphDebugger;TOOL,WIRE 7;net.torvald.terrarum.modulebasegame.gameitems.WireGraphDebugger;TOOL,WIRE
8;net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalEmitter;FIXTURE 8;net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalEmitter;FIXTURE,SIGNAL
9;net.torvald.terrarum.modulebasegame.gameitems.WireCutterAll;TOOL,WIRE 9;net.torvald.terrarum.modulebasegame.gameitems.WireCutterAll;TOOL,WIRE
10;net.torvald.terrarum.modulebasegame.gameitems.ItemTypewriter;FIXTURE,PRINTING 10;net.torvald.terrarum.modulebasegame.gameitems.ItemTypewriter;FIXTURE,PRINTING
11;net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar;FIXTURE 11;net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar;FIXTURE
@@ -20,7 +20,7 @@ id;classname;tags
19;net.torvald.terrarum.modulebasegame.gameitems.AxeCopper;TOOL,AXE 19;net.torvald.terrarum.modulebasegame.gameitems.AxeCopper;TOOL,AXE
20;net.torvald.terrarum.modulebasegame.gameitems.AxeIron;TOOL,AXE 20;net.torvald.terrarum.modulebasegame.gameitems.AxeIron;TOOL,AXE
21;net.torvald.terrarum.modulebasegame.gameitems.AxeSteel;TOOL,AXE 21;net.torvald.terrarum.modulebasegame.gameitems.AxeSteel;TOOL,AXE
#22;net.torvald.terrarum.modulebasegame.gameitems.AxeWood;TOOL,AXE 22;net.torvald.terrarum.modulebasegame.gameitems.AxeWood;TOOL,AXE
23;net.torvald.terrarum.modulebasegame.gameitems.PickaxeStone;TOOL,PICK 23;net.torvald.terrarum.modulebasegame.gameitems.PickaxeStone;TOOL,PICK
24;net.torvald.terrarum.modulebasegame.gameitems.AxeStone;TOOL,AXE 24;net.torvald.terrarum.modulebasegame.gameitems.AxeStone;TOOL,AXE
25;net.torvald.terrarum.modulebasegame.gameitems.ItemClayBall; 25;net.torvald.terrarum.modulebasegame.gameitems.ItemClayBall;
@@ -32,6 +32,16 @@ id;classname;tags
31;net.torvald.terrarum.modulebasegame.gameitems.ItemGunpowder;POWDER,EXPLOSIVE 31;net.torvald.terrarum.modulebasegame.gameitems.ItemGunpowder;POWDER,EXPLOSIVE
32;net.torvald.terrarum.modulebasegame.gameitems.ItemCherryBomb;EXPLOSIVE,THROWABLE 32;net.torvald.terrarum.modulebasegame.gameitems.ItemCherryBomb;EXPLOSIVE,THROWABLE
33;net.torvald.terrarum.modulebasegame.gameitems.ItemTorch;FIXTURE,LIGHT 33;net.torvald.terrarum.modulebasegame.gameitems.ItemTorch;FIXTURE,LIGHT
34;net.torvald.terrarum.modulebasegame.gameitems.ItemSignalSwitchManual;FIXTURE,SIGNAL
35;net.torvald.terrarum.modulebasegame.gameitems.ItemSignalBulb;FIXTURE,SIGNAL
36;net.torvald.terrarum.modulebasegame.gameitems.ItemWireRollingMill;FIXTURE,CRAFTING
37;net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChestEbony;FIXTURE,STORAGE
38;net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChestBirch;FIXTURE,STORAGE
39;net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChestRosewood;FIXTURE,STORAGE
40;net.torvald.terrarum.modulebasegame.gameitems.ItemTable;FIXTURE,SURFACE
41;net.torvald.terrarum.modulebasegame.gameitems.ItemTableEbony;FIXTURE,SURFACE
42;net.torvald.terrarum.modulebasegame.gameitems.ItemTableBirch;FIXTURE,SURFACE
43;net.torvald.terrarum.modulebasegame.gameitems.ItemTableRosewood;FIXTURE,SURFACE
# ingots # ingots
26;net.torvald.terrarum.modulebasegame.gameitems.IngotSteel;INGOT 26;net.torvald.terrarum.modulebasegame.gameitems.IngotSteel;INGOT
1 id classname tags
6 5 net.torvald.terrarum.modulebasegame.gameitems.ItemTikiTorch FIXTURE,LIGHT
7 6 net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChest FIXTURE,STORAGE
8 7 net.torvald.terrarum.modulebasegame.gameitems.WireGraphDebugger TOOL,WIRE
9 8 net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalEmitter FIXTURE FIXTURE,SIGNAL
10 9 net.torvald.terrarum.modulebasegame.gameitems.WireCutterAll TOOL,WIRE
11 10 net.torvald.terrarum.modulebasegame.gameitems.ItemTypewriter FIXTURE,PRINTING
12 11 net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar FIXTURE
20 19 net.torvald.terrarum.modulebasegame.gameitems.AxeCopper TOOL,AXE
21 20 net.torvald.terrarum.modulebasegame.gameitems.AxeIron TOOL,AXE
22 21 net.torvald.terrarum.modulebasegame.gameitems.AxeSteel TOOL,AXE
23 #22 22 net.torvald.terrarum.modulebasegame.gameitems.AxeWood TOOL,AXE
24 23 net.torvald.terrarum.modulebasegame.gameitems.PickaxeStone TOOL,PICK
25 24 net.torvald.terrarum.modulebasegame.gameitems.AxeStone TOOL,AXE
26 25 net.torvald.terrarum.modulebasegame.gameitems.ItemClayBall
32 32 net.torvald.terrarum.modulebasegame.gameitems.ItemCherryBomb EXPLOSIVE,THROWABLE
33 33 net.torvald.terrarum.modulebasegame.gameitems.ItemTorch FIXTURE,LIGHT
34 # ingots 34 net.torvald.terrarum.modulebasegame.gameitems.ItemSignalSwitchManual FIXTURE,SIGNAL
35 35 net.torvald.terrarum.modulebasegame.gameitems.ItemSignalBulb FIXTURE,SIGNAL
36 36 net.torvald.terrarum.modulebasegame.gameitems.ItemWireRollingMill FIXTURE,CRAFTING
37 37 net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChestEbony FIXTURE,STORAGE
38 38 net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChestBirch FIXTURE,STORAGE
39 39 net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChestRosewood FIXTURE,STORAGE
40 40 net.torvald.terrarum.modulebasegame.gameitems.ItemTable FIXTURE,SURFACE
41 41 net.torvald.terrarum.modulebasegame.gameitems.ItemTableEbony FIXTURE,SURFACE
42 42 net.torvald.terrarum.modulebasegame.gameitems.ItemTableBirch FIXTURE,SURFACE
43 43 net.torvald.terrarum.modulebasegame.gameitems.ItemTableRosewood FIXTURE,SURFACE
44 # ingots
45 26 net.torvald.terrarum.modulebasegame.gameitems.IngotSteel INGOT
46 112 net.torvald.terrarum.modulebasegame.gameitems.IngotCopper INGOT
47 113 net.torvald.terrarum.modulebasegame.gameitems.IngotIron INGOT

Binary file not shown.

View File

@@ -0,0 +1,15 @@
{
"MENU_MONITOR_CALI_TITLE": "Check Monitor",
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "Show Ore Tooltip When Mining",
"MENU_OPTIONS_MAX_CRAFTING": "Max Number of Items for Crafting",
"MENU_OPTIONS_UNIT_BLOCKS": "Blocks",
"MENU_OPTIONS_UNIT_FEET": "Imperial",
"MENU_OPTIONS_UNIT_METRIC": "Metric",
"MENU_OPTIONS_UNIT_OF_MEASUREMENT": "Unit of Measurement",
"MENU_OPTIONS_DISTANCE_UNIT": "Distance",
"MENU_OPTIONS_TEMPERATURE_UNIT": "Temperature",
"MENU_OPTIONS_UNIT_CELSIUS_DNT": "°C",
"MENU_OPTIONS_UNIT_FAHRENHEIT_DNT": "°F",
"MENU_OPTIONS_UNIT_KELVIN_DNT": "K"
}

View File

@@ -13,9 +13,6 @@
"MENU_LABEL_RENAME": "Rename", "MENU_LABEL_RENAME": "Rename",
"MENU_LABEL_USE_CODE": "Use Code", "MENU_LABEL_USE_CODE": "Use Code",
"MENU_MODE_BUILDINGMAKER": "POI Editor", "MENU_MODE_BUILDINGMAKER": "POI Editor",
"MENU_MONITOR_CALI_TITLE": "Check Monitor",
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "Show Ore Tooltip When Mining",
"MENU_OPTIONS_MAX_CRAFTING": "Max Number of Items for Crafting",
"MENU_UPDATE_UPDATE_AVAILABLE": "Update Available!", "MENU_UPDATE_UPDATE_AVAILABLE": "Update Available!",
"GAME_ACTION_GRAPPLE": "Grapple", "GAME_ACTION_GRAPPLE": "Grapple",
"GAME_ACTION_QUICKSEL": "Quick Select", "GAME_ACTION_QUICKSEL": "Quick Select",

View File

@@ -16,6 +16,9 @@
"TOOLTIP_item@basegame:4": "Breaks down walls", "TOOLTIP_item@basegame:4": "Breaks down walls",
"TOOLTIP_item@basegame:5": "Provides light but fancier", "TOOLTIP_item@basegame:5": "Provides light but fancier",
"TOOLTIP_item@basegame:6": "“I am sworn to keep your burdens.”", /* skyrim/lydia reference */ "TOOLTIP_item@basegame:6": "“I am sworn to keep your burdens.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:37": "“I am sworn to keep your burdens.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:38": "“I am sworn to keep your burdens.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:39": "“I am sworn to keep your burdens.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:8": "Emits a signal", "TOOLTIP_item@basegame:8": "Emits a signal",
"TOOLTIP_item@basegame:9": "An electricians best friend", "TOOLTIP_item@basegame:9": "An electricians best friend",
"TOOLTIP_item@basegame:10": "“Who needs a Book and Quill when youve got this?”", /* a jab on the Minecraft item Book and Quill */ "TOOLTIP_item@basegame:10": "“Who needs a Book and Quill when youve got this?”", /* a jab on the Minecraft item Book and Quill */
@@ -31,6 +34,7 @@
"TOOLTIP_item@basegame:20": "Cuts trees", "TOOLTIP_item@basegame:20": "Cuts trees",
"TOOLTIP_item@basegame:21": "Cuts trees", "TOOLTIP_item@basegame:21": "Cuts trees",
"TOOLTIP_item@basegame:22": "Cuts trees, just barely", "TOOLTIP_item@basegame:22": "Cuts trees, just barely",
/*"TOOLTIP_item@basegame:22": "Perhaps its more useful for casting than actually using",*/
"TOOLTIP_item@basegame:23": "Breaks rocks", "TOOLTIP_item@basegame:23": "Breaks rocks",
"TOOLTIP_item@basegame:24": "Cuts trees", "TOOLTIP_item@basegame:24": "Cuts trees",
"TOOLTIP_item@basegame:25": "Finer grains of dirts that gets stronger when burned", "TOOLTIP_item@basegame:25": "Finer grains of dirts that gets stronger when burned",
@@ -38,6 +42,7 @@
"TOOLTIP_item@basegame:27": "Every blacksmith gotta start from somewhere", "TOOLTIP_item@basegame:27": "Every blacksmith gotta start from somewhere",
"TOOLTIP_item@basegame:28": "A music vending machine (free to play)", "TOOLTIP_item@basegame:28": "A music vending machine (free to play)",
"TOOLTIP_item@basegame:29": "A coal lookalike that burns just as well and is renewable", "TOOLTIP_item@basegame:29": "A coal lookalike that burns just as well and is renewable",
"TOOLTIP_item@basegame:36": "Creates wires from metal ingots",
"TOOLTIP_item@basegame:114": "A precious fuel for the steel production", "TOOLTIP_item@basegame:114": "A precious fuel for the steel production",

View File

@@ -3,6 +3,7 @@
"ITEM_CHARCOAL": "Charcoal", "ITEM_CHARCOAL": "Charcoal",
"ITEM_CHERRY_BOMB": "Bomb", "ITEM_CHERRY_BOMB": "Bomb",
"ITEM_COAL_COKE": "Coal Coke", "ITEM_COAL_COKE": "Coal Coke",
"ITEM_COPPER_BULB": "Copper Bulb",
"ITEM_DOOR_OAK": "Oak Door", "ITEM_DOOR_OAK": "Oak Door",
"ITEM_DOOR_EBONY": "Ebony Door", "ITEM_DOOR_EBONY": "Ebony Door",
"ITEM_DOOR_BIRCH": "Birch Door", "ITEM_DOOR_BIRCH": "Birch Door",
@@ -37,6 +38,7 @@
"ITEM_INGOT_ZINC": "Zinc Ingot", "ITEM_INGOT_ZINC": "Zinc Ingot",
"ITEM_JUKEBOX": "Jukebox", "ITEM_JUKEBOX": "Jukebox",
"ITEM_LOGIC_SIGNAL_EMITTER": "Logic Signal Emitter", "ITEM_LOGIC_SIGNAL_EMITTER": "Logic Signal Emitter",
"ITEM_LOGIC_SIGNAL_SWITCH": "Logic Signal Switch",
"ITEM_LOGS_BIRCH": "Birch Logs", "ITEM_LOGS_BIRCH": "Birch Logs",
"ITEM_LOGS_EBONY": "Ebony Logs", "ITEM_LOGS_EBONY": "Ebony Logs",
"ITEM_LOGS_OAK": "Oak Logs", "ITEM_LOGS_OAK": "Oak Logs",
@@ -65,11 +67,16 @@
"ITEM_SLEDGEHAMMER_STEEL": "Steel Sledgehammer", "ITEM_SLEDGEHAMMER_STEEL": "Steel Sledgehammer",
"ITEM_SMELTER_SMALL": "Small Smelter", "ITEM_SMELTER_SMALL": "Small Smelter",
"ITEM_STORAGE_CHEST": "Storage Chest", "ITEM_STORAGE_CHEST": "Storage Chest",
"ITEM_TABLE_OAK": "Oak Table",
"ITEM_TABLE_EBONY": "Ebony Table",
"ITEM_TABLE_BIRCH": "Birch Table",
"ITEM_TABLE_ROSEWOOD": "Rosewood Table",
"ITEM_TIKI_TORCH": "Tiki Torch", "ITEM_TIKI_TORCH": "Tiki Torch",
"ITEM_TURNTABLE": "Turntable", "ITEM_TURNTABLE": "Turntable",
"ITEM_TYPEWRITER": "Typewriter", "ITEM_TYPEWRITER": "Typewriter",
"ITEM_WIRE": "Wire", "ITEM_WIRE": "Wire",
"ITEM_WIRE_CUTTER": "Wire Cutter", "ITEM_WIRE_CUTTER": "Wire Cutter",
"ITEM_WIRE_ROLLING_MILL": "Wire Rolling Mill",
"ITEM_WOOD_STICK": "Stick", "ITEM_WOOD_STICK": "Stick",
"ITEM_WOODEN_MALLET": "Wooden Mallet", "ITEM_WOODEN_MALLET": "Wooden Mallet",
"ITEM_WORKBENCH": "Workbench", "ITEM_WORKBENCH": "Workbench",

View File

@@ -0,0 +1,11 @@
{
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "채굴 시 광석 툴팁 보이기",
"MENU_OPTIONS_MAX_CRAFTING": "한번에 제작할 최대 아이템 수",
"MENU_OPTIONS_UNIT_BLOCKS": "블록",
"MENU_OPTIONS_UNIT_FEET": "피트",
"MENU_OPTIONS_UNIT_METRIC": "미터",
"MENU_OPTIONS_UNIT_OF_MEASUREMENT": "측정 단위",
"MENU_OPTIONS_DISTANCE_UNIT": "거리",
"MENU_OPTIONS_TEMPERATURE_UNIT": "온도"
}

View File

@@ -12,9 +12,6 @@
"MENU_LABEL_PREV_SAVES": "이전 세이브", "MENU_LABEL_PREV_SAVES": "이전 세이브",
"MENU_LABEL_RENAME": "이름 바꾸기", "MENU_LABEL_RENAME": "이름 바꾸기",
"MENU_LABEL_USE_CODE": "코드 사용", "MENU_LABEL_USE_CODE": "코드 사용",
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "채굴 시 광석 툴팁 보이기",
"MENU_OPTIONS_MAX_CRAFTING": "한번에 제작할 최대 아이템 수",
"MENU_UPDATE_UPDATE_AVAILABLE": "새 업데이트가 있습니다!", "MENU_UPDATE_UPDATE_AVAILABLE": "새 업데이트가 있습니다!",
"GAME_ACTION_GRAPPLE": "매달리기", "GAME_ACTION_GRAPPLE": "매달리기",
"GAME_ACTION_QUICKSEL": "빠른 선택", "GAME_ACTION_QUICKSEL": "빠른 선택",

View File

@@ -16,6 +16,9 @@
"TOOLTIP_item@basegame:4": "벽을 부숩니다", "TOOLTIP_item@basegame:4": "벽을 부숩니다",
"TOOLTIP_item@basegame:5": "빛을 더 이쁘게 냅니다", "TOOLTIP_item@basegame:5": "빛을 더 이쁘게 냅니다",
"TOOLTIP_item@basegame:6": "“짐을 맡아두기로 한 몸이니까요.”", /* skyrim/lydia reference */ "TOOLTIP_item@basegame:6": "“짐을 맡아두기로 한 몸이니까요.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:37": "“짐을 맡아두기로 한 몸이니까요.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:38": "“짐을 맡아두기로 한 몸이니까요.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:39": "“짐을 맡아두기로 한 몸이니까요.”", /* skyrim/lydia reference */
"TOOLTIP_item@basegame:8": "신호를 만들어냅니다", "TOOLTIP_item@basegame:8": "신호를 만들어냅니다",
"TOOLTIP_item@basegame:9": "전기공의 친한 친구", "TOOLTIP_item@basegame:9": "전기공의 친한 친구",
"TOOLTIP_item@basegame:10": "“이게 있는데 책과 깃펜이 왜 필요하죠?”", /* a jab on the Minecraft item Book and Quill */ "TOOLTIP_item@basegame:10": "“이게 있는데 책과 깃펜이 왜 필요하죠?”", /* a jab on the Minecraft item Book and Quill */
@@ -38,6 +41,7 @@
"TOOLTIP_item@basegame:27": "모든 대장장이는 초보 시절이 있는 법이죠", "TOOLTIP_item@basegame:27": "모든 대장장이는 초보 시절이 있는 법이죠",
"TOOLTIP_item@basegame:28": "음악 자판기입이다 (무료 플레이)", "TOOLTIP_item@basegame:28": "음악 자판기입이다 (무료 플레이)",
"TOOLTIP_item@basegame:29": "석탄과 비슷하고 똑같이 잘 타지만 재생 가능합니다", "TOOLTIP_item@basegame:29": "석탄과 비슷하고 똑같이 잘 타지만 재생 가능합니다",
"TOOLTIP_item@basegame:36": "금속 주괴를 사용해 철사를 뽑아냅니다",
"TOOLTIP_item@basegame:114": "강철 생산의 소중한 연료입니다", "TOOLTIP_item@basegame:114": "강철 생산의 소중한 연료입니다",

View File

@@ -3,6 +3,7 @@
"ITEM_CHARCOAL": "목탄", "ITEM_CHARCOAL": "목탄",
"ITEM_CHERRY_BOMB": "폭탄", "ITEM_CHERRY_BOMB": "폭탄",
"ITEM_COAL_COKE": "코크스", "ITEM_COAL_COKE": "코크스",
"ITEM_COPPER_BULB": "구리 전구",
"ITEM_DOOR_OAK": "나무 문", "ITEM_DOOR_OAK": "나무 문",
"ITEM_DOOR_EBONY": "흑단 문", "ITEM_DOOR_EBONY": "흑단 문",
"ITEM_DOOR_BIRCH": "백단 문", "ITEM_DOOR_BIRCH": "백단 문",
@@ -37,6 +38,7 @@
"ITEM_INGOT_ZINC": "아연괴", "ITEM_INGOT_ZINC": "아연괴",
"ITEM_JUKEBOX": "주크박스", "ITEM_JUKEBOX": "주크박스",
"ITEM_LOGIC_SIGNAL_EMITTER": "신호발생기", "ITEM_LOGIC_SIGNAL_EMITTER": "신호발생기",
"ITEM_LOGIC_SIGNAL_SWITCH": "신호 스위치",
"ITEM_LOGS_BIRCH": "백단 통나무", "ITEM_LOGS_BIRCH": "백단 통나무",
"ITEM_LOGS_EBONY": "흑단 통나무", "ITEM_LOGS_EBONY": "흑단 통나무",
"ITEM_LOGS_OAK": "통나무", "ITEM_LOGS_OAK": "통나무",
@@ -65,11 +67,16 @@
"ITEM_SLEDGEHAMMER_STEEL": "강철 해머", "ITEM_SLEDGEHAMMER_STEEL": "강철 해머",
"ITEM_SMELTER_SMALL": "소형 고로", "ITEM_SMELTER_SMALL": "소형 고로",
"ITEM_STORAGE_CHEST": "보관상자", "ITEM_STORAGE_CHEST": "보관상자",
"ITEM_TABLE_OAK": "나무 탁자",
"ITEM_TABLE_EBONY": "흑단 탁자",
"ITEM_TABLE_BIRCH": "백단 탁자",
"ITEM_TABLE_ROSEWOOD": "자단 탁자",
"ITEM_TIKI_TORCH": "티키 토치", "ITEM_TIKI_TORCH": "티키 토치",
"ITEM_TURNTABLE": "전축", "ITEM_TURNTABLE": "전축",
"ITEM_TYPEWRITER": "타자기", "ITEM_TYPEWRITER": "타자기",
"ITEM_WIRE": "전선", "ITEM_WIRE": "전선",
"ITEM_WIRE_CUTTER": "전선 절단기", "ITEM_WIRE_CUTTER": "전선 절단기",
"ITEM_WIRE_ROLLING_MILL": "철사 압연기",
"ITEM_WOOD_STICK": "막대기", "ITEM_WOOD_STICK": "막대기",
"ITEM_WOODEN_MALLET": "나무 망치", "ITEM_WOODEN_MALLET": "나무 망치",
"ITEM_WORKBENCH": "작업대", "ITEM_WORKBENCH": "작업대",

View File

@@ -44,10 +44,10 @@ package=net.torvald.terrarum.modulebasegame
entrypoint=net.torvald.terrarum.modulebasegame.EntryPoint entrypoint=net.torvald.terrarum.modulebasegame.EntryPoint
# Release date in YYYY-MM-DD # Release date in YYYY-MM-DD
releasedate=2024-02-19 releasedate=2024-03-03
# The version, must follow Semver 2.0.0 scheme (https://semver.org/) # The version, must follow Semver 2.0.0 scheme (https://semver.org/)
version=0.4.0 version=0.4.1
# External JAR that the module is compiled. If your module requires yet another library, the JAR must be compiled as a "Fatjar"; # External JAR that the module is compiled. If your module requires yet another library, the JAR must be compiled as a "Fatjar";
# Due to security reasons, loading an arbitrary JAR is not allowed. # Due to security reasons, loading an arbitrary JAR is not allowed.

View File

@@ -1,6 +1,6 @@
"id";"freq";"power";"scale";"ratio";"tiling";"comment";"blocktagnongrata" "id";"freq";"power";"scale";"ratio";"tiling";"comment";"blocktagnongrata"
"1";"0.026";"0.010";"0.517";"1.0";"a16x16";"copper (malachite)";"" "1";"0.026";"0.010";"0.517";"1.0";"a16x16";"copper (malachite)";""
"2";"0.045";"0.011";"0.517";"1.0";"a16x16";"iron (haematite)";"" "2";"0.031";"0.011";"0.521";"1.0";"a16x16";"iron (haematite)";""
"3";"0.017";"0.070";"0.511";"3.8";"a16x4";"coal";"" "3";"0.017";"0.070";"0.511";"3.8";"a16x4";"coal";""
"4";"0.019";"0.011";"0.511";"1.0";"a16x16";"zinc (sphalerite)";"" "4";"0.019";"0.011";"0.511";"1.0";"a16x16";"zinc (sphalerite)";""
"5";"0.017";"0.017";"0.511";"1.0";"a16x16";"tin (cassiterite)";"" "5";"0.017";"0.017";"0.511";"1.0";"a16x16";"tin (cassiterite)";""
1 id freq power scale ratio tiling comment blocktagnongrata
2 1 0.026 0.010 0.517 1.0 a16x16 copper (malachite)
3 2 0.045 0.031 0.011 0.517 0.521 1.0 a16x16 iron (haematite)
4 3 0.017 0.070 0.511 3.8 a16x4 coal
5 4 0.019 0.011 0.511 1.0 a16x16 zinc (sphalerite)
6 5 0.017 0.017 0.511 1.0 a16x16 tin (cassiterite)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,11 +1,11 @@
id;drop;name;renderclass;accept;inputcount;inputtype;outputtype;javaclass;inventoryimg;branching id;drop;name;renderclass;accept;inputcount;inputtype;outputtype;javaclass;inventoryimg;branching;tags
8192;8192;WIRE_RED;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,4;1 8192;8192;WIRE_RED;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,4;1;"SIGNALWIRE"
8193;8193;WIRE_GREEN;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,1,4;1 8193;8193;WIRE_GREEN;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,1,4;1;"SIGNALWIRE"
8194;8194;WIRE_BLUE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,2,4;1 8194;8194;WIRE_BLUE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,2,4;1;"SIGNALWIRE"
#8195;8195;WIRE_BUNDLE;signal;digital_3bits;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,0;1 #8195;8195;WIRE_BUNDLE;signal;digital_3bits;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,0;1;"SIGNALWIRE"
8196;8196;WIRE_POWER_LOW;power;power_low;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,3,4;1 8196;8196;WIRE_POWER_LOW;power;power_low;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,3,4;1;"POWERWIRE_LOW"
8197;8197;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,4,4;1 8197;8197;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,4,4;1;"POWERWIRE_HIGH"
8198;8198;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,5,4;1 8198;8198;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,5,4;1;"ETHERNETWIRE"
# accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka not wires) # accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka not wires)
1 id drop name renderclass accept inputcount inputtype outputtype javaclass inventoryimg branching tags
2 8192 8192 WIRE_RED signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,0,4 1 SIGNALWIRE
3 8193 8193 WIRE_GREEN signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,1,4 1 SIGNALWIRE
4 8194 8194 WIRE_BLUE signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,2,4 1 SIGNALWIRE
5 #8195 8195 WIRE_BUNDLE signal digital_3bits 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,0,0 1 SIGNALWIRE
6 8196 8196 WIRE_POWER_LOW power power_low 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,3,4 1 POWERWIRE_LOW
7 8197 8197 WIRE_POWER_HIGH power power_high 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,4,4 1 POWERWIRE_HIGH
8 8198 8198 WIRE_ETHERNET network 10base2 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,5,4 1 ETHERNETWIRE
9 # accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka not wires)
10 # inputcount: how many sides are input (outputcount is deduced from the inputcount). N/A for wires
11 # inputtype: which wiretype it accepts. N/A for wires

View File

@@ -3,8 +3,8 @@ description=Simple music player widget
author=CuriousTo\uA75Bvald author=CuriousTo\uA75Bvald
package=net.torvald.terrarum.musicplayer package=net.torvald.terrarum.musicplayer
entrypoint=net.torvald.terrarum.musicplayer.EntryPoint entrypoint=net.torvald.terrarum.musicplayer.EntryPoint
releasedate=2024-02-19 releasedate=2024-03-03
version=1.0.0 version=1.0.1
jar=MusicPlayer.jar jar=MusicPlayer.jar
jarhash=c8896ce5b2aa79057e1324a701c1c5bd4099a8a651f044a120ad700cedfbb16e jarhash=53248a70a8cbfbcdd76e11549a132400305e91785ff98af514e68e8cafacdc19
dependency=basegame 0.4.0 dependency=basegame 0.4.1

View File

@@ -442,12 +442,12 @@ public class App implements ApplicationListener {
if (useFullscreen) { if (useFullscreen) {
// auto resize for fullscreen // auto resize for fullscreen
var disp = Lwjgl3ApplicationConfiguration.getDisplayMode(); var disp = Lwjgl3ApplicationConfiguration.getDisplayMode(Lwjgl3ApplicationConfiguration.getPrimaryMonitor());
var newWidth = ((int)(disp.width / magn)) & 0x7FFFFFFE; var newWidth = ((int)(disp.width / magn)) & 0x7FFFFFFE;
var newHeight = ((int)(disp.height / magn)) & 0x7FFFFFFE; var newHeight = ((int)(disp.height / magn)) & 0x7FFFFFFE;
scr.setDimension(newWidth, newHeight, magn); scr.setDimension(newWidth, newHeight, magn);
appConfig.setFullscreenMode(Lwjgl3ApplicationConfiguration.getDisplayMode()); appConfig.setFullscreenMode(disp);
} }
else else

View File

@@ -282,7 +282,6 @@ $BULLET Music:
- music/discs/lucid_dream.ogg - music/discs/lucid_dream.ogg
- music/discs/railway.ogg - music/discs/railway.ogg
- music/discs/welded.ogg - music/discs/welded.ogg
℗ 2021, 2022, 2023, 2024 Orstphone ℗ 2021, 2022, 2023, 2024 Orstphone
Check out the original tracks on: Check out the original tracks on:
Apple Music: <https://music.apple.com/kr/artist/orstphone/1587723053> Apple Music: <https://music.apple.com/kr/artist/orstphone/1587723053>
@@ -300,7 +299,6 @@ $BULLET Foleys:
- ambient/season/diurnal_winter.*.ogg - ambient/season/diurnal_winter.*.ogg
- ambient/season/matutinal.*.ogg - ambient/season/matutinal.*.ogg
- ambient/season/nocturnal.*.ogg - ambient/season/nocturnal.*.ogg
℗ 2011, 2013, 2015, 2020, 2021 Klankbeeld ℗ 2011, 2013, 2015, 2020, 2021 Klankbeeld
Sound from <https://www.freesound.org/people/klankbeeld> Sound from <https://www.freesound.org/people/klankbeeld>
@@ -311,38 +309,31 @@ Sound from <https://www.freesound.org/people/klankbeeld>
- effects/steps/WOOD.*.ogg - effects/steps/WOOD.*.ogg
- effects/door/wooden_open.*.ogg - effects/door/wooden_open.*.ogg
- effects/door/wooden_close.*.ogg - effects/door/wooden_close.*.ogg
℗ 2020, 2021, 2022 Nox Sound ℗ 2020, 2021, 2022 Nox Sound
Sound from <https://freesound.org/people/Nox_Sound> Sound from <https://freesound.org/people/Nox_Sound>
- effects/static/phono_pops.ogg - effects/static/phono_pops.ogg
℗ 2011 Veezay ℗ 2011 Veezay
Sound from <https://freesound.org/people/veezay> Sound from <https://freesound.org/people/veezay>
- effects/static/tape_hiss.ogg - effects/static/tape_hiss.ogg
℗ 2017 Stephen Holdaway ℗ 2017 Stephen Holdaway
Sound from <https://freesound.org/people/stecman> Sound from <https://freesound.org/people/stecman>
- effects/static/film_pops_lowpass.ogg - effects/static/film_pops_lowpass.ogg
℗ 2015 Joe DeShon ℗ 2015 Joe DeShon
Sound from <https://freesound.org/people/joedeshon> Sound from <https://freesound.org/people/joedeshon>
- effects/static/bonfire.ogg - effects/static/bonfire.ogg
℗ 2019 DrinkingWindGames ℗ 2019 DrinkingWindGames
Sound from <https://freesound.org/people/DrinkingWindGames> Sound from <https://freesound.org/people/DrinkingWindGames>
- effects/explosion/bang_bomb.ogg - effects/explosion/bang_bomb.ogg
℗ 2019 Richwise ℗ 2019 Richwise
Sound from <https://freesound.org/people/richwise> Sound from <https://freesound.org/people/richwise>
- effects/explosion/fuse.ogg - effects/explosion/fuse.ogg
- effects/explosion/fuse_continue.ogg - effects/explosion/fuse_continue.ogg
℗ 2012, 2015 j1987 and ScouseMouseJB ℗ 2012, 2015 j1987 and ScouseMouseJB
Sound from <https://freesound.org/people/j1987> and <https://freesound.org/people/ScouseMouseJB> Sound from <https://freesound.org/people/j1987> and <https://freesound.org/people/ScouseMouseJB>
@@ -351,12 +342,10 @@ Sound from <https://freesound.org/people/j1987> and <https://freesound.org/peopl
$BULLET Impulse Responses: $BULLET Impulse Responses:
- convolution/EchoThief - *.bin - convolution/EchoThief - *.bin
EchoThief Impulse Response Library EchoThief Impulse Response Library
℗ 2013-2023 Chris Warren <cwarren@sdsu.edu> ℗ 2013-2023 Chris Warren <cwarren@sdsu.edu>
- convolution/Soundwoofer - *.bin - convolution/Soundwoofer - *.bin
Soundwoofer Free Impulse Response Library Soundwoofer Free Impulse Response Library
℗ 2018 Soundwoofer Team ℗ 2018 Soundwoofer Team
<https://soundwoofer.com/User/Index?uid=soundwoofer> <https://soundwoofer.com/User/Index?uid=soundwoofer>

View File

@@ -439,7 +439,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
} }
open fun saveTheGame(onSuccessful: () -> Unit, onError: (Throwable) -> Unit) { open fun saveTheGame(onSuccessful: () -> Unit, onError: (Throwable) -> Unit) {
loadedTime_t = App.getTIME_T()
} }
/** /**

View File

@@ -561,13 +561,15 @@ object ModMgr {
)) ))
} }
} }
Terrarum.wireCodex.fromModule(module, "wires/") Terrarum.wireCodex.fromModule(module, "wires/") { wire ->
}
} }
private fun makeNewItemObj(tile: BlockProp, isWall: Boolean) = object : GameItem( private fun makeNewItemObj(tile: BlockProp, isWall: Boolean) = object : GameItem(
if (isWall) "wall@"+tile.id else tile.id if (isWall) "wall@"+tile.id else tile.id
) { ) {
override var baseMass: Double = tile.density / 100.0 override var baseMass: Double = (tile.density / 100.0) * (if (tile.isPlatform) 0.5 else 1.0)
override var baseToolSize: Double? = null override var baseToolSize: Double? = null
override var inventoryCategory = if (isWall) Category.WALL else Category.BLOCK override var inventoryCategory = if (isWall) Category.WALL else Category.BLOCK
override var canBeDynamic = false override var canBeDynamic = false

View File

@@ -11,6 +11,8 @@ class Point2d() : Cloneable {
var x: Double = 0.0 var x: Double = 0.0
var y: Double = 0.0 var y: Double = 0.0
constructor(other: Point2d) : this(other.x, other.y)
constructor(x: Double, y: Double) : this() { constructor(x: Double, y: Double) : this() {
this.x = x this.x = x
this.y = y this.y = y

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.serialise.toUint import net.torvald.terrarum.serialise.toUint
import java.net.URL
import java.time.LocalDate import java.time.LocalDate
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.* import java.util.*
@@ -48,6 +49,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
basegame basegame
""" """
val FIXED_LATEST_DOWNLOAD_LINK = URL("https://github.com/curioustorvald/Terrarum/releases/latest")
/** /**
* *
* *
@@ -66,12 +69,13 @@ basegame
* e.g. 0x02010034 will be translated as 2.1.52 * e.g. 0x02010034 will be translated as 2.1.52
* *
*/ */
const val VERSION_RAW: Long = 0x0000_000004_000000 const val VERSION_RAW: Long = 0x0000_000004_000001
// Commit counts up to the Release 0.3.0: 2259 // Commit counts up to the Release 0.3.0: 2259
// Commit counts up to the Release 0.3.1: 2278 // Commit counts up to the Release 0.3.1: 2278
// Commit counts up to the Release 0.3.2: 2732 // Commit counts up to the Release 0.3.2: 2732
// Commit counts up to the Release 0.3.3: 3020 // Commit counts up to the Release 0.3.3: 3020
// Commit counts up to the Release 0.4.0: 3631 // Commit counts up to the Release 0.4.0: 3631
// Commit counts up to the Release 0.4.1: 3678
// val VERSION_SNAPSHOT = Snapshot(0) // for normal dev // val VERSION_SNAPSHOT = Snapshot(0) // for normal dev
// val VERSION_SNAPSHOT = ForcedSnapshot("24w07d") // for snapshot release // val VERSION_SNAPSHOT = ForcedSnapshot("24w07d") // for snapshot release

View File

@@ -123,14 +123,22 @@ class AudioMixer : Disposable {
* Return oldest dynamic track, even if the track is currently playing * Return oldest dynamic track, even if the track is currently playing
*/ */
fun getFreeTrackNoMatterWhat(): TerrarumAudioMixerTrack { fun getFreeTrackNoMatterWhat(): TerrarumAudioMixerTrack {
return getFreeTrack() ?: dynamicTracks.minBy { it.playStartedTime } synchronized(this) {
return getFreeTrack() ?: dynamicTracks.minBy { it.playStartedTime }.also { it.checkedOutTime = System.nanoTime() }
}
} }
/** /**
* Return oldest dynamic track that is not playing * Return oldest dynamic track that is not playing
*/ */
fun getFreeTrack(): TerrarumAudioMixerTrack? { fun getFreeTrack(): TerrarumAudioMixerTrack? {
return dynamicTracks.filter { it.trackingTarget == null && !it.isPlaying }.minByOrNull { it.playStartedTime } synchronized(this) {
return dynamicTracks.filter { it.trackingTarget == null && !it.isPlaying }
.minByOrNull { maxOf(it.checkedOutTime, it.playStartedTime) }
.also {
it?.checkedOutTime = System.nanoTime()
}
}
} }
var listenerHeadSize = BinoPan.EARDIST_DEFAULT; private set var listenerHeadSize = BinoPan.EARDIST_DEFAULT; private set
@@ -144,6 +152,10 @@ class AudioMixer : Disposable {
return (headSize0 ?: 0f).times(scale).coerceAtLeast(BinoPan.EARDIST_DEFAULT) return (headSize0 ?: 0f).times(scale).coerceAtLeast(BinoPan.EARDIST_DEFAULT)
} }
private val millisecUnitTime = 100L // 48 * p, p is multiplied to compensate the time takes for writing samples
private val sleepMS = App.audioBufferSize / millisecUnitTime
private val sleepNS = (App.audioBufferSize / millisecUnitTime * 1000000).toInt() % 1000000
fun createProcessingThread(): Thread = Thread { fun createProcessingThread(): Thread = Thread {
// serial precessing // serial precessing
while (processing) { while (processing) {
@@ -168,6 +180,8 @@ class AudioMixer : Disposable {
while (processing && !masterTrack.pcmQueue.isEmpty) { while (processing && !masterTrack.pcmQueue.isEmpty) {
masterTrack.adev!!.writeSamples(masterTrack.pcmQueue.removeFirst()) // it blocks until the queue is consumed masterTrack.adev!!.writeSamples(masterTrack.pcmQueue.removeFirst()) // it blocks until the queue is consumed
} }
Thread.sleep(sleepMS, sleepNS)
} }
// parallel processing, it seems even on the 7950X this is less efficient than serial processing... // parallel processing, it seems even on the 7950X this is less efficient than serial processing...

View File

@@ -147,7 +147,7 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
private val readBuf = ByteArray(fetchSize * 4) private val readBuf = ByteArray(fetchSize * 4)
init { init {
printdbg(this, "App.audioMixerBufferSize=${App.audioBufferSize}") // printdbg(this, "App.audioMixerBufferSize=${App.audioBufferSize}")
} }
private fun shift(array: FloatArray, size: Int) { private fun shift(array: FloatArray, size: Int) {

View File

@@ -103,6 +103,8 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
return newRead return newRead
} }
var bufEmpty = true; private set
override fun run() { override fun run() {
// while (running) { // uncomment to multithread // while (running) { // uncomment to multithread
/*synchronized(pauseLock) { // uncomment to multithread /*synchronized(pauseLock) { // uncomment to multithread
@@ -196,7 +198,7 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
var samplesL1: FloatArray var samplesL1: FloatArray
var samplesR1: FloatArray var samplesR1: FloatArray
var bufEmpty = false bufEmpty = false
// get samples and apply the fader // get samples and apply the fader
if (track.trackType == TrackType.MASTER || track.trackType == TrackType.BUS) { if (track.trackType == TrackType.MASTER || track.trackType == TrackType.BUS) {
@@ -379,15 +381,6 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
} }
private fun <T> Queue<T>.removeFirstOrElse(function: () -> T): T {
return if (this.isEmpty) {
this.removeFirst()
}
else {
function()
}
}
class FeedSamplesToAdev(val bufferSize: Int, val rate: Int, val track: TerrarumAudioMixerTrack) : Runnable { class FeedSamplesToAdev(val bufferSize: Int, val rate: Int, val track: TerrarumAudioMixerTrack) : Runnable {
init { init {

View File

@@ -65,7 +65,7 @@ class TerrarumAudioMixerTrack(
internal val streamPlaying = AtomicBoolean(false) internal val streamPlaying = AtomicBoolean(false)
var playStartedTime = 0L; internal set var playStartedTime = 0L; internal set
var checkedOutTime = 0L; internal set
fun copyStatusTo(other: TerrarumAudioMixerTrack) { fun copyStatusTo(other: TerrarumAudioMixerTrack) {
other.pullNextTrack = this.pullNextTrack other.pullNextTrack = this.pullNextTrack
@@ -162,6 +162,9 @@ class TerrarumAudioMixerTrack(
override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTrack).hash override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTrack).hash
fun stop() { fun stop() {
printdbg("TerrarumAudioMixerTrack $name", "Stop music (mixertrack=${this.name}, musictrack=$currentTrack)")
// printStackTrace("TerrarumAudioMixerTrack $name")
currentTrack?.reset() currentTrack?.reset()
streamPlaying.set(false) streamPlaying.set(false)

View File

@@ -53,7 +53,7 @@ class OreCodex {
private fun setProp(modname: String, key: Int, record: CSVRecord) { private fun setProp(modname: String, key: Int, record: CSVRecord) {
val prop = OreProp() val prop = OreProp()
prop.id = "ores@$modname:$key" prop.id = "ores@$modname:$key"
prop.tags = record.get("tags").split(',').map { it.trim() }.toHashSet() prop.tags = record.get("tags").split(',').map { it.trim().toUpperCase() }.toHashSet()
prop.item = record.get("item").let { if (it == null) "" else if (it.contains(':')) it else "$modname:$it" } prop.item = record.get("item").let { if (it == null) "" else if (it.contains(':')) it else "$modname:$it" }
oreProps[prop.id] = prop oreProps[prop.id] = prop

View File

@@ -39,15 +39,15 @@ class WireCodex {
* @param module name of the module * @param module name of the module
* @param path to the "wires" directory, not path to the CSV; must end with a slash! * @param path to the "wires" directory, not path to the CSV; must end with a slash!
*/ */
fun fromModule(module: String, path: String) { fun fromModule(module: String, path: String, blockRegisterHook: (WireProp) -> Unit) {
printdbg(this, "Building wire properties table for module $module") printdbg(this, "Building wire properties table for module $module")
try { try {
register(module, path, CSVFetcher.readFromModule(module, path + "wires.csv")) register(module, path, CSVFetcher.readFromModule(module, path + "wires.csv"), blockRegisterHook)
} }
catch (e: IOException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() }
} }
fun fromCSV(module: String, path: String, csvString: String) { fun fromCSV(module: String, path: String, csvString: String, blockRegisterHook: (WireProp) -> Unit) {
printdbg(this, "Building wire properties table for module $module") printdbg(this, "Building wire properties table for module $module")
val csvParser = org.apache.commons.csv.CSVParser.parse( val csvParser = org.apache.commons.csv.CSVParser.parse(
@@ -57,10 +57,10 @@ class WireCodex {
val csvRecordList = csvParser.records val csvRecordList = csvParser.records
csvParser.close() csvParser.close()
register(module, path, csvRecordList) register(module, path, csvRecordList, blockRegisterHook)
} }
private fun register(module: String, path: String, records: List<CSVRecord>) { private fun register(module: String, path: String, records: List<CSVRecord>, blockRegisterHook: (WireProp) -> Unit) {
records.forEach { records.forEach {
setProp(module, it.intVal("id"), it) setProp(module, it.intVal("id"), it)
} }
@@ -73,9 +73,12 @@ class WireCodex {
val t = TextureRegionPack(ModMgr.getGdxFile(module, "$path$wireid.tga"), TILE_SIZE, TILE_SIZE) val t = TextureRegionPack(ModMgr.getGdxFile(module, "$path$wireid.tga"), TILE_SIZE, TILE_SIZE)
/*return*/t /*return*/t
} }
wireProps[id]?.let(blockRegisterHook)
} }
CommonResourcePool.loadAll() CommonResourcePool.loadAll()
} }
fun getAll() = wireProps.values fun getAll() = wireProps.values
@@ -134,6 +137,7 @@ class WireCodex {
prop.inputType = record.get("inputtype") ?: prop.accepts prop.inputType = record.get("inputtype") ?: prop.accepts
prop.outputType = record.get("outputtype") ?: prop.accepts prop.outputType = record.get("outputtype") ?: prop.accepts
prop.canBranch = record.boolVal("branching") prop.canBranch = record.boolVal("branching")
prop.tags = record.get("tags").split(',').map { it.trim().toUpperCase() }.toHashSet()
wireProps[prop.id] = prop wireProps[prop.id] = prop

View File

@@ -24,4 +24,18 @@ class WireProp {
* Mainly intended to be used by third-party modules * Mainly intended to be used by third-party modules
*/ */
val extra = Codex() val extra = Codex()
@Transient var tags = HashSet<String>()
fun hasTag(s: String) = tags.contains(s)
fun hasAnyTagOf(vararg s: String) = s.any { hasTag(it) }
fun hasAnyTag(s: Collection<String>) = s.any { hasTag(it) }
fun hasAnyTag(s: Array<String>) = s.any { hasTag(it) }
fun hasAllTagOf(vararg s: String) = s.all { hasTag(it) }
fun hasAllTag(s: Collection<String>) = s.all { hasTag(it) }
fun hasAllTag(s: Array<String>) = s.all { hasTag(it) }
fun hasNoTagOf(vararg s: String) = s.none { hasTag(it) }
fun hasNoTag(s: Collection<String>) = s.none { hasTag(it) }
fun hasNoTag(s: Array<String>) = s.none { hasTag(it) }
} }

View File

@@ -15,7 +15,7 @@ import org.apache.commons.codec.digest.DigestUtils
* - BE CRACKABLE (crackstation.net) * - BE CRACKABLE (crackstation.net)
* *
* Example passwords would be: * Example passwords would be:
* aryll -> beedle -> ciela -> daruk -> ... -> linebeck -> mido -> navi -> ... * aryll -> beedle -> ciela -> daruk -> epona -> ... -> linebeck -> mido -> navi -> ...
* *
* Notes: * Notes:
* do NOT put plaintext anywhere in the code (except for comments maybe) * do NOT put plaintext anywhere in the code (except for comments maybe)
@@ -36,7 +36,7 @@ internal object Authenticator : ConsoleCommand {
// println("auth passwd: '$pwd'") // println("auth passwd: '$pwd'")
// println("hash: $hashedPwd") // println("hash: $hashedPwd")
if ("c40232ae7b8020da3ab1449a015e7cc23f249a790856b63b1b69c6a5de019fed".equals(hashedPwd, ignoreCase = true)) { if ("4a26c5cd64195c4a52d2e3770e56c1d0c65861d2a03b47f8ba5d25ca033b9c42".equals(hashedPwd, ignoreCase = true)) {
// beedle // beedle
val msg = if (a) "Locked" else "Authenticated" val msg = if (a) "Locked" else "Authenticated"
Echo(msg) Echo(msg)

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum.gameactors
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.App.printdbgerr
import net.torvald.terrarum.INGAME import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.audio.MusicContainer
@@ -160,6 +161,10 @@ abstract class Actor : Comparable<Actor>, Runnable {
musicTracks[music] = track musicTracks[music] = track
musicTracks1.add(track.name) musicTracks1.add(track.name)
track.stop() track.stop()
track.trackingTarget = this
}
else {
printdbgerr(this, "Could not get a free track")
} }
} }
@@ -182,9 +187,9 @@ abstract class Actor : Comparable<Actor>, Runnable {
it.currentTrack = music it.currentTrack = music
it.maxVolumeFun = { volume } it.maxVolumeFun = { volume }
it.volume = volume it.volume = volume
doSomethingWithTrack(it)
// it.play() // it.play()
it.playRequested.set(true) it.playRequested.set(true)
doSomethingWithTrack(it)
} }
} }
} }

View File

@@ -443,7 +443,7 @@ open class ActorWithBody : Actor {
fun setPosition(pos: Point2d) = setPosition(pos.x, pos.y) fun setPosition(pos: Point2d) = setPosition(pos.x, pos.y)
fun setPosition(pos: Vector2) = setPosition(pos.x, pos.y) fun setPosition(pos: Vector2) = setPosition(pos.x, pos.y)
fun setPositionFromCentrePoint(pos: Vector2) = setPosition(pos.x, pos.y + (hitbox.height) / 2)
/** /**
* ONLY FOR INITIAL SETUP * ONLY FOR INITIAL SETUP

View File

@@ -524,9 +524,17 @@ open class GameWorld(
if (wiringGraph[blockAddr]!![itemID] == null) if (wiringGraph[blockAddr]!![itemID] == null)
wiringGraph[blockAddr]!![itemID] = WiringSimCell(0, vector) wiringGraph[blockAddr]!![itemID] = WiringSimCell(0, vector)
wiringGraph[blockAddr]!![itemID]!!.emt.set(vector) // out = max(old, new)
val old = wiringGraph[blockAddr]!![itemID]!!.emt
wiringGraph[blockAddr]!![itemID]!!.emt.set(old max vector)
} }
private infix fun Vector2.max(other: Vector2) = Vector2(
maxOf(this.x, other.x),
maxOf(this.y, other.y)
)
fun addWireRecvStateOf(x: Int, y: Int, itemID: ItemID, state: WireReceptionState) { fun addWireRecvStateOf(x: Int, y: Int, itemID: ItemID, state: WireReceptionState) {
val (x, y) = coerceXY(x, y) val (x, y) = coerceXY(x, y)
val blockAddr = LandUtil.getBlockAddr(this, x, y) val blockAddr = LandUtil.getBlockAddr(this, x, y)

View File

@@ -13,20 +13,29 @@ import net.torvald.random.HQRNG
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.* import net.torvald.terrarum.App.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.SI_TO_GAME_ACC
import net.torvald.terrarum.gamecontroller.KeyToggler import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.mouseInInteractableRange
import net.torvald.terrarum.gameparticles.ParticleBase import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
import net.torvald.terrarum.modulebasegame.gameitems.getThrowPosAndVector
import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.weather.WeatherMixer import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.weather.WeatherMixer.render
import net.torvald.terrarum.worlddrawer.BlocksDrawer import net.torvald.terrarum.worlddrawer.BlocksDrawer
import net.torvald.terrarum.worlddrawer.FeaturesDrawer import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.LightmapRenderer import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray import net.torvald.util.CircularArray
import org.dyn4j.geometry.Vector2
import kotlin.system.exitProcess import kotlin.system.exitProcess
@@ -206,6 +215,17 @@ object IngameRenderer : Disposable {
private var oldCamX = 0 private var oldCamX = 0
private fun FlippingSpriteBatch.drawFramebufferWithZoom(buf: TextureRegion, zoom: Float) {
val t = (if (App.getConfigBoolean("fx_streamerslayout")) App.scr.chatWidth / 2 else 0).toFloat()
this.draw(buf,
-0.5f * buf.regionWidth * zoom + 0.5f * buf.regionWidth + t * (zoom - 1f),
-0.5f * buf.regionHeight * zoom + 0.5f * buf.regionHeight,
buf.regionWidth * zoom,
buf.regionHeight * zoom
)
}
operator fun invoke( operator fun invoke(
frameDelta: Float, frameDelta: Float,
gamePaused: Boolean, gamePaused: Boolean,
@@ -248,6 +268,8 @@ object IngameRenderer : Disposable {
drawToRGB(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer) drawToRGB(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
drawToA(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer) drawToA(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
drawOverlayActors(frameDelta, actorsRenderOverlay) drawOverlayActors(frameDelta, actorsRenderOverlay)
if (player != null && player is Pocketed) drawAimGuide(frameDelta, player)
} }
batch.color = Color.WHITE batch.color = Color.WHITE
@@ -287,12 +309,7 @@ object IngameRenderer : Disposable {
blendNormalStraightAlpha(batch) blendNormalStraightAlpha(batch)
batch.shader = shaderBlendGlow batch.shader = shaderBlendGlow
shaderBlendGlow.setUniformi("tex1", 1) shaderBlendGlow.setUniformi("tex1", 1)
batch.draw(rgbTex, batch.drawFramebufferWithZoom(rgbTex, zoom)
-0.5f * rgbTex.regionWidth * zoom + 0.5f * rgbTex.regionWidth,
-0.5f * rgbTex.regionHeight * zoom + 0.5f * rgbTex.regionHeight,
rgbTex.regionWidth * zoom,
rgbTex.regionHeight * zoom
)
} }
} }
@@ -304,12 +321,7 @@ object IngameRenderer : Disposable {
batch.inUse { batch.inUse {
blendNormalStraightAlpha(batch) blendNormalStraightAlpha(batch)
batch.shader = null batch.shader = null
batch.draw(rgbTex, batch.drawFramebufferWithZoom(rgbTex, zoom)
-0.5f * rgbTex.regionWidth * zoom + 0.5f * rgbTex.regionWidth,
-0.5f * rgbTex.regionHeight * zoom + 0.5f * rgbTex.regionHeight,
rgbTex.regionWidth * zoom,
rgbTex.regionHeight * zoom
)
// indicator // indicator
batch.color = Color.RED batch.color = Color.RED
@@ -331,12 +343,7 @@ object IngameRenderer : Disposable {
batch.inUse { batch.inUse {
blendNormalStraightAlpha(batch) blendNormalStraightAlpha(batch)
batch.shader = null batch.shader = null
batch.draw(aTex, batch.drawFramebufferWithZoom(aTex, zoom)
-0.5f * aTex.regionWidth * zoom + 0.5f * aTex.regionWidth,
-0.5f * aTex.regionHeight * zoom + 0.5f * aTex.regionHeight,
aTex.regionWidth * zoom,
aTex.regionHeight * zoom
)
// indicator // indicator
batch.color = Color.WHITE batch.color = Color.WHITE
@@ -730,6 +737,160 @@ object IngameRenderer : Disposable {
} }
} }
private fun drawAimGuide(frameDelta: Float, player: ActorWithBody) {
fboRGB_lightMixed.inActionF(camera, batch) { fb ->
setCameraPosition(0f, 0f)
// BlocksDrawer.renderWhateverGlow_WALL
batch.inUse {
batch.shader = null
batch.color = Color.WHITE
moveCameraToWorldCoord()
(player as Pocketed).inventory.itemEquipped[GameItem.EquipPosition.HAND_GRIP]?.let { itemID ->
val heldItem = ItemCodex[itemID] // will be null for blocks
// this is a case-by-case affair
when (heldItem) {
is ItemThrowable -> drawTrajectoryForThrowable(fb, batch, frameDelta, player, world, heldItem)
}
}
}
setCameraPosition(0f, 0f)
// BlocksDrawer.renderWhateverGlow_TERRAIN
}
}
private val cubeSize = 7.0
private val externalV = Vector2()
private val maxStep = 56
private fun drawTrajectoryForThrowable(frameBuffer: FrameBuffer, batch: SpriteBatch, frameDelta: Float, player: ActorWithBody, world: GameWorld, item: ItemThrowable) {
val ww = world.width * TILE_SIZEF
mouseInInteractableRange(player) { mx, my, mtx, mty ->
val (throwPos, throwVector) = getThrowPosAndVector(player)
val grav = world.gravitation
externalV.set(throwVector)
var c = 0
while (c < maxStep) {
batch.color = Color(0.9f, 0.9f, 0.9f, 0.9f * (1f - (c.toFloat() / maxStep).sqr()))
// plot a dot
if (c > 0) {
Toolkit.fillArea(batch, throwPos.x.toFloat(), throwPos.y.toFloat(), 2f, 2f)
Toolkit.fillArea(batch, throwPos.x.toFloat() + ww, throwPos.y.toFloat(), 2f, 2f)
Toolkit.fillArea(batch, throwPos.x.toFloat() - ww, throwPos.y.toFloat(), 2f, 2f)
}
// simulate physics
applyGravitation(grav, cubeSize) // TODO use actual value instead of `cubeSize`
// move the point
throwPos += externalV
// more physics
setHorizontalFriction()
setVerticalFriction()
// break if colliding with a tile
val hitSolid = listOf(
throwPos + Vector2(-cubeSize/2, -cubeSize/2),
throwPos + Vector2(-cubeSize/2, +cubeSize/2),
throwPos + Vector2(+cubeSize/2, +cubeSize/2),
throwPos + Vector2(+cubeSize/2, -cubeSize/2),
).any {
val wx = (it.x / TILE_SIZED).toInt()
val wy = (it.y / TILE_SIZED).toInt()
val tile = world.getTileFromTerrain(wx, wy)
BlockCodex[tile].isSolid
}
if (hitSolid)
break
c++
}
1L
}
}
private val bodyFriction = BlockCodex[Block.AIR].friction.frictionToMult()
private val bodyViscosity = BlockCodex[Block.AIR].viscosity.viscosityToMult()
private fun applyGravitation(gravitation: Vector2, hitboxWidth: Double) {
applyForce(getDrag(externalV, gravitation, hitboxWidth))
}
private fun Int.frictionToMult(): Double = this / 16.0
private fun Int.viscosityToMult(): Double = 16.0 / (16.0 + this)
private fun applyForce(acc: Vector2) {
val speedMultByTile = bodyViscosity
externalV += acc * speedMultByTile
}
private fun getDrag(externalForce: Vector2, gravitation: Vector2, hitboxWidth: Double): Vector2 {
val dragCoefficient = 1.2
/**
* weight; gravitational force in action
* W = mass * G (9.8 [m/s^2])
*/
val W: Vector2 = gravitation * Terrarum.PHYS_TIME_FRAME
/**
* Area
*/
val A: Double = (hitboxWidth / METER).sqr() // this is not physically accurate but it's needed to make large playable characters more controllable
/**
* Drag of atmosphere
* D = Cd (drag coefficient) * 0.5 * rho (density) * V^2 (velocity sqr) * A (area)
*/
val D: Vector2 = Vector2(externalForce.x.magnSqr(), externalForce.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / Terrarum.PHYS_TIME_FRAME * SI_TO_GAME_ACC
return V
// FIXME v * const, where const = 1.0 for FPS=60, sqrt(2.0) for FPS=30, etc.
// this is "close enough" solution and not perfect.
}
/** about stopping
* for about get moving, see updateMovementControl */
private fun setHorizontalFriction() {
val friction = 0.3 * bodyFriction
if (externalV.x < 0) {
externalV.x += friction
if (externalV.x > 0) externalV.x = 0.0 // compensate overshoot
}
else if (externalV.x > 0) {
externalV.x -= friction
if (externalV.x < 0) externalV.x = 0.0 // compensate overshoot
}
}
private fun setVerticalFriction() {
val friction = 0.3 * bodyFriction
if (externalV.y < 0) {
externalV.y += friction
if (externalV.y > 0) externalV.y = 0.0 // compensate overshoot
}
else if (externalV.y > 0) {
externalV.y -= friction
if (externalV.y < 0) externalV.y = 0.0 // compensate overshoot
}
}
private fun invokeInit() { private fun invokeInit() {
if (!initDone) { if (!initDone) {

View File

@@ -319,6 +319,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
(!tileProp.isSolid && !wallProp.isSolid).toInt().toFloat() (!tileProp.isSolid && !wallProp.isSolid).toInt().toFloat()
} }
) )
loadedTime_t = App.getTIME_T()
} }
data class NewGameParams( data class NewGameParams(
@@ -493,6 +495,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
App.savegameWorlds[world.worldIndex] = SavegameCollection.collectFromBaseFilename(File(worldsDir), worldSavefileName) App.savegameWorlds[world.worldIndex] = SavegameCollection.collectFromBaseFilename(File(worldsDir), worldSavefileName)
App.savegameWorldsName[world.worldIndex] = worldName App.savegameWorldsName[world.worldIndex] = worldName
loadedTime_t = App.getTIME_T()
} }
} }
} }
@@ -1182,6 +1186,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
// return to normal state // return to normal state
onSuccessful() onSuccessful()
loadedTime_t = App.getTIME_T()
} }
} }
} }
@@ -1412,6 +1418,9 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
val timeDiff = System.nanoTime() - start val timeDiff = System.nanoTime() - start
debugTimers.put("Last Autosave Duration", timeDiff) debugTimers.put("Last Autosave Duration", timeDiff)
printdbg(this, "Last Autosave Duration: ${(timeDiff) / 1000000000} s") printdbg(this, "Last Autosave Duration: ${(timeDiff) / 1000000000} s")
loadedTime_t = App.getTIME_T()
} }
} }

View File

@@ -35,6 +35,8 @@ import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.ReadSimpleWorld import net.torvald.terrarum.serialise.ReadSimpleWorld
import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemTextButton
import net.torvald.terrarum.utils.OpenURL
import net.torvald.terrarum.weather.WeatherMixer import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray import net.torvald.util.CircularArray
@@ -494,18 +496,47 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
// update available! // update available!
if (App.hasUpdate) { if (App.hasUpdate) {
batch.color = Toolkit.Theme.COL_SELECTED
batch.color = if (System.currentTimeMillis() % 1500 < 750L)
Toolkit.Theme.COL_MOUSE_UP
else
Toolkit.Theme.COL_SELECTED
val tx = UIRemoCon.menubarOffX + UIRemoCon.UIRemoConElement.paddingLeft / 2 + uiRemoCon.posX
val ty1 = UIRemoCon.menubarOffY - uiRemoCon.height + uiRemoCon.posY - 60
val ty2 = ty1 + 28
App.fontGame.draw( App.fontGame.draw(
batch, batch,
Lang["MENU_UPDATE_UPDATE_AVAILABLE"], Lang["MENU_UPDATE_UPDATE_AVAILABLE"],
UIRemoCon.menubarOffX + UIRemoCon.UIRemoConElement.paddingLeft / 2 + uiRemoCon.posX, tx, ty1
UIRemoCon.menubarOffY - uiRemoCon.height + uiRemoCon.posY
) )
val tw = App.fontGame.getWidth("<${TerrarumAppConfiguration.FIXED_LATEST_DOWNLOAD_LINK}>")
if (Terrarum.mouseScreenX in tx - 32 until tx + tw + 32 &&
Terrarum.mouseScreenY in ty2 - 16 until ty2 + App.fontGame.lineHeight.toInt() + 16) {
if (Gdx.input.isButtonJustPressed(App.getConfigInt("config_mouseprimary"))) {
OpenURL(TerrarumAppConfiguration.FIXED_LATEST_DOWNLOAD_LINK)
}
batch.color = Toolkit.Theme.COL_SELECTED
}
else
batch.color = Toolkit.Theme.COL_MOUSE_UP
App.fontGame.draw(
batch,
"<${TerrarumAppConfiguration.FIXED_LATEST_DOWNLOAD_LINK}>",
tx, ty2
)
} }
} }
} }
override fun pause() { override fun pause() {
} }

View File

@@ -589,7 +589,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
private fun applyVelo(x: Int): Double { private fun applyVelo(x: Int): Double {
return if (x < WALK_FRAMES_TO_MAX_ACCEL) return if (x < WALK_FRAMES_TO_MAX_ACCEL)
0.5 - 0.5 * Math.cos(Math.PI * x / WALK_FRAMES_TO_MAX_ACCEL) x.toDouble() / WALK_FRAMES_TO_MAX_ACCEL //0.5 - 0.5 * Math.cos(Math.PI * x / WALK_FRAMES_TO_MAX_ACCEL)
else 1.0 else 1.0
} }

View File

@@ -8,6 +8,7 @@ import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.ui.UIQuickslotBar import net.torvald.terrarum.modulebasegame.ui.UIQuickslotBar
import net.torvald.terrarum.sqr
/** /**
* Created by minjaesong on 2016-03-15. * Created by minjaesong on 2016-03-15.
@@ -38,6 +39,21 @@ class ActorInventory() : FixtureInventory() {
field = value field = value
} }
val maxCapacityByActor: Double
get() = maxCapacity * ((actor.actorValue.getAsDouble(AVKey.SCALE) ?: 1.0) * (actor.actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)).sqr()
/**
* How encumbered the actor is. 1.0 if weight of the items are exactly same as the capacity limit, >1.0 if encumbered.
*/
override val encumberment: Double
get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER)
0.0
else if (capacityMode == CAPACITY_MODE_WEIGHT)
capacity / maxCapacityByActor
else
0.0
/** /**
* List of all equipped items (tools, armours, rings, necklaces, etc.) * List of all equipped items (tools, armours, rings, necklaces, etc.)
* *

View File

@@ -248,7 +248,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
* Condition for (if the tile is solid) is always implied regardless of this function. See [canSpawnHere0] * Condition for (if the tile is solid) is always implied regardless of this function. See [canSpawnHere0]
*/ */
open fun canSpawnOnThisFloor(itemID: ItemID): Boolean { open fun canSpawnOnThisFloor(itemID: ItemID): Boolean {
return true val blockprop = BlockCodex[itemID]
return blockprop.isSolid || blockprop.isPlatform
} }
fun canSpawnHere(posX0: Int, posY0: Int): Boolean { fun canSpawnHere(posX0: Int, posY0: Int): Boolean {
@@ -277,7 +278,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
val xs = posX until posX + blockBox.width val xs = posX until posX + blockBox.width
cannotSpawn = cannotSpawn or xs.any { x -> cannotSpawn = cannotSpawn or xs.any { x ->
world!!.getTileFromTerrain(x, y).let { world!!.getTileFromTerrain(x, y).let {
!BlockCodex[it].isSolid || !canSpawnOnThisFloor(it) !canSpawnOnThisFloor(it)
} }
} }
} }

View File

@@ -1,11 +1,9 @@
package net.torvald.terrarum.modulebasegame.gameactors package net.torvald.terrarum.modulebasegame.gameactors
import com.badlogic.gdx.Gdx
import net.torvald.gdx.graphics.Cvec import net.torvald.gdx.graphics.Cvec
import net.torvald.spriteanimation.SheetSpriteAnimation import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.audio.MusicContainer
import net.torvald.terrarum.audio.decibelsToFullscale
import net.torvald.terrarum.audio.dsp.Gain import net.torvald.terrarum.audio.dsp.Gain
import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
@@ -17,7 +15,6 @@ import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.ui.UICrafting import net.torvald.terrarum.modulebasegame.ui.UICrafting
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/** /**
@@ -81,6 +78,8 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
private var nextDelay = 0.25f private var nextDelay = 0.25f
private var spawnTimer = 0f private var spawnTimer = 0f
@Transient private var audioStatus = 0
override fun updateImpl(delta: Float) { override fun updateImpl(delta: Float) {
super.updateImpl(delta) super.updateImpl(delta)
@@ -108,17 +107,32 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
// manage audio // manage audio
getTrackByAudio(static).let { getTrackByAudio(static).let {
if (it != null && !it.isPlaying) { // printdbg(this, "Checking out track ${it?.name}")
startAudio(static) { if (it != null) {
it.filters[filterIndex] = Gain(0f)
if (audioStatus == 0) {
startAudio(static) {
it.filters[filterIndex] = Gain(0f)
audioStatus = 1
}
} }
} }
} else {
getTrackByAudio(static)?.let { // printdbg(this, "Track is null! (old audio status=$audioStatus")
if (it.filters[filterIndex] !is Gain) // just in case... audioStatus = 0
it.filters[filterIndex] = Gain(0f) }
(it.filters[filterIndex] as Gain).gain = 0.4f * volRand.get() if (it != null) {
if (it.processor.streamBuf != null || it.playRequested.get()) {
if (it.filters[filterIndex] !is Gain) // just in case...
it.filters[filterIndex] = Gain(0f)
(it.filters[filterIndex] as Gain).gain = 0.4f * volRand.get()
}
else {
audioStatus = 0
}
}
} }
} }

View File

@@ -254,7 +254,7 @@ open class FixtureInventory() {
/** /**
* How encumbered the actor is. 1.0 if weight of the items are exactly same as the capacity limit, >1.0 if encumbered. * How encumbered the actor is. 1.0 if weight of the items are exactly same as the capacity limit, >1.0 if encumbered.
*/ */
val encumberment: Double open val encumberment: Double
get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER) get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER)
0.0 0.0
else if (capacityMode == CAPACITY_MODE_WEIGHT) else if (capacityMode == CAPACITY_MODE_WEIGHT)
@@ -332,6 +332,10 @@ class InventoryPair : Comparable<InventoryPair> {
operator fun component2() = qty operator fun component2() = qty
override fun compareTo(other: InventoryPair) = this.itm.compareTo(other.itm) override fun compareTo(other: InventoryPair) = this.itm.compareTo(other.itm)
override fun toString(): String {
return if (qty == -1L) "$itm" else "$itm ($qty)"
}
} }
class InventoryTransactionFailedError(msg: String) : Error(msg) class InventoryTransactionFailedError(msg: String) : Error(msg)

View File

@@ -7,6 +7,9 @@ import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
/**
* Created by minjaesong on 2021-08-08.
*/
class FixtureLogicSignalEmitter : Electric { class FixtureLogicSignalEmitter : Electric {
@Transient override val spawnNeedsFloor = false @Transient override val spawnNeedsFloor = false

View File

@@ -0,0 +1,59 @@
package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.TerrarumAppConfiguration
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.toInt
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2024-03-01.
*/
class FixtureSignalBulb : Electric {
@Transient override val spawnNeedsFloor = false
@Transient override val spawnNeedsWall = true
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
nameFun = { Lang["ITEM_COPPER_BULB"] }
)
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/copper_bulb.tga")
val itemImage2 = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/copper_bulb_emissive.tga")
density = 1400.0
setHitboxDimension(TerrarumAppConfiguration.TILE_SIZE, TerrarumAppConfiguration.TILE_SIZE, 0, 1)
makeNewSprite(TextureRegionPack(itemImage.texture, TerrarumAppConfiguration.TILE_SIZE, TerrarumAppConfiguration.TILE_SIZE)).let {
it.setRowsAndFrames(2,1)
it.delays = floatArrayOf(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
}
makeNewSpriteEmissive(TextureRegionPack(itemImage2.texture, TerrarumAppConfiguration.TILE_SIZE, TerrarumAppConfiguration.TILE_SIZE)).let {
it.setRowsAndFrames(2,1)
it.delays = floatArrayOf(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
}
actorValue[AVKey.BASEMASS] = FixtureLogicSignalEmitter.MASS
setWireSinkAt(0, 0, "digital_bit")
}
private fun light(state: Boolean) {
(sprite as SheetSpriteAnimation).currentRow = state.toInt()
(spriteEmissive as SheetSpriteAnimation).currentRow = state.toInt()
}
override fun onSignalHigh(readFrom: BlockBoxIndex) {
light(true)
}
override fun onSignalLow(readFrom: BlockBoxIndex) {
light(false)
}
}

View File

@@ -0,0 +1,71 @@
package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.App
import net.torvald.terrarum.TerrarumAppConfiguration
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.toInt
import net.torvald.terrarum.ui.MouseLatch
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
/**
* Created by minjaesong on 2024-03-01.
*/
class FixtureSignalSwitchManual : Electric {
@Transient override val spawnNeedsFloor = false
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
nameFun = { Lang["ITEM_LOGIC_SIGNAL_SWITCH"] }
)
private val variant = (Math.random() * 8).toInt()
private var state = false // false = off
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/signal_switch.tga")
density = 1400.0
setHitboxDimension(TerrarumAppConfiguration.TILE_SIZE, TerrarumAppConfiguration.TILE_SIZE, 0, 1)
makeNewSprite(TextureRegionPack(itemImage.texture, TerrarumAppConfiguration.TILE_SIZE, TerrarumAppConfiguration.TILE_SIZE)).let {
it.setRowsAndFrames(2,8)
it.currentFrame = variant
it.delays = floatArrayOf(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
}
actorValue[AVKey.BASEMASS] = FixtureLogicSignalEmitter.MASS
setWireEmitterAt(0, 0, "digital_bit")
}
override fun reload() {
super.reload()
(sprite as SheetSpriteAnimation).currentFrame = variant
(sprite as SheetSpriteAnimation).currentRow = state.toInt()
setWireEmissionAt(0, 0, Vector2(state.toInt().toDouble(), 0.0))
}
@Transient private val clickLatch = MouseLatch(listOf(App.getConfigInt("config_mousesecondary")))
override fun updateImpl(delta: Float) {
super.updateImpl(delta)
// right click
if (mouseUp) {
clickLatch.latch {
state = !state
(sprite as SheetSpriteAnimation).currentRow = state.toInt()
setWireEmissionAt(0, 0, Vector2(state.toInt().toDouble(), 0.0))
}
}
}
}

View File

@@ -289,8 +289,9 @@ class FixtureSmelterBasic : FixtureBase, CraftingStation {
// manage audio // manage audio
// FIXME this code is also killing the audio played by the other fixture (FixtureFurnaceAndAnvil)
getTrackByAudio(static).let { getTrackByAudio(static).let {
if (it == null || (temperature > 0f && !it.isPlaying)) { if (it == null || (temperature > 0f && !it.isPlaying && !it.playRequested.get())) {
startAudio(static) { startAudio(static) {
it.filters[filterIndex] = Gain(0f) it.filters[filterIndex] = Gain(0f)
} }
@@ -300,12 +301,13 @@ class FixtureSmelterBasic : FixtureBase, CraftingStation {
it.filters[filterIndex] = NullFilter it.filters[filterIndex] = NullFilter
} }
} }
}
getTrackByAudio(static)?.let {
if (it.filters[filterIndex] !is Gain) // just in case...
it.filters[filterIndex] = Gain(0f)
(it.filters[filterIndex] as Gain).gain = (it.maxVolume * temperature * volRand.get()).toFloat() if (it != null) {
if (it.filters[filterIndex] !is Gain) // just in case...
it.filters[filterIndex] = Gain(0f)
(it.filters[filterIndex] as Gain).gain = (it.maxVolume * temperature * volRand.get()).toFloat()
}
} }
} }

View File

@@ -5,6 +5,9 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory.Companion.CAPACITY_MODE_COUNT import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory.Companion.CAPACITY_MODE_COUNT
import net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChest.Companion.MASS
import net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChest.Companion.MAXCAP_MODE
import net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChest.Companion.MAXCAP_NUM
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.ui.* import net.torvald.terrarum.modulebasegame.ui.*
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -12,13 +15,11 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/** /**
* Created by minjaesong on 2019-07-08. * Created by minjaesong on 2019-07-08.
*/ */
internal class FixtureStorageChest : FixtureBase { class FixtureStorageChest : FixtureBase {
constructor() : super( constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1), BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1),
mainUI = UIStorageChest(), mainUI = UIStorageChest(),
inventory = FixtureInventory(40, CAPACITY_MODE_COUNT), inventory = FixtureInventory(MAXCAP_NUM, MAXCAP_MODE),
nameFun = { Lang["ITEM_STORAGE_CHEST"] } nameFun = { Lang["ITEM_STORAGE_CHEST"] }
) { ) {
@@ -36,6 +37,50 @@ internal class FixtureStorageChest : FixtureBase {
actorValue[AVKey.BASEMASS] = MASS actorValue[AVKey.BASEMASS] = MASS
// printStackTrace(this)
}
override fun reload() {
super.reload()
// doing this is required as when things are deserialised, constructor is called, THEN the fields are
// filled in, thus the initialised mainUI has a stale reference;
// we fix it by simply giving a new reference to the mainUI
(mainUI as UIStorageChest).chestInventory = this.inventory!!
(mainUI as UIStorageChest).chestNameFun = this.nameFun
}
companion object {
const val MASS = 2.0
const val MAXCAP_NUM = 40L
val MAXCAP_MODE = CAPACITY_MODE_COUNT
}
}
/**
* Created by minjaesong on 2024-03-02.
*/
class FixtureStorageChestEbony : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1),
mainUI = UIStorageChest(),
inventory = FixtureInventory(MAXCAP_NUM, MAXCAP_MODE),
nameFun = { Lang["ITEM_STORAGE_CHEST"] }
) {
(mainUI as UIStorageChest).chestInventory = this.inventory!!
(mainUI as UIStorageChest).chestNameFun = this.nameFun
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest_2.tga")
setHitboxDimension(TILE_SIZE, TILE_SIZE, 1, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, 18, 18)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = MASS
printStackTrace(this) printStackTrace(this)
} }
@@ -47,8 +92,80 @@ internal class FixtureStorageChest : FixtureBase {
(mainUI as UIStorageChest).chestInventory = this.inventory!! (mainUI as UIStorageChest).chestInventory = this.inventory!!
(mainUI as UIStorageChest).chestNameFun = this.nameFun (mainUI as UIStorageChest).chestNameFun = this.nameFun
} }
}
companion object { /**
const val MASS = 2.0 * Created by minjaesong on 2024-03-02.
*/
class FixtureStorageChestBirch : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1),
mainUI = UIStorageChest(),
inventory = FixtureInventory(MAXCAP_NUM, MAXCAP_MODE),
nameFun = { Lang["ITEM_STORAGE_CHEST"] }
) {
(mainUI as UIStorageChest).chestInventory = this.inventory!!
(mainUI as UIStorageChest).chestNameFun = this.nameFun
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest_3.tga")
setHitboxDimension(TILE_SIZE, TILE_SIZE, 1, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, 18, 18)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = MASS
printStackTrace(this)
}
override fun reload() {
super.reload()
// doing this is required as when things are deserialised, constructor is called, THEN the fields are
// filled in, thus the initialised mainUI has a stale reference;
// we fix it by simply giving a new reference to the mainUI
(mainUI as UIStorageChest).chestInventory = this.inventory!!
(mainUI as UIStorageChest).chestNameFun = this.nameFun
}
}
/**
* Created by minjaesong on 2024-03-02.
*/
class FixtureStorageChestRosewood : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1),
mainUI = UIStorageChest(),
inventory = FixtureInventory(MAXCAP_NUM, MAXCAP_MODE),
nameFun = { Lang["ITEM_STORAGE_CHEST"] }
) {
(mainUI as UIStorageChest).chestInventory = this.inventory!!
(mainUI as UIStorageChest).chestNameFun = this.nameFun
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest_4.tga")
setHitboxDimension(TILE_SIZE, TILE_SIZE, 1, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, 18, 18)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = MASS
printStackTrace(this)
}
override fun reload() {
super.reload()
// doing this is required as when things are deserialised, constructor is called, THEN the fields are
// filled in, thus the initialised mainUI has a stale reference;
// we fix it by simply giving a new reference to the mainUI
(mainUI as UIStorageChest).chestInventory = this.inventory!!
(mainUI as UIStorageChest).chestNameFun = this.nameFun
} }
} }

View File

@@ -0,0 +1,89 @@
package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.TerrarumAppConfiguration
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.ui.UIStorageChest
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2024-03-03.
*/
class FixtureTable : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 2),
nameFun = { Lang["ITEM_TABLE_OAK"] }
) {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/table_1.tga")
setHitboxDimension(2*TILE_SIZE, 2*TILE_SIZE, 0, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, 32, 33)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = 20.0
}
}
/**
* Created by minjaesong on 2024-03-03.
*/
class FixtureTableEbony : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 2),
nameFun = { Lang["ITEM_TABLE_EBONY"] }
) {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/table_2.tga")
setHitboxDimension(2*TILE_SIZE, 2*TILE_SIZE, 0, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, 32, 33)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = 20.0
}
}
/**
* Created by minjaesong on 2024-03-03.
*/
class FixtureTableBirch : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 2),
nameFun = { Lang["ITEM_TABLE_BIRCH"] }
) {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/table_3.tga")
setHitboxDimension(2*TILE_SIZE, 2*TILE_SIZE, 0, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, 32, 33)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = 20.0
}
}
/**
* Created by minjaesong on 2024-03-03.
*/
class FixtureTableRosewood : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 2),
nameFun = { Lang["ITEM_TABLE_ROSEWOOD"] }
) {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/table_4.tga")
setHitboxDimension(2*TILE_SIZE, 2*TILE_SIZE, 0, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, 32, 33)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = 20.0
}
}

View File

@@ -0,0 +1,35 @@
package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.BlockCodex
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.ui.UICrafting
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2024-03-02.
*/
class FixtureWireRollingMill : FixtureBase, CraftingStation {
@Transient override val tags = listOf("wirerollingmill")
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 2, 2),
nameFun = { Lang["ITEM_WIRE_ROLLING_MILL"] },
mainUI = UICrafting(null)
) {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/wire_rolling_mill.tga")
density = BlockCodex[Block.STONE].density.toDouble()
setHitboxDimension(itemImage.texture.width, itemImage.texture.height, 0, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, itemImage.texture.width, itemImage.texture.height)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = 50.0
}
}

View File

@@ -1,16 +1,11 @@
package net.torvald.terrarum.modulebasegame.gameactors package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.BlockCodex import net.torvald.terrarum.BlockCodex
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.ui.UICrafting import net.torvald.terrarum.modulebasegame.ui.UICrafting
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
import net.torvald.terrarum.modulebasegame.ui.UIWallCalendar
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/** /**

View File

@@ -1,26 +0,0 @@
package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.PhysProperties
import net.torvald.terrarum.gameitems.ItemID
/**
* Created by minjaesong on 2016-04-26.
*/
class ItemCarrying : ActorWithBody {
var itemID: ItemID = ""; private set
private constructor()
constructor(itemID: ItemID) : super(RenderOrder.MIDTOP, PhysProperties.IMMOBILE()) {
this.itemID = itemID
}
// just let the solver use AABB; it's cheap but works just enough
init {
}
}

View File

@@ -21,28 +21,31 @@ interface Pocketed {
fun unequipItem(item: GameItem?) { fun unequipItem(item: GameItem?) {
if (item == null) return if (item == null) return
// check equipposition of the given item
if (item.equipPosition == GameItem.EquipPosition.NULL) if (item.equipPosition == GameItem.EquipPosition.NULL)
throw Error("Unequipping the item that cannot be equipped in the first place") throw Error("Unequipping the item that cannot be equipped in the first place")
// check if the actor even has the items
if (!inventory.contains(item)) { if (!inventory.contains(item)) {
//throw Error("Unequipping the item that does not exist in inventory") //throw Error("Unequipping the item that does not exist in inventory")
System.err.println("[Pocketed] Warning -- Unequipping the item that does not exist in inventory") System.err.println("[Pocketed] Warning -- Unequipping the item that does not exist in inventory")
return // just do nothing return // just do nothing
} }
inventory.itemEquipped[item.equipPosition] = null // check if the actor actually have the item equipped
if (inventory.itemEquipped[item.equipPosition] == item.dynamicID) {
inventory.itemEquipped[item.equipPosition] = null
// NOTE: DON'T TOUCH QUICKSLOT HERE // NOTE: DON'T TOUCH QUICKSLOT HERE
// Relevant Actorvalue is NOT being updated on time // Relevant Actorvalue is NOT being updated on time
// They're being safely handled by UIItemInventoryElem*.touchDown() and ActorInventory.remove // They're being safely handled by UIItemInventoryElem*.touchDown() and ActorInventory.remove
item.effectOnUnequip(this as ActorWithBody) item.effectOnUnequip(this as ActorWithBody)
}
} }
fun unequipItem(itemID: ItemID?) { fun unequipItem(itemID: ItemID?) {
itemID?.let { unequipItem(ItemCodex[itemID])
unequipItem(ItemCodex[itemID])
} ?: return
} }
// no need for equipSlot(Int) // no need for equipSlot(Int)
@@ -50,7 +53,13 @@ interface Pocketed {
if (slot < 0 || slot > GameItem.EquipPosition.INDEX_MAX) if (slot < 0 || slot > GameItem.EquipPosition.INDEX_MAX)
throw IllegalArgumentException("Slot index out of range: $slot") throw IllegalArgumentException("Slot index out of range: $slot")
unequipItem(inventory.itemEquipped[slot]) val itemID = inventory.itemEquipped[slot]
if (itemID != null) {
val item = ItemCodex[itemID]!!
inventory.itemEquipped[slot] = null
item.effectOnUnequip(this as ActorWithBody)
}
} }
/** /**

View File

@@ -124,6 +124,8 @@ object AxeCore {
else if (tileprop.hasAllTag(listOf("TREE", "TREETRUNK") + additionalCheckTags)) { else if (tileprop.hasAllTag(listOf("TREE", "TREETRUNK") + additionalCheckTags)) {
val actionInterval = actorvalue.getAsDouble(AVKey.ACTION_INTERVAL)!! val actionInterval = actorvalue.getAsDouble(AVKey.ACTION_INTERVAL)!!
val swingDmgToFrameDmg = delta.toDouble() / actionInterval val swingDmgToFrameDmg = delta.toDouble() / actionInterval
val isLargeTree = tileprop.hasTag("TREELARGE")
val axePowerMult = if (isLargeTree) 0.5f else 1f
if (INGAME.WORLD_UPDATE_TIMER % 11 == (Math.random() * 3).toInt()) { if (INGAME.WORLD_UPDATE_TIMER % 11 == (Math.random() * 3).toInt()) {
PickaxeCore.makeNoiseTileTouching(actor, tile) PickaxeCore.makeNoiseTileTouching(actor, tile)
@@ -131,7 +133,7 @@ object AxeCore {
INGAME.world.inflictTerrainDamage( INGAME.world.inflictTerrainDamage(
x, y, x, y,
Calculate.hatchetPower(actor, item?.material) * swingDmgToFrameDmg, Calculate.hatchetPower(actor, item?.material) * swingDmgToFrameDmg * axePowerMult,
false false
).let { (tileBroken, _) -> ).let { (tileBroken, _) ->
// tile busted // tile busted

View File

@@ -8,6 +8,9 @@ import net.torvald.terrarum.itemproperties.Material
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
/**
* Created by minjaesong on 2021-08-08.
*/
class ItemLogicSignalEmitter(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter") { class ItemLogicSignalEmitter(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter") {
override var dynamicID: ItemID = originalID override var dynamicID: ItemID = originalID

View File

@@ -4,6 +4,9 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.gdx.graphics.Cvec import net.torvald.gdx.graphics.Cvec
import net.torvald.terrarum.BlockCodex import net.torvald.terrarum.BlockCodex
import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
@@ -69,7 +72,17 @@ class ItemTorch(originalID: ItemID) : LightIngredientBase(originalID) {
override fun getLumCol() = BlockCodex[Block.TORCH].getLumCol(0, 0) override fun getLumCol() = BlockCodex[Block.TORCH].getLumCol(0, 0)
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long { override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long {
return BlockBase.blockStartPrimaryUse(actor, this, "basegame:176", delta) val mwx = (Terrarum.mouseX / TILE_SIZE).toInt()
val mwy = (Terrarum.mouseY / TILE_SIZE).toInt()
val wall = BlockCodex[INGAME.world.getTileFromWall(mwx, mwy)]
val terr1 = BlockCodex[INGAME.world.getTileFromTerrain(mwx - 1, mwy)]
val terr2 = BlockCodex[INGAME.world.getTileFromTerrain(mwx, mwy + 1)]
val terr3 = BlockCodex[INGAME.world.getTileFromTerrain(mwx + 1, mwy)]
if (wall.isSolid || terr1.isSolid || terr2.isSolid || terr3.isSolid)
return BlockBase.blockStartPrimaryUse(actor, this, "basegame:176", delta)
else
return -1L
} }
override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) { override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) {

View File

@@ -6,7 +6,7 @@ import net.torvald.terrarum.gameitems.ItemID
class ItemSeedOak(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingOak") { class ItemSeedOak(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingOak") {
override var originalName = "ITEM_SEED_OAK" override var originalName = "ITEM_SEED_OAK"
override var baseMass = 10.0 override var baseMass = 1.0
override val materialId = "OOZE" override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion override val itemImage: TextureRegion
@@ -14,7 +14,7 @@ class ItemSeedOak(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald
} }
class ItemSeedEbony(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingEbony") { class ItemSeedEbony(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingEbony") {
override var originalName = "ITEM_SEED_EBONY" override var originalName = "ITEM_SEED_EBONY"
override var baseMass = 10.0 override var baseMass = 1.0
override val materialId = "OOZE" override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion override val itemImage: TextureRegion
@@ -22,7 +22,7 @@ class ItemSeedEbony(originalID: ItemID) : FixtureItemBase(originalID, "net.torva
} }
class ItemSeedBirch(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingBirch") { class ItemSeedBirch(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingBirch") {
override var originalName = "ITEM_SEED_BIRCH" override var originalName = "ITEM_SEED_BIRCH"
override var baseMass = 10.0 override var baseMass = 1.0
override val materialId = "OOZE" override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion override val itemImage: TextureRegion
@@ -30,7 +30,7 @@ class ItemSeedBirch(originalID: ItemID) : FixtureItemBase(originalID, "net.torva
} }
class ItemSeedRosewood(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingRosewood") { class ItemSeedRosewood(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingRosewood") {
override var originalName = "ITEM_SEED_ROSEWOOD" override var originalName = "ITEM_SEED_ROSEWOOD"
override var baseMass = 10.0 override var baseMass = 1.0
override val materialId = "OOZE" override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion override val itemImage: TextureRegion

View File

@@ -0,0 +1,36 @@
package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
/**
* Created by minjaesong on 2024-03-01.
*/
class ItemSignalBulb(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureSignalBulb") {
override var dynamicID: ItemID = originalID
override var baseMass = FixtureLogicSignalEmitter.MASS
override val canBeDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(9, 3)
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_COPPER_BULB"
override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) {
super.effectWhileEquipped(actor, delta)
(Terrarum.ingame!! as TerrarumIngame).selectedWireRenderClass = "signal"
}
override fun effectOnUnequip(actor: ActorWithBody) {
super.effectOnUnequip(actor)
(Terrarum.ingame!! as TerrarumIngame).selectedWireRenderClass = ""
}
}

View File

@@ -0,0 +1,36 @@
package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
/**
* Created by minjaesong on 2024-03-01.
*/
class ItemSignalSwitchManual(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureSignalSwitchManual") {
override var dynamicID: ItemID = originalID
override var baseMass = FixtureLogicSignalEmitter.MASS
override val canBeDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(8, 3)
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_LOGIC_SIGNAL_SWITCH"
override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) {
super.effectWhileEquipped(actor, delta)
(Terrarum.ingame!! as TerrarumIngame).selectedWireRenderClass = "signal"
}
override fun effectOnUnequip(actor: ActorWithBody) {
super.effectOnUnequip(actor)
(Terrarum.ingame!! as TerrarumIngame).selectedWireRenderClass = ""
}
}

View File

@@ -11,7 +11,6 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch
* Created by minjaesong on 2019-07-08. * Created by minjaesong on 2019-07-08.
*/ */
class ItemStorageChest(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChest") { class ItemStorageChest(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChest") {
override var dynamicID: ItemID = originalID override var dynamicID: ItemID = originalID
override var baseMass = FixtureTikiTorch.MASS override var baseMass = FixtureTikiTorch.MASS
override val canBeDynamic = false override val canBeDynamic = false
@@ -20,5 +19,46 @@ class ItemStorageChest(originalID: ItemID) : FixtureItemBase(originalID, "net.to
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest.tga") get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest.tga")
override var baseToolSize: Double? = baseMass override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_STORAGE_CHEST" override var originalName = "ITEM_STORAGE_CHEST"
}
/**
* Created by minjaesong on 2024-03-02.
*/
class ItemStorageChestEbony(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChestEbony") {
override var dynamicID: ItemID = originalID
override var baseMass = FixtureTikiTorch.MASS
override val canBeDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest_2.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_STORAGE_CHEST"
}
/**
* Created by minjaesong on 2024-03-02.
*/
class ItemStorageChestBirch(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChestBirch") {
override var dynamicID: ItemID = originalID
override var baseMass = FixtureTikiTorch.MASS
override val canBeDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest_3.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_STORAGE_CHEST"
}
/**
* Created by minjaesong on 2024-03-02.
*/
class ItemStorageChestRosewood(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChestRosewood") {
override var dynamicID: ItemID = originalID
override var baseMass = FixtureTikiTorch.MASS
override val canBeDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest_4.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_STORAGE_CHEST"
} }

View File

@@ -0,0 +1,60 @@
package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.gameitems.ItemID
/**
* Created by minjaesong on 2024-03-03.
*/
class ItemTable(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureTable") {
override var dynamicID: ItemID = originalID
override var baseMass = 20.0
override val canBeDynamic = false
override val materialId = "WOOD"
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/table_1.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_TABLE_OAK"
}
/**
* Created by minjaesong on 2024-03-03.
*/
class ItemTableEbony(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureTableEbony") {
override var dynamicID: ItemID = originalID
override var baseMass = 20.0
override val canBeDynamic = false
override val materialId = "WOOD"
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/table_2.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_TABLE_EBONY"
}
/**
* Created by minjaesong on 2024-03-03.
*/
class ItemTableBirch(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureTableBirch") {
override var dynamicID: ItemID = originalID
override var baseMass = 20.0
override val canBeDynamic = false
override val materialId = "WOOD"
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/table_3.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_TABLE_BIRCH"
}
/**
* Created by minjaesong on 2024-03-03.
*/
class ItemTableRosewood(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureTableRosewood") {
override var dynamicID: ItemID = originalID
override var baseMass = 20.0
override val canBeDynamic = false
override val materialId = "WOOD"
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/table_4.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_TABLE_ROSEWOOD"
}

View File

@@ -31,19 +31,11 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
} }
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long = mouseInInteractableRange(actor) { mx, my, mtx, mty -> override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long = mouseInInteractableRange(actor) { mx, my, mtx, mty ->
val (throwPos, throwForce) = getThrowPosAndVector(actor)
val playerCentrePos = actor.centrePosVector
val mousePos = Vector2(mx, my)
val actorPowMult = actor.avStrength / 2000.0
val relativeX = relativeXposition(actor, mousePos)
val relativeY = my - playerCentrePos.y
val powX = relativeX / TILE_SIZED * 3.0 * actorPowMult
val powY = relativeY / TILE_SIZED * 3.0 * actorPowMult
val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody
lobbed.setPosition(playerCentrePos) lobbed.setPositionFromCentrePoint(throwPos)
lobbed.externalV.set(powX, powY) lobbed.externalV.set(throwForce)
setupLobbedActor(lobbed) setupLobbedActor(lobbed)
Terrarum.ingame?.queueActorAddition(lobbed) Terrarum.ingame?.queueActorAddition(lobbed)
@@ -52,6 +44,24 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
1L 1L
} }
}
/**
* @return pair of throwing start position, throwing force
*/
fun getThrowPosAndVector(actor: ActorWithBody): Pair<Vector2, Vector2> {
val playerCentrePos = Vector2(actor.centrePosVector) // make a COPY of the actor.centrePosPoint
val mousePos = Vector2(Terrarum.mouseX, Terrarum.mouseY)
val actorPowMult = actor.avStrength / 2000.0
val relativeX = relativeXposition(actor, mousePos)
val relativeY = mousePos.y - playerCentrePos.y
val powX = relativeX / TILE_SIZED * 3.0 * actorPowMult
val powY = relativeY / TILE_SIZED * 3.0 * actorPowMult
return Pair(playerCentrePos, Vector2(powX, powY))
} }

View File

@@ -0,0 +1,21 @@
package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.gameitems.ItemID
/**
* Created by minjaesong on 2024-03-02.
*/
class ItemWireRollingMill(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureWireRollingMill") {
override var baseMass = 50.0
override val canBeDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/wire_rolling_mill.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_WIRE_ROLLING_MILL"
}

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.WireCodex
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.gameitems.ItemID
@@ -26,6 +27,7 @@ class WirePieceSignalWire(originalID: ItemID, private val atlasID: String, priva
init { init {
equipPosition = GameItem.EquipPosition.HAND_GRIP equipPosition = GameItem.EquipPosition.HAND_GRIP
originalName = "ITEM_WIRE" originalName = "ITEM_WIRE"
tags.addAll(WireCodex[originalID].tags)
} }
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long { override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long {

View File

@@ -1,11 +1,12 @@
package net.torvald.terrarum.modulebasegame.ui package net.torvald.terrarum.modulebasegame.ui
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
interface HasInventory { interface HasInventory {
fun getNegotiator(): InventoryTransactionNegotiator fun getNegotiator(): InventoryTransactionNegotiator
fun getFixtureInventory(): FixtureInventory fun getFixtureInventory(): FixtureInventory
fun getPlayerInventory(): FixtureInventory fun getPlayerInventory(): ActorInventory
} }

View File

@@ -1,593 +1,84 @@
package net.torvald.terrarum.modulebasegame.ui package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.* import net.torvald.terrarum.App
import net.torvald.terrarum.App.* import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.ui.UIItemHorizontalFadeSlide
import net.torvald.terrarum.gameitems.isWall
import net.torvald.terrarum.itemproperties.CraftingCodex
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.CraftingStation
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.listGap
import net.torvald.terrarum.modulebasegame.ui.UITemplateHalfInventory.Companion.INVENTORY_NAME_TEXT_GAP
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.ui.UIItemCatBar.Companion.FILTER_CAT_ALL
import net.torvald.unicode.getKeycapPC
import kotlin.math.ceil
/** /**
* This UI has inventory, but it's just there to display all craftable items and should not be serialised. * Created by minjaesong on 2024-03-02.
*
* Created by minjaesong on 2022-03-10.
*/ */
class UICrafting(val full: UIInventoryFull?) : UICanvas( class UICrafting(val full: UIInventoryFull?) : UICanvas(
toggleKeyLiteral = if (full == null) "control_key_inventory" else null, toggleKeyLiteral = if (full == null) "control_key_inventory" else null,
toggleButtonLiteral = if (full == null) "control_gamepad_start" else null toggleButtonLiteral = if (full == null) "control_gamepad_start" else null
), HasInventory { ) {
override var width = Toolkit.drawWidth override var width = Toolkit.drawWidth
override var height = App.scr.height override var height = App.scr.height
private val playerThings = UITemplateHalfInventory(this, false).also { pt -> internal val transitionalCraftingUI = UICraftingWorkbench(full, this)
pt.itemListTouchDownFun = { gameItem, _, _, _, theButton -> if (gameItem != null) { internal val transitionalTechtreePanel = UITechView(full, this)
val recipe = recipeClicked val transitionPanel = UIItemHorizontalFadeSlide(
val itemID = gameItem.dynamicID this,
(width - UIInventoryFull.internalWidth) / 2,
UIInventoryFull.INVENTORY_CELLS_OFFSET_Y(),
width,
App.scr.height,
0f,
listOf(transitionalCraftingUI, transitionalTechtreePanel),
listOf()
)
private val uis = listOf(transitionalCraftingUI, transitionalTechtreePanel)
// change ingredient used
if (recipe != null) {
// don't rely on highlightedness of the button to determine the item on the button is the selected
// ingredient (because I don't fully trust my code lol)
val targetItemToAlter =
recipe.ingredients.filter { (key, mode) -> // altering recipe doesn't make sense if player selected a recipe that requires no tag-ingredients
val tags = key.split(',')
val wantsWall = tags.contains("WALL")
(mode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.hasAllTags(tags) && (wantsWall == gameItem.originalID.isWall())) // true if (wants wall and is wall) or (wants no wall and is not wall)
}.let {
if (it.size > 1)
println(
"[UICrafting] Your recipe seems to have two similar ingredients defined\n" +
"affected ingredients: ${it.joinToString()}\n" +
"the recipe: ${recipe}"
)
it.firstOrNull()
}
targetItemToAlter?.let { (key, mode) ->
val oldItem = _getItemListIngredients().getInventory().first { (itm, qty) ->
val tags = key.split(',')
val wantsWall = tags.contains("WALL")
(mode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itm]!!.hasAllTags(tags) && (wantsWall == itm.isWall())) // true if (wants wall and is wall) or (wants no wall and is not wall)
}
changeIngredient(recipe, oldItem, itemID)
refreshCraftButtonStatus()
}
}
// show all the items that can be made using this ingredient
else {
itemListCraftable.rebuild(arrayOf(itemID))
pt.itemList.clearForceHighlightList()
pt.itemList.addToForceHighlightList(listOf(itemID))
if (itemListCraftable.craftingRecipes.isEmpty()) {
pt.itemList.clearForceHighlightList()
itemListCraftable.rebuild(FILTER_CAT_ALL)
}
}
}
else {
pt.itemList.clearForceHighlightList()
recipeClicked = null
filterPlayerListUsing(recipeClicked)
highlightCraftingCandidateButton(null)
ingredients.clear()
itemListIngredients.rebuild(FILTER_CAT_ALL)
}}
}
private val catIcons = CommonResourcePool.getAsTextureRegionPack("inventory_category")
internal val itemListCraftable: UIItemCraftingCandidateGrid // might be changed to something else
internal val itemListIngredients: UIItemInventoryItemGrid // this one is definitely not to be changed
private val buttonCraft: UIItemTextButton
private val spinnerCraftCount: UIItemSpinner
private val ingredients = FixtureInventory() // this one is definitely not to be changed
private val negotiator = object : InventoryTransactionNegotiator() {
override fun accept(player: FixtureInventory, fixture: FixtureInventory, item: GameItem, amount: Long) {
// TODO()
}
override fun refund(fixture: FixtureInventory, player: FixtureInventory, item: GameItem, amount: Long) {
// TODO()
}
}
override fun getNegotiator() = negotiator
override fun getFixtureInventory(): FixtureInventory = TODO()
override fun getPlayerInventory(): FixtureInventory = INGAME.actorNowPlaying!!.inventory
private val halfSlotOffset = (UIItemInventoryElemSimple.height + listGap) / 2
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + listGap - halfSlotOffset
private val thisOffsetX2 = thisOffsetX + (listGap + UIItemInventoryElemWide.height) * 7
private val thisXend = thisOffsetX + (listGap + UIItemInventoryElemWide.height) * 13 - listGap
private val thisOffsetY = UIInventoryFull.INVENTORY_CELLS_OFFSET_Y()
private val cellsWidth = (listGap + UIItemInventoryElemWide.height) * 6 - listGap
private val LAST_LINE_IN_GRID = ((UIItemInventoryElemWide.height + listGap) * (UIInventoryFull.CELLS_VRT - 2)) + 22//359 // TEMPORARY VALUE!
private var recipeClicked: CraftingCodex.CraftingRecipe? = null
private val controlHelp: String
get() = if (App.environment == RunningEnvironment.PC)
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
else
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
"$gamepadLabelLEFTRIGHT ${Lang["GAME_OBJECTIVE_MULTIPLIER"]}\u3000 " +
"${App.gamepadLabelWest} ${Lang["GAME_ACTION_CRAFT"]}"
private val oldSelectedItems = ArrayList<ItemID>()
private val craftMult
get() = spinnerCraftCount.value.toLong()
private fun _getItemListPlayer() = playerThings.itemList
private fun _getItemListIngredients() = itemListIngredients
private fun _getItemListCraftables() = itemListCraftable
init {
val craftButtonsY = thisOffsetY + 23 + (UIItemInventoryElemWide.height + listGap) * (UIInventoryFull.CELLS_VRT - 1)
val buttonWidth = (UIItemInventoryElemWide.height + listGap) * 3 - listGap - 2
// ingredient list
itemListIngredients = UIItemInventoryItemGrid(
this,
{ ingredients },
thisOffsetX,
thisOffsetY + LAST_LINE_IN_GRID,
6, 1,
drawScrollOnRightside = false,
drawWallet = false,
hideSidebar = true,
colourTheme = UIItemInventoryCellCommonRes.defaultInventoryCellTheme.copy(
cellHighlightSubCol = Toolkit.Theme.COL_INACTIVE
),
keyDownFun = { _, _, _, _, _ -> },
wheelFun = { _, _, _, _, _, _ -> },
touchDownFun = { gameItem, amount, _, _, _ -> gameItem?.let { gameItem ->
// if the clicked item is craftable one, present its recipe to the player //
CraftingRecipeCodex.getRecipesFor(gameItem.originalID)?.let { recipes ->
// select most viable recipe (completely greedy search)
val player = getPlayerInventory()
// list of [Score, Ingredients, Recipe]
recipes.map { recipe ->
// list of (Item, How many player has, How many the recipe requires)
val items = recipeToIngredientRecord(player, recipe, nearbyCraftingStations)
val score = items.fold(1L) { acc, item ->
(item.howManyPlayerHas).times(16L) + 1L
}
listOf(score, items, recipe)
}.maxByOrNull { it[0] as Long }?.let { (_, items, recipe) ->
val items = items as List<RecipeIngredientRecord>
val recipe = recipe as CraftingCodex.CraftingRecipe
// change selected recipe to mostViableRecipe then update the UIs accordingly
val selectedItems = ArrayList<ItemID>()
resetSpinner()
ingredients.clear()
recipeClicked = recipe
items.forEach {
val itm = it.selectedItem
val qty = it.howManyRecipeWants
selectedItems.add(itm)
ingredients.add(itm, qty)
}
_getItemListPlayer().let {
it.removeFromForceHighlightList(oldSelectedItems)
//filterPlayerListUsing(recipeClicked) // ???
it.addToForceHighlightList(selectedItems)
filterPlayerListUsing(recipeClicked)
}
_getItemListIngredients().rebuild(FILTER_CAT_ALL)
_getItemListCraftables().highlightRecipe(recipeClicked, true)
oldSelectedItems.clear()
oldSelectedItems.addAll(selectedItems)
refreshCraftButtonStatus()
}
}
} }
)
// make sure grid buttons for ingredients do nothing (even if they are hidden!)
itemListIngredients.navRemoCon.listButtonListener = { _,_, -> }
itemListIngredients.navRemoCon.gridButtonListener = { _,_, -> }
itemListIngredients.isCompactMode = true
itemListIngredients.setCustomHighlightRuleSub {
it.item?.let { ingredient ->
return@setCustomHighlightRuleSub getPlayerInventory().searchByID(ingredient.dynamicID)?.let { itemOnPlayer ->
itemOnPlayer.qty * craftMult >= it.amount * craftMult
} == true
}
false
}
// crafting list to the left
itemListCraftable = UIItemCraftingCandidateGrid(
this,
thisOffsetX,
thisOffsetY,
6, UIInventoryFull.CELLS_VRT - 2, // decrease the internal height so that craft/cancel button would fit in
keyDownFun = { _, _, _, _, _ -> },
touchDownFun = { gameItem, amount, _, recipe0, button ->
(recipe0 as? CraftingCodex.CraftingRecipe).let { recipe ->
val selectedItems = ArrayList<ItemID>()
val playerInventory = getPlayerInventory()
ingredients.clear()
recipeClicked = recipe
// printdbg(this, "Recipe selected: $recipe")
recipe?.ingredients?.forEach { ingredient ->
val selectedItem = getItemForIngredient(playerInventory, ingredient)
selectedItems.add(selectedItem)
ingredients.add(selectedItem, ingredient.qty)
}
_getItemListPlayer().removeFromForceHighlightList(oldSelectedItems)
_getItemListPlayer().addToForceHighlightList(selectedItems)
if (recipe != null) _getItemListPlayer().itemPage = 0
filterPlayerListUsing(recipeClicked)
_getItemListIngredients().rebuild(FILTER_CAT_ALL)
highlightCraftingCandidateButton(recipe)
oldSelectedItems.clear()
oldSelectedItems.addAll(selectedItems)
if (recipe == null) {
playerThings.itemList.clearForceHighlightList()
}
refreshCraftButtonStatus()
}
}
)
buttonCraft = UIItemTextButton(this,
{ Lang["GAME_ACTION_CRAFT"] }, thisOffsetX + 3 + buttonWidth + listGap, craftButtonsY, buttonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
spinnerCraftCount = UIItemSpinner(this, thisOffsetX + 1, craftButtonsY, 1, 1, App.getConfigInt("basegame:gameplay_max_crafting"), 1, buttonWidth, numberToTextFunction = {"×\u200A${it.toInt()}"})
spinnerCraftCount.selectionChangeListener = {
itemListIngredients.numberMultiplier = it.toLong()
itemListIngredients.rebuild(FILTER_CAT_ALL)
itemListCraftable.numberMultiplier = it.toLong()
itemListCraftable.rebuild()
refreshCraftButtonStatus()
}
buttonCraft.clickOnceListener = { _,_ ->
getPlayerInventory().let { player -> recipeClicked?.let { recipe ->
// check if player has enough amount of ingredients
val itemCraftable = itemListIngredients.getInventory().all { (itm, qty) ->
(player.searchByID(itm)?.qty ?: -1) >= qty * craftMult
}
if (itemCraftable) {
itemListIngredients.getInventory().forEach { (itm, qty) ->
player.remove(itm, qty * craftMult)
}
player.add(recipe.product, recipe.moq * craftMult)
// reset selection status after a crafting to hide the possible artefact where no-longer-craftable items are still displayed due to ingredient depletion
resetUI() // also clears forcehighlightlist
playerThings.rebuild(FILTER_CAT_ALL)
itemListCraftable.rebuild(FILTER_CAT_ALL)
}
} }
refreshCraftButtonStatus()
}
// make grid mode buttons work together
// itemListCraftable.gridModeButtons[0].clickOnceListener = { _,_ -> setCompact(false) }
// itemListCraftable.gridModeButtons[1].clickOnceListener = { _,_ -> setCompact(true) }
handler.allowESCtoClose = true
val menuButtonTechView = UIItemImageButton(
this, catIcons.get(20, 1),
initialX = itemListCraftable.navRemoCon.posX + 12,
initialY = itemListCraftable.navRemoCon.getIconPosY(-2) - 8,
highlightable = true
).also {
it.clickOnceListener = { _, _ ->
full?.transitionPanel?.setLeftUIto(1)
full?.transitionPanel?.uis?.get(0)?.show()
it.highlighted = false
}
}
val menuButtonCraft = UIItemImageButton(
this, catIcons.get(19, 1),
initialX = itemListCraftable.navRemoCon.posX + 12,
initialY = itemListCraftable.navRemoCon.getIconPosY(-1) - 8,
activeCol = Toolkit.Theme.COL_SELECTED,
inactiveCol = Toolkit.Theme.COL_SELECTED,
highlightable = true
)
addUIitem(itemListCraftable)
addUIitem(itemListIngredients)
addUIitem(playerThings)
addUIitem(spinnerCraftCount)
addUIitem(buttonCraft)
// temporarily disabled for 0.4 release
if (TerrarumAppConfiguration.VERSION_RAW >= 0x0000_000005_000000) {
addUIitem(menuButtonCraft)
addUIitem(menuButtonTechView)
}
}
private fun filterPlayerListUsing(recipe: CraftingCodex.CraftingRecipe?) {
if (recipe == null)
playerThings.rebuild(FILTER_CAT_ALL)
else {
val items = recipe.ingredients.flatMap {
getItemCandidatesForIngredient(getPlayerInventory(), it).map { it.itm }
}.sorted()
val filterFun = { pair: InventoryPair ->
items.binarySearch(pair.itm) >= 0
}
playerThings.rebuild(filterFun, recipe.product)
}
}
var nearbyCraftingStations = emptyList<String>(); protected set
fun getCraftingStationsWithinReach(): List<String> {
val reach = 2 * INGAME.actorNowPlaying!!.actorValue.getAsDouble(AVKey.REACH)!! * (INGAME.actorNowPlaying!!.actorValue.getAsDouble(AVKey.REACHBUFF) ?: 1.0) * INGAME.actorNowPlaying!!.scale
val nearbyCraftingStations = INGAME.findKNearestActors(INGAME.actorNowPlaying!!, 256) {
it is CraftingStation && (distBetweenActors(it, INGAME.actorNowPlaying!!) < reach)
}
return nearbyCraftingStations.flatMap { (it.get() as CraftingStation).tags }
}
private fun changeIngredient(recipe: CraftingCodex.CraftingRecipe?, old: InventoryPair, new: ItemID) {
playerThings.itemList.removeFromForceHighlightList(oldSelectedItems)
oldSelectedItems.remove(old.itm)
oldSelectedItems.add(new)
playerThings.itemList.addToForceHighlightList(oldSelectedItems)
playerThings.itemList.itemPage = 0
filterPlayerListUsing(recipe)
// change highlight status of itemListIngredients
itemListIngredients.getInventory().let {
val amount = old.qty
it.remove(old.itm, amount)
it.add(new, amount)
}
itemListIngredients.rebuild(FILTER_CAT_ALL)
}
private fun highlightCraftingCandidateButton(recipe: CraftingCodex.CraftingRecipe?) { // a proxy function
itemListCraftable.highlightRecipe(recipe)
itemListCraftable.rebuild(FILTER_CAT_ALL)
}
/**
* Updates Craft! button so that the button is correctly highlighted
*/
fun refreshCraftButtonStatus() {
val itemCraftable = if (itemListIngredients.getInventory().totalUniqueCount < 1) false
else getPlayerInventory().let { player ->
// check if player has enough amount of ingredients
itemListIngredients.getInventory().all { (itm, qty) ->
(player.searchByID(itm)?.qty ?: -1) >= qty * craftMult
}
}
buttonCraft.isEnabled = itemCraftable
}
// reset whatever player has selected to null and bring UI to its initial state
fun resetUI() { fun resetUI() {
// reset spinner transitionalCraftingUI.resetUI()
resetSpinner() transitionalTechtreePanel.resetUI()
// reset selected recipe status
recipeClicked = null
filterPlayerListUsing(recipeClicked)
highlightCraftingCandidateButton(null)
ingredients.clear()
playerThings.itemList.clearForceHighlightList()
itemListIngredients.rebuild(FILTER_CAT_ALL)
// reset scroll
itemListCraftable.itemPage = 0
playerThings.itemList.itemPage = 0
refreshCraftButtonStatus()
} }
private fun resetSpinner() { fun showCraftingUI() {
spinnerCraftCount.resetToSmallest() transitionPanel.setLeftUIto(0)
itemListIngredients.numberMultiplier = 1L transitionalCraftingUI.show()
itemListCraftable.numberMultiplier = 1L
} }
private var openingClickLatched = false fun showTechViewUI() {
transitionPanel.setLeftUIto(1)
override fun show() { transitionalTechtreePanel.show()
nearbyCraftingStations = getCraftingStationsWithinReach()
// printdbg(this, "Nearby crafting stations: $nearbyCraftingStations")
playerThings.setGetInventoryFun { INGAME.actorNowPlaying!!.inventory }
itemListUpdate()
openingClickLatched = Terrarum.mouseDown
tooltipShowing.clear()
INGAME.setTooltipMessage(null)
resetUI()
}
private var encumbrancePerc = 0f
private fun itemListUpdate() {
// let itemlists be sorted
itemListCraftable.rebuild()
playerThings.rebuild(FILTER_CAT_ALL)
encumbrancePerc = getPlayerInventory().let {
it.capacity.toFloat() / it.maxCapacity
}
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
if (!openingClickLatched) {
return super.touchDown(screenX, screenY, pointer, button)
}
return false
} }
override fun updateImpl(delta: Float) { override fun updateImpl(delta: Float) {
// NO super.update due to an infinite recursion uiItems.forEach { it.update(delta) }
this.uiItems.forEach { it.update(delta) }
if (openingClickLatched && !Terrarum.mouseDown) openingClickLatched = false // copy transition of parent (UIItemHorizontalFadeSlide) to this (also UIItemHorizontalFadeSlide)
full?.let { full ->
uis.forEach {
it.posX = full.transitionPanel.getOffX(0)
it.opacity = full.transitionPanel.getOpacity(0)
}
}
} }
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) { override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
// NO super.render due to an infinite recursion if (full == null) {
this.uiItems.forEach { it.render(frameDelta, batch, camera) } UIInventoryFull.drawBackground(batch, opacity)
batch.color = Color.WHITE
// text label for two inventory grids
val craftingLabel = Lang["GAME_CRAFTING"]
val ingredientsLabel = Lang["GAME_INVENTORY_INGREDIENTS"]
App.fontGame.draw(batch, craftingLabel, thisOffsetX + (cellsWidth - App.fontGame.getWidth(craftingLabel)) / 2, thisOffsetY - INVENTORY_NAME_TEXT_GAP)
App.fontGame.draw(batch, ingredientsLabel, thisOffsetX + (cellsWidth - App.fontGame.getWidth(ingredientsLabel)) / 2, thisOffsetY + LAST_LINE_IN_GRID - INVENTORY_NAME_TEXT_GAP)
// control hints
val controlHintXPos = thisOffsetX + 2f
blendNormalStraightAlpha(batch)
App.fontGame.draw(batch, controlHelp, controlHintXPos, UIInventoryFull.yEnd - 20)
if (INGAME.actorNowPlaying != null) {
//draw player encumb
val encumbBarXPos = thisXend - UIInventoryCells.weightBarWidth + 36
val encumbBarYPos = UIInventoryFull.yEnd - 20 + 3f
UIInventoryCells.drawEncumbranceBar(batch, encumbBarXPos, encumbBarYPos, encumbrancePerc, INGAME.actorNowPlaying!!.inventory)
} }
uiItems.forEach { it.render(frameDelta, batch, camera) }
blendNormalStraightAlpha(batch)
} }
override fun doOpening(delta: Float) {
super.doOpening(delta)
INGAME.setTooltipMessage(null)
}
override fun doClosing(delta: Float) {
super.doClosing(delta)
INGAME.setTooltipMessage(null)
}
override fun endOpening(delta: Float) {
super.endOpening(delta)
tooltipShowing.clear()
INGAME.setTooltipMessage(null) // required!
}
override fun endClosing(delta: Float) {
super.endClosing(delta)
resetUI()
tooltipShowing.clear()
INGAME.setTooltipMessage(null) // required!
}
override fun dispose() { override fun dispose() {
transitionPanel.dispose()
} }
companion object { init {
data class RecipeIngredientRecord( addUIitem(transitionPanel)
val selectedItem: ItemID, }
val howManyPlayerHas: Long,
val howManyRecipeWants: Long,
val craftingStationAvailable: Boolean,
)
fun getItemCandidatesForIngredient(inventory: FixtureInventory, ingredient: CraftingCodex.CraftingIngredients): List<InventoryPair> { override fun setPosition(x: Int, y: Int) {
return if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { transitionalCraftingUI.setPosition(x, y)
val tags = ingredient.key.split(',') transitionalTechtreePanel.setPosition(x, y)
val wantsWall = tags.contains("WALL")
// If the player has the required item, use it; otherwise, will take an item from the ItemCodex
inventory.filter { (itm, qty) ->
ItemCodex[itm]?.hasAllTags(tags) == true && qty >= ingredient.qty && (wantsWall == itm.isWall()) // true if (wants wall and is wall) or (wants no wall and is not wall)
}
}
else {
listOf(InventoryPair(ingredient.key, -1))
}
}
fun getItemForIngredient(inventory: FixtureInventory, ingredient: CraftingCodex.CraftingIngredients): ItemID {
val candidate = getItemCandidatesForIngredient(inventory, ingredient)
return if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) {
candidate.maxByOrNull { it.qty }?.itm ?: (
(ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?:
throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed (ingredient: $ingredient)")
)
}
else {
ingredient.key
}
}
/**
* For each ingredient of the recipe, returns list of (ingredient, how many the player has the ingredient, how many the recipe wants)
*/
fun recipeToIngredientRecord(inventory: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List<String>): List<RecipeIngredientRecord> {
val hasStation = if (recipe.workbench.isBlank()) true else nearbyCraftingStations.containsAll(recipe.workbench.split(','))
return recipe.ingredients.map { ingredient ->
val selectedItem = getItemForIngredient(inventory, ingredient)
val howManyPlayerHas = inventory.searchByID(selectedItem)?.qty ?: 0L
val howManyTheRecipeWants = ingredient.qty
RecipeIngredientRecord(selectedItem, howManyPlayerHas, howManyTheRecipeWants, hasStation)
}
}
} }
} }

View File

@@ -0,0 +1,600 @@
package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.*
import net.torvald.terrarum.App.*
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameitems.isWall
import net.torvald.terrarum.itemproperties.CraftingCodex
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.CraftingStation
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.listGap
import net.torvald.terrarum.modulebasegame.ui.UITemplateHalfInventory.Companion.INVENTORY_NAME_TEXT_GAP
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.ui.UIItemCatBar.Companion.FILTER_CAT_ALL
import net.torvald.unicode.getKeycapPC
/**
* This UI has inventory, but it's just there to display all craftable items and should not be serialised.
*
* Created by minjaesong on 2022-03-10.
*/
class UICraftingWorkbench(val inventoryUI: UIInventoryFull?, val parentContainer: UICrafting) : UICanvas(
toggleKeyLiteral = if (inventoryUI == null) "control_key_inventory" else null,
toggleButtonLiteral = if (inventoryUI == null) "control_gamepad_start" else null
), HasInventory {
override var width = Toolkit.drawWidth
override var height = App.scr.height
private val playerThings = UITemplateHalfInventory(this, false).also { pt ->
pt.itemListTouchDownFun = { gameItem, _, _, _, theButton -> if (gameItem != null) {
val recipe = recipeClicked
val itemID = gameItem.dynamicID
// change ingredient used
if (recipe != null) {
// don't rely on highlightedness of the button to determine the item on the button is the selected
// ingredient (because I don't fully trust my code lol)
val targetItemToAlter =
recipe.ingredients.filter { (key, mode) -> // altering recipe doesn't make sense if player selected a recipe that requires no tag-ingredients
val tags = key.split(',')
val wantsWall = tags.contains("WALL")
(mode == CraftingCodex.CraftingItemKeyMode.TAG && gameItem.hasAllTags(tags) && (wantsWall == gameItem.originalID.isWall())) // true if (wants wall and is wall) or (wants no wall and is not wall)
}.let {
if (it.size > 1)
println(
"[UICrafting] Your recipe seems to have two similar ingredients defined\n" +
"affected ingredients: ${it.joinToString()}\n" +
"the recipe: ${recipe}"
)
it.firstOrNull()
}
targetItemToAlter?.let { (key, mode) ->
val oldItem = _getItemListIngredients().getInventory().first { (itm, qty) ->
val tags = key.split(',')
val wantsWall = tags.contains("WALL")
(mode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itm]!!.hasAllTags(tags) && (wantsWall == itm.isWall())) // true if (wants wall and is wall) or (wants no wall and is not wall)
}
changeIngredient(recipe, oldItem, itemID)
refreshCraftButtonStatus()
}
}
// show all the items that can be made using this ingredient
else {
itemListCraftable.rebuild(arrayOf(itemID))
pt.itemList.clearForceHighlightList()
pt.itemList.addToForceHighlightList(listOf(itemID))
if (itemListCraftable.craftingRecipes.isEmpty()) {
pt.itemList.clearForceHighlightList()
itemListCraftable.rebuild(FILTER_CAT_ALL)
}
}
}
else {
pt.itemList.clearForceHighlightList()
recipeClicked = null
filterPlayerListUsing(recipeClicked)
highlightCraftingCandidateButton(null)
ingredients.clear()
itemListIngredients.rebuild(FILTER_CAT_ALL)
}}
}
private val catIcons = CommonResourcePool.getAsTextureRegionPack("inventory_category")
internal val itemListCraftable: UIItemCraftingCandidateGrid // might be changed to something else
internal val itemListIngredients: UIItemInventoryItemGrid // this one is definitely not to be changed
private val buttonCraft: UIItemTextButton
private val spinnerCraftCount: UIItemSpinner
private val ingredients = FixtureInventory() // this one is definitely not to be changed
private val negotiator = object : InventoryTransactionNegotiator() {
override fun accept(player: FixtureInventory, fixture: FixtureInventory, item: GameItem, amount: Long) {
// TODO()
}
override fun refund(fixture: FixtureInventory, player: FixtureInventory, item: GameItem, amount: Long) {
// TODO()
}
}
override fun getNegotiator() = negotiator
override fun getFixtureInventory(): FixtureInventory = TODO()
override fun getPlayerInventory(): ActorInventory = INGAME.actorNowPlaying!!.inventory
private val halfSlotOffset = (UIItemInventoryElemSimple.height + listGap) / 2
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + listGap - halfSlotOffset
private val thisOffsetX2 = thisOffsetX + (listGap + UIItemInventoryElemWide.height) * 7
private val thisXend = thisOffsetX + (listGap + UIItemInventoryElemWide.height) * 13 - listGap
private val thisOffsetY = UIInventoryFull.INVENTORY_CELLS_OFFSET_Y()
private val cellsWidth = (listGap + UIItemInventoryElemWide.height) * 6 - listGap
private val LAST_LINE_IN_GRID = ((UIItemInventoryElemWide.height + listGap) * (UIInventoryFull.CELLS_VRT - 2)) + 22//359 // TEMPORARY VALUE!
private var recipeClicked: CraftingCodex.CraftingRecipe? = null
private val controlHelp: String
get() = if (App.environment == RunningEnvironment.PC)
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
else
"$gamepadLabelStart ${Lang["GAME_ACTION_CLOSE"]}\u3000 " +
"$gamepadLabelLEFTRIGHT ${Lang["GAME_OBJECTIVE_MULTIPLIER"]}\u3000 " +
"${App.gamepadLabelWest} ${Lang["GAME_ACTION_CRAFT"]}"
private val oldSelectedItems = ArrayList<ItemID>()
private val craftMult
get() = spinnerCraftCount.value.toLong()
private fun _getItemListPlayer() = playerThings.itemList
private fun _getItemListIngredients() = itemListIngredients
private fun _getItemListCraftables() = itemListCraftable
init {
val craftButtonsY = thisOffsetY + 23 + (UIItemInventoryElemWide.height + listGap) * (UIInventoryFull.CELLS_VRT - 1)
val buttonWidth = (UIItemInventoryElemWide.height + listGap) * 3 - listGap - 2
// ingredient list
itemListIngredients = UIItemInventoryItemGrid(
this,
{ ingredients },
thisOffsetX,
thisOffsetY + LAST_LINE_IN_GRID,
6, 1,
drawScrollOnRightside = false,
drawWallet = false,
hideSidebar = true,
colourTheme = UIItemInventoryCellCommonRes.defaultInventoryCellTheme.copy(
cellHighlightSubCol = Toolkit.Theme.COL_INACTIVE
),
keyDownFun = { _, _, _, _, _ -> },
wheelFun = { _, _, _, _, _, _ -> },
touchDownFun = { gameItem, amount, _, _, _ -> gameItem?.let { gameItem ->
// if the clicked item is craftable one, present its recipe to the player //
CraftingRecipeCodex.getRecipesFor(gameItem.originalID)?.let { recipes ->
// select most viable recipe (completely greedy search)
val player = getPlayerInventory()
// list of [Score, Ingredients, Recipe]
recipes.map { recipe ->
// list of (Item, How many player has, How many the recipe requires)
val items = recipeToIngredientRecord(player, recipe, nearbyCraftingStations)
val score = items.fold(1L) { acc, item ->
(item.howManyPlayerHas).times(16L) + 1L
}
listOf(score, items, recipe)
}.maxByOrNull { it[0] as Long }?.let { (_, items, recipe) ->
val items = items as List<RecipeIngredientRecord>
val recipe = recipe as CraftingCodex.CraftingRecipe
// change selected recipe to mostViableRecipe then update the UIs accordingly
val selectedItems = ArrayList<ItemID>()
resetSpinner()
ingredients.clear()
recipeClicked = recipe
items.forEach {
val itm = it.selectedItem
val qty = it.howManyRecipeWants
selectedItems.add(itm)
ingredients.add(itm, qty)
}
_getItemListPlayer().let {
it.removeFromForceHighlightList(oldSelectedItems)
//filterPlayerListUsing(recipeClicked) // ???
it.addToForceHighlightList(selectedItems)
filterPlayerListUsing(recipeClicked)
}
_getItemListIngredients().rebuild(FILTER_CAT_ALL)
_getItemListCraftables().highlightRecipe(recipeClicked, true)
oldSelectedItems.clear()
oldSelectedItems.addAll(selectedItems)
refreshCraftButtonStatus()
}
}
} }
)
// make sure grid buttons for ingredients do nothing (even if they are hidden!)
itemListIngredients.navRemoCon.listButtonListener = { _,_, -> }
itemListIngredients.navRemoCon.gridButtonListener = { _,_, -> }
itemListIngredients.isCompactMode = true
itemListIngredients.setCustomHighlightRuleSub {
it.item?.let { ingredient ->
return@setCustomHighlightRuleSub getPlayerInventory().searchByID(ingredient.dynamicID)?.let { itemOnPlayer ->
itemOnPlayer.qty * craftMult >= it.amount * craftMult
} == true
}
false
}
// crafting list to the left
itemListCraftable = UIItemCraftingCandidateGrid(
this,
thisOffsetX,
thisOffsetY,
6, UIInventoryFull.CELLS_VRT - 2, // decrease the internal height so that craft/cancel button would fit in
keyDownFun = { _, _, _, _, _ -> },
touchDownFun = { gameItem, amount, _, recipe0, button ->
(recipe0 as? CraftingCodex.CraftingRecipe).let { recipe ->
val selectedItems = ArrayList<ItemID>()
val playerInventory = getPlayerInventory()
ingredients.clear()
recipeClicked = recipe
// printdbg(this, "Recipe selected: $recipe")
recipe?.ingredients?.forEach { ingredient ->
val selectedItem = resolveIngredientKey(playerInventory, ingredient, recipe.product)
selectedItems.add(selectedItem)
ingredients.add(selectedItem, ingredient.qty)
}
_getItemListPlayer().removeFromForceHighlightList(oldSelectedItems)
_getItemListPlayer().addToForceHighlightList(selectedItems)
if (recipe != null) _getItemListPlayer().itemPage = 0
filterPlayerListUsing(recipeClicked)
_getItemListIngredients().rebuild(FILTER_CAT_ALL)
highlightCraftingCandidateButton(recipe)
oldSelectedItems.clear()
oldSelectedItems.addAll(selectedItems)
if (recipe == null) {
playerThings.itemList.clearForceHighlightList()
}
refreshCraftButtonStatus()
}
}
)
buttonCraft = UIItemTextButton(this,
{ Lang["GAME_ACTION_CRAFT"] }, thisOffsetX + 3 + buttonWidth + listGap, craftButtonsY, buttonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
spinnerCraftCount = UIItemSpinner(this, thisOffsetX + 1, craftButtonsY, 1, 1, App.getConfigInt("basegame:gameplay_max_crafting"), 1, buttonWidth, numberToTextFunction = {"×\u200A${it.toInt()}"})
spinnerCraftCount.selectionChangeListener = {
itemListIngredients.numberMultiplier = it.toLong()
itemListIngredients.rebuild(FILTER_CAT_ALL)
itemListCraftable.numberMultiplier = it.toLong()
itemListCraftable.rebuild()
refreshCraftButtonStatus()
}
buttonCraft.clickOnceListener = { _,_ ->
getPlayerInventory().let { player -> recipeClicked?.let { recipe ->
// check if player has enough amount of ingredients
val itemCraftable = itemListIngredients.getInventory().all { (itm, qty) ->
(player.searchByID(itm)?.qty ?: -1) >= qty * craftMult
}
if (itemCraftable) {
val itemEquippedBefore = player.itemEquipped[GameItem.EquipPosition.HAND_GRIP]
itemListIngredients.getInventory().forEach { (itm, qty) ->
player.remove(itm, qty * craftMult)
}
player.add(recipe.product, recipe.moq * craftMult)
// reset selection status after a crafting to hide the possible artefact where no-longer-craftable items are still displayed due to ingredient depletion
resetUI() // also clears forcehighlightlist
playerThings.rebuild(FILTER_CAT_ALL)
itemListCraftable.rebuild(FILTER_CAT_ALL)
// preserve equipped item
if (itemEquippedBefore != null && player.searchByID(itemEquippedBefore) != null) {
player.itemEquipped[GameItem.EquipPosition.HAND_GRIP] = itemEquippedBefore
}
}
} }
refreshCraftButtonStatus()
}
// make grid mode buttons work together
// itemListCraftable.gridModeButtons[0].clickOnceListener = { _,_ -> setCompact(false) }
// itemListCraftable.gridModeButtons[1].clickOnceListener = { _,_ -> setCompact(true) }
handler.allowESCtoClose = true
val menuButtonTechView = UIItemImageButton(
this, catIcons.get(20, 1),
initialX = itemListCraftable.navRemoCon.posX + 12,
initialY = itemListCraftable.navRemoCon.getIconPosY(-2) - 8,
highlightable = true
).also {
it.clickOnceListener = { _, _ ->
parentContainer.showTechViewUI()
it.highlighted = false
}
}
val menuButtonCraft = UIItemImageButton(
this, catIcons.get(19, 1),
initialX = itemListCraftable.navRemoCon.posX + 12,
initialY = itemListCraftable.navRemoCon.getIconPosY(-1) - 8,
activeCol = Toolkit.Theme.COL_SELECTED,
inactiveCol = Toolkit.Theme.COL_SELECTED,
highlightable = true
)
addUIitem(itemListCraftable)
addUIitem(itemListIngredients)
addUIitem(playerThings)
addUIitem(spinnerCraftCount)
addUIitem(buttonCraft)
// temporarily disabled for 0.4 release
if (TerrarumAppConfiguration.VERSION_RAW >= 0x0000_000005_000000) {
addUIitem(menuButtonCraft)
addUIitem(menuButtonTechView)
}
}
private fun filterPlayerListUsing(recipe: CraftingCodex.CraftingRecipe?) {
if (recipe == null)
playerThings.rebuild(FILTER_CAT_ALL)
else {
val items = recipe.ingredients.flatMap {
getItemCandidatesForIngredient(getPlayerInventory(), it).map { it.itm }
}.filter { it != recipe.product }.sorted() // filter out the product itself from the ingredient
val filterFun = { pair: InventoryPair ->
items.binarySearch(pair.itm) >= 0
}
playerThings.rebuild(filterFun, recipe.product)
}
}
var nearbyCraftingStations = emptyList<String>(); protected set
fun getCraftingStationsWithinReach(): List<String> {
val reach = 2 * INGAME.actorNowPlaying!!.actorValue.getAsDouble(AVKey.REACH)!! * (INGAME.actorNowPlaying!!.actorValue.getAsDouble(AVKey.REACHBUFF) ?: 1.0) * INGAME.actorNowPlaying!!.scale
val nearbyCraftingStations = INGAME.findKNearestActors(INGAME.actorNowPlaying!!, 256) {
it is CraftingStation && (distBetweenActors(it, INGAME.actorNowPlaying!!) < reach)
}
return nearbyCraftingStations.flatMap { (it.get() as CraftingStation).tags }
}
private fun changeIngredient(recipe: CraftingCodex.CraftingRecipe?, old: InventoryPair, new: ItemID) {
playerThings.itemList.removeFromForceHighlightList(oldSelectedItems)
oldSelectedItems.remove(old.itm)
oldSelectedItems.add(new)
playerThings.itemList.addToForceHighlightList(oldSelectedItems)
playerThings.itemList.itemPage = 0
filterPlayerListUsing(recipe)
// change highlight status of itemListIngredients
itemListIngredients.getInventory().let {
val amount = old.qty
it.remove(old.itm, amount)
it.add(new, amount)
}
itemListIngredients.rebuild(FILTER_CAT_ALL)
}
private fun highlightCraftingCandidateButton(recipe: CraftingCodex.CraftingRecipe?) { // a proxy function
itemListCraftable.highlightRecipe(recipe)
itemListCraftable.rebuild(FILTER_CAT_ALL)
}
/**
* Updates Craft! button so that the button is correctly highlighted
*/
fun refreshCraftButtonStatus() {
val itemCraftable = if (itemListIngredients.getInventory().totalUniqueCount < 1) false
else getPlayerInventory().let { player ->
// check if player has enough amount of ingredients
itemListIngredients.getInventory().all { (itm, qty) ->
(player.searchByID(itm)?.qty ?: -1) >= qty * craftMult
}
}
buttonCraft.isEnabled = itemCraftable
}
// reset whatever player has selected to null and bring UI to its initial state
fun resetUI() {
// reset spinner
resetSpinner()
// reset selected recipe status
recipeClicked = null
filterPlayerListUsing(recipeClicked)
highlightCraftingCandidateButton(null)
ingredients.clear()
playerThings.itemList.clearForceHighlightList()
itemListIngredients.rebuild(FILTER_CAT_ALL)
// reset scroll
itemListCraftable.itemPage = 0
playerThings.itemList.itemPage = 0
refreshCraftButtonStatus()
}
private fun resetSpinner() {
spinnerCraftCount.resetToSmallest()
itemListIngredients.numberMultiplier = 1L
itemListCraftable.numberMultiplier = 1L
}
private var openingClickLatched = false
override fun show() {
nearbyCraftingStations = getCraftingStationsWithinReach()
// printdbg(this, "Nearby crafting stations: $nearbyCraftingStations")
playerThings.setGetInventoryFun { INGAME.actorNowPlaying!!.inventory }
itemListUpdate()
openingClickLatched = Terrarum.mouseDown
tooltipShowing.clear()
INGAME.setTooltipMessage(null)
resetUI()
}
private var encumbrancePerc = 0f
private fun itemListUpdate() {
// let itemlists be sorted
itemListCraftable.rebuild()
playerThings.rebuild(FILTER_CAT_ALL)
encumbrancePerc = getPlayerInventory().encumberment.toFloat()
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
if (!openingClickLatched) {
return super.touchDown(screenX, screenY, pointer, button)
}
return false
}
override fun updateImpl(delta: Float) {
// NO super.update due to an infinite recursion
this.uiItems.forEach { it.update(delta) }
if (openingClickLatched && !Terrarum.mouseDown) openingClickLatched = false
}
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
// NO super.render due to an infinite recursion
this.uiItems.forEach { it.render(frameDelta, batch, camera) }
batch.color = Color.WHITE
// text label for two inventory grids
val craftingLabel = Lang["GAME_CRAFTING"]
val ingredientsLabel = Lang["GAME_INVENTORY_INGREDIENTS"]
App.fontGame.draw(batch, craftingLabel, thisOffsetX + (cellsWidth - App.fontGame.getWidth(craftingLabel)) / 2, thisOffsetY - INVENTORY_NAME_TEXT_GAP)
App.fontGame.draw(batch, ingredientsLabel, thisOffsetX + (cellsWidth - App.fontGame.getWidth(ingredientsLabel)) / 2, thisOffsetY + LAST_LINE_IN_GRID - INVENTORY_NAME_TEXT_GAP)
// control hints
val controlHintXPos = thisOffsetX + 2f
blendNormalStraightAlpha(batch)
App.fontGame.draw(batch, controlHelp, controlHintXPos, UIInventoryFull.yEnd - 20)
if (INGAME.actorNowPlaying != null) {
//draw player encumb
val encumbBarXPos = thisXend - UIInventoryCells.weightBarWidth + 36
val encumbBarYPos = UIInventoryFull.yEnd - 20 + 3f
UIInventoryCells.drawEncumbranceBar(batch, encumbBarXPos, encumbBarYPos, encumbrancePerc, INGAME.actorNowPlaying!!.inventory)
}
blendNormalStraightAlpha(batch)
}
override fun doOpening(delta: Float) {
super.doOpening(delta)
INGAME.setTooltipMessage(null)
}
override fun doClosing(delta: Float) {
super.doClosing(delta)
INGAME.setTooltipMessage(null)
}
override fun endOpening(delta: Float) {
super.endOpening(delta)
tooltipShowing.clear()
INGAME.setTooltipMessage(null) // required!
}
override fun endClosing(delta: Float) {
super.endClosing(delta)
resetUI()
tooltipShowing.clear()
INGAME.setTooltipMessage(null) // required!
}
override fun dispose() {
}
companion object {
data class RecipeIngredientRecord(
val selectedItem: ItemID,
val howManyPlayerHas: Long,
val howManyRecipeWants: Long,
val craftingStationAvailable: Boolean,
)
fun getItemCandidatesForIngredient(inventory: FixtureInventory, ingredient: CraftingCodex.CraftingIngredients): List<InventoryPair> {
return if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) {
val tags = ingredient.key.split(',')
val wantsWall = tags.contains("WALL")
// If the player has the required item, use it; otherwise, will take an item from the ItemCodex
inventory.filter { (itm, qty) ->
ItemCodex[itm]?.hasAllTags(tags) == true && qty >= ingredient.qty && (wantsWall == itm.isWall()) // true if (wants wall and is wall) or (wants no wall and is not wall)
}
}
else {
listOf(InventoryPair(ingredient.key, -1))
}
}
fun resolveIngredientKey(inventory: FixtureInventory, ingredient: CraftingCodex.CraftingIngredients, product: ItemID): ItemID {
val candidate = getItemCandidatesForIngredient(inventory, ingredient).filter { it.itm != product }
// printdbg(this, "resolveIngredientKey product=$product, candidate=$candidate")
return if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) {
// filter out the product itself from the ingredient
candidate.maxByOrNull { it.qty }?.itm ?: (
(ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?:
throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed (ingredient: $ingredient)")
)
}
else {
ingredient.key
}
}
/**
* For each ingredient of the recipe, returns list of (ingredient, how many the player has the ingredient, how many the recipe wants)
*/
fun recipeToIngredientRecord(inventory: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List<String>): List<RecipeIngredientRecord> {
val hasStation = if (recipe.workbench.isBlank()) true else nearbyCraftingStations.containsAll(recipe.workbench.split(','))
return recipe.ingredients.map { ingredient ->
val selectedItem = resolveIngredientKey(inventory, ingredient, recipe.product)
val howManyPlayerHas = inventory.searchByID(selectedItem)?.qty ?: 0L
val howManyTheRecipeWants = ingredient.qty
RecipeIngredientRecord(selectedItem, howManyPlayerHas, howManyTheRecipeWants, hasStation)
}
}
}
}

View File

@@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.DroppedItem import net.torvald.terrarum.modulebasegame.gameactors.DroppedItem
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELLS_HOR import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELLS_HOR
@@ -36,7 +37,7 @@ internal class UIInventoryCells(
val weightBarWidth = UIItemInventoryElemSimple.height * 2f + UIItemInventoryItemGrid.listGap val weightBarWidth = UIItemInventoryElemSimple.height * 2f + UIItemInventoryItemGrid.listGap
// var encumbBarYPos = (App.scr.height + internalHeight).div(2) - 20 + 3f // var encumbBarYPos = (App.scr.height + internalHeight).div(2) - 20 + 3f
fun drawEncumbranceBar(batch: SpriteBatch, encumbBarXPos: Float, encumbBarYPos: Float, encumbrancePerc: Float, actorInventory: FixtureInventory) { fun drawEncumbranceBar(batch: SpriteBatch, encumbBarXPos: Float, encumbBarYPos: Float, encumbrancePerc: Float, actorInventory: ActorInventory) {
//draw player encumb //draw player encumb
// encumbrance meter // encumbrance meter
val encumbranceText = Lang["GAME_INVENTORY_ENCUMBRANCE"] val encumbranceText = Lang["GAME_INVENTORY_ENCUMBRANCE"]
@@ -75,7 +76,7 @@ internal class UIInventoryCells(
else else
"${(actorInventory.capacity * 100L).toLong() / 100.0}" "${(actorInventory.capacity * 100L).toLong() / 100.0}"
INGAME.setTooltipMessage("$capaStr/${actorInventory.maxCapacity}.0") INGAME.setTooltipMessage("$capaStr/${actorInventory.maxCapacityByActor}")
tooltipShowing[10001] = true tooltipShowing[10001] = true
} }
else { else {

View File

@@ -140,10 +140,10 @@ class UIInventoryFull(
} }
internal var xEnd = (Toolkit.drawWidth + internalWidth).div(2).toFloat() internal val xEnd: Float
private set get() = (Toolkit.drawWidth + internalWidth).div(2).toFloat()
internal var yEnd = -YPOS_CORRECTION + (App.scr.height + internalHeight).div(2).toFloat() internal val yEnd: Float
private set get() = -YPOS_CORRECTION + (App.scr.height + internalHeight).div(2).toFloat()
} }
//val REQUIRED_MARGIN: Int = 138 // hard-coded value. Don't know the details. Range: [91-146]. I chose MAX-8 because cell gap is 8 //val REQUIRED_MARGIN: Int = 138 // hard-coded value. Don't know the details. Range: [91-146]. I chose MAX-8 because cell gap is 8
@@ -247,7 +247,6 @@ class UIInventoryFull(
// private val transitionalMinimap = UIInventoryMinimap(this) // private val transitionalMinimap = UIInventoryMinimap(this)
internal val transitionalCraftingUI = UICrafting(this) internal val transitionalCraftingUI = UICrafting(this)
internal val transitionalTechTreeViewUI = UITechView(this)
internal val transitionalItemCells = UIInventoryCells(this) internal val transitionalItemCells = UIInventoryCells(this)
internal val transitionalEscMenu = UIInventoryEscMenu(this) internal val transitionalEscMenu = UIInventoryEscMenu(this)
val transitionPanel = UIItemHorizontalFadeSlide( val transitionPanel = UIItemHorizontalFadeSlide(
@@ -257,7 +256,7 @@ class UIInventoryFull(
width, width,
App.scr.height, App.scr.height,
1f, 1f,
listOf(transitionalCraftingUI, transitionalTechTreeViewUI), listOf(transitionalCraftingUI),
listOf(transitionalItemCells), listOf(transitionalItemCells),
listOf(transitionalEscMenu) listOf(transitionalEscMenu)
) )
@@ -320,7 +319,6 @@ class UIInventoryFull(
transitionPanel.forcePosition(0) transitionPanel.forcePosition(0)
catBar.setSelectedPanel(0) catBar.setSelectedPanel(0)
transitionalCraftingUI.resetUI() transitionalCraftingUI.resetUI()
transitionalTechTreeViewUI.resetUI()
it.setAsOpen() it.setAsOpen()
} }
@@ -442,9 +440,6 @@ class UIInventoryFull(
offsetX = ((width - internalWidth) / 2).toFloat() offsetX = ((width - internalWidth) / 2).toFloat()
offsetY = ((App.scr.height - internalHeight) / 2).toFloat() offsetY = ((App.scr.height - internalHeight) / 2).toFloat()
xEnd = (width + internalWidth).div(2).toFloat()
yEnd = -YPOS_CORRECTION + (scr.height + internalHeight).div(2).toFloat()
} }
} }

View File

@@ -2,7 +2,6 @@ package net.torvald.terrarum.modulebasegame.ui
import net.torvald.terrarum.CraftingRecipeCodex import net.torvald.terrarum.CraftingRecipeCodex
import net.torvald.terrarum.ItemCodex import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.ui.UIItemCatBar
import net.torvald.terrarum.ceilToInt import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.gameitems.ItemID
@@ -15,7 +14,7 @@ import net.torvald.terrarum.ui.UIItemCatBar.Companion.CAT_ALL
* Created by minjaesong on 2022-06-28. * Created by minjaesong on 2022-06-28.
*/ */
class UIItemCraftingCandidateGrid( class UIItemCraftingCandidateGrid(
parentUI: UICrafting, parentUI: UICraftingWorkbench,
initialX: Int, initialY: Int, initialX: Int, initialY: Int,
horizontalCells: Int, verticalCells: Int, horizontalCells: Int, verticalCells: Int,
drawScrollOnRightside: Boolean = false, drawScrollOnRightside: Boolean = false,
@@ -83,7 +82,7 @@ class UIItemCraftingCandidateGrid(
private fun isCraftable(player: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List<String>): Boolean { private fun isCraftable(player: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List<String>): Boolean {
// printdbg(this, "Is this recipe craftable? $recipe") // printdbg(this, "Is this recipe craftable? $recipe")
return UICrafting.recipeToIngredientRecord(player, recipe, nearbyCraftingStations).none { return UICraftingWorkbench.recipeToIngredientRecord(player, recipe, nearbyCraftingStations).none {
// printdbg(this, " considering ingredient ${it.selectedItem}, ${it.howManyRecipeWants} is required and got ${it.howManyPlayerHas}; crafting station available? ${it.craftingStationAvailable}") // printdbg(this, " considering ingredient ${it.selectedItem}, ${it.howManyRecipeWants} is required and got ${it.howManyPlayerHas}; crafting station available? ${it.craftingStationAvailable}")
it.howManyPlayerHas <= 0L || !it.craftingStationAvailable it.howManyPlayerHas <= 0L || !it.craftingStationAvailable
} }
@@ -114,14 +113,14 @@ class UIItemCraftingCandidateGrid(
if (currentFilter1 == CAT_ALL) if (currentFilter1 == CAT_ALL)
CraftingRecipeCodex.props.forEach { (_, recipes) -> CraftingRecipeCodex.props.forEach { (_, recipes) ->
recipes.forEach { recipes.forEach {
if (isCraftable((parentUI as UICrafting).getPlayerInventory(), it, (parentUI as UICrafting).nearbyCraftingStations)) { if (isCraftable((parentUI as UICraftingWorkbench).getPlayerInventory(), it, (parentUI as UICraftingWorkbench).nearbyCraftingStations)) {
craftingRecipes.add(it) craftingRecipes.add(it)
} }
} }
} }
else else
CraftingRecipeCodex.getCraftableRecipesUsingTheseItems(currentFilter1).forEach { CraftingRecipeCodex.getCraftableRecipesUsingTheseItems(currentFilter1).forEach {
if (isCraftable((parentUI as UICrafting).getPlayerInventory(), it, (parentUI as UICrafting).nearbyCraftingStations)) { if (isCraftable((parentUI as UICraftingWorkbench).getPlayerInventory(), it, (parentUI as UICraftingWorkbench).nearbyCraftingStations)) {
craftingRecipes.add(it) craftingRecipes.add(it)
} }
} }

View File

@@ -11,6 +11,7 @@ import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.ui.Movement import net.torvald.terrarum.ui.Movement
import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import net.torvald.unicode.getKeycapConsole import net.torvald.unicode.getKeycapConsole
import net.torvald.unicode.getKeycapPC import net.torvald.unicode.getKeycapPC
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -70,6 +71,13 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
internal lateinit var cellLoadThread: Thread internal lateinit var cellLoadThread: Thread
init {
CommonResourcePool.addToLoadingList("gradtile32") {
TextureRegionPack("assets/graphics/gui/gradtile32.tga", 1, 32)
}
CommonResourcePool.loadAll()
}
fun advanceMode() { fun advanceMode() {
App.printdbg(this, "Load playerUUID: ${UILoadGovernor.playerUUID}, worldUUID: ${UILoadGovernor.worldUUID}") App.printdbg(this, "Load playerUUID: ${UILoadGovernor.playerUUID}, worldUUID: ${UILoadGovernor.worldUUID}")
full.loadables = SavegameCollectionPair(App.savegamePlayers[UILoadGovernor.playerUUID], App.savegameWorlds[UILoadGovernor.worldUUID]) full.loadables = SavegameCollectionPair(App.savegamePlayers[UILoadGovernor.playerUUID], App.savegameWorlds[UILoadGovernor.worldUUID])
@@ -175,14 +183,16 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
batch.end() batch.end()
val cells = playerCells val cells = playerCells
val grad = CommonResourcePool.getAsTextureRegionPack("gradtile32")
val w = 4096f
lateinit var savePixmap: Pixmap
sliderFBO.inAction(camera, batch) { sliderFBO.inAction(camera, batch) {
gdxClearAndEnableBlend(0f, 0f, 0f, 0f) gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
full.setCameraPosition(batch, camera, 0f, 0f) full.setCameraPosition(batch, camera, 0f, 0f)
batch.color = Color.WHITE batch.color = Color.WHITE
batch.inUse { batch.inUse {
blendNormalStraightAlpha(batch)
for (index in 0 until cells.size) { for (index in 0 until cells.size) {
val it = cells[index] val it = cells[index]
@@ -195,49 +205,30 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
if (App.getConfigBoolean("fx_streamerslayout")) if (App.getConfigBoolean("fx_streamerslayout"))
it.posX -= uiXdiffChatOverlay it.posX -= uiXdiffChatOverlay
} }
}
savePixmap = Pixmap.createFromFrameBuffer(0, 0, sliderFBO.width, sliderFBO.height)
savePixmap.blending = Pixmap.Blending.None
}
// implement "wipe-out" by CPU-rendering (*deep exhale*) // wipe out top and bottom
//savePixmap.setColor(1f,1f,1f,0f) blendAlphaMask(batch)
savePixmap.setColor(0f, 0f, 0f, 0f) batch.color = Color.WHITE
savePixmap.fillRectangle(0, savePixmap.height - titleTopGradStart, savePixmap.width, titleTopGradStart) batch.draw(grad.get(3,0), 0f, 0f, w, titleTopGradStart.toFloat())
// top grad batch.draw(grad.get(1,0), 0f, titleTopGradStart.toFloat(), w, grad.tileH.toFloat())
for (y in titleTopGradStart until titleTopGradEnd) { batch.draw(grad.get(2,0), 0f, titleTopGradEnd.toFloat(), w, (titleBottomGradStart - titleTopGradEnd).toFloat())
val alpha = (y - titleTopGradStart).toFloat() / gradAreaHeight batch.draw(grad.get(0,0), 0f, titleBottomGradStart.toFloat(), w, grad.tileH.toFloat())
for (x in 0 until savePixmap.width) { batch.draw(grad.get(3,0), 0f, titleBottomGradEnd.toFloat(), w, 4096f)
val col = savePixmap.getPixel(x, savePixmap.height - y)
val blendAlpha = (col.and(0xFF) * alpha).roundToInt()
savePixmap.drawPixel(x, savePixmap.height - y, col.and(0xFFFFFF00.toInt()) or blendAlpha)
} }
} }
// bottom grad
for (y in titleBottomGradStart until titleBottomGradEnd) {
val alpha = 1f - ((y - titleBottomGradStart).toFloat() / gradAreaHeight)
for (x in 0 until savePixmap.width) {
val col = savePixmap.getPixel(x, savePixmap.height - y)
val blendAlpha = (col.and(0xFF) * alpha).roundToInt()
savePixmap.drawPixel(x, savePixmap.height - y, col.and(0xFFFFFF00.toInt()) or blendAlpha)
}
}
savePixmap.setColor(0f, 0f, 0f, 0f)
savePixmap.fillRectangle(0, 0, savePixmap.width, height - titleBottomGradEnd + 1)
full.setCameraPosition(batch, camera, 0f, 0f) full.setCameraPosition(batch, camera, 0f, 0f)
val saveTex = TextureRegion(Texture(savePixmap)); saveTex.flip(false, true)
batch.inUse { batch.inUse {
batch.draw(saveTex, posX + (width - uiWidth - 10) / 2f, 0f) batch.color = Color.WHITE
blendNormalStraightAlpha(batch)
(batch as FlippingSpriteBatch).drawFlipped(sliderFBO.colorBufferTexture, posX + (width - uiWidth - 10) / 2f, 0f)
// Control help // Control help
App.fontGame.draw(batch, controlHelp, posX + full.uiX.toFloat(), controlHelperY.toFloat()) App.fontGame.draw(batch, controlHelp, posX + full.uiX.toFloat(), controlHelperY.toFloat())
} }
saveTex.texture.dispose()
savePixmap.dispose()
batch.begin() batch.begin()

View File

@@ -7,6 +7,7 @@ import net.torvald.colourutil.cieluv_getGradient
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureSmelterBasic import net.torvald.terrarum.modulebasegame.gameactors.FixtureSmelterBasic
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair
@@ -128,7 +129,7 @@ class UISmelterBasic(val smelter: FixtureSmelterBasic) : UICanvas(
} }
} }
fun getPlayerInventory(): FixtureInventory = INGAME.actorNowPlaying!!.inventory fun getPlayerInventory(): ActorInventory = INGAME.actorNowPlaying!!.inventory
private var listModeButtonPushed = false private var listModeButtonPushed = false
@@ -357,9 +358,7 @@ class UISmelterBasic(val smelter: FixtureSmelterBasic) : UICanvas(
// let itemlists be sorted // let itemlists be sorted
inventoryFilter = { _: InventoryPair -> true } inventoryFilter = { _: InventoryPair -> true }
playerThings.rebuild(FILTER_CAT_ALL) playerThings.rebuild(FILTER_CAT_ALL)
encumbrancePerc = getPlayerInventory().let { encumbrancePerc = getPlayerInventory().encumberment.toFloat()
it.capacity.toFloat() / it.maxCapacity
}
} }
private var inventoryFilter = { _: InventoryPair -> true } private var inventoryFilter = { _: InventoryPair -> true }
@@ -368,17 +367,13 @@ class UISmelterBasic(val smelter: FixtureSmelterBasic) : UICanvas(
// let itemlists be sorted // let itemlists be sorted
inventoryFilter = filter inventoryFilter = filter
playerThings.rebuild(filter) playerThings.rebuild(filter)
encumbrancePerc = getPlayerInventory().let { encumbrancePerc = getPlayerInventory().encumberment.toFloat()
it.capacity.toFloat() / it.maxCapacity
}
} }
private fun itemListUpdateKeepCurrentFilter() { private fun itemListUpdateKeepCurrentFilter() {
// let itemlists be sorted // let itemlists be sorted
playerThings.rebuild(inventoryFilter) playerThings.rebuild(inventoryFilter)
encumbrancePerc = getPlayerInventory().let { encumbrancePerc = getPlayerInventory().encumberment.toFloat()
it.capacity.toFloat() / it.maxCapacity
}
} }
init { init {

View File

@@ -7,6 +7,7 @@ import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.getWidthOfCells import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.getWidthOfCells
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing
@@ -44,7 +45,7 @@ internal class UIStorageChest : UICanvas(
override fun getNegotiator() = negotiator override fun getNegotiator() = negotiator
override fun getFixtureInventory(): FixtureInventory = chestInventory override fun getFixtureInventory(): FixtureInventory = chestInventory
override fun getPlayerInventory(): FixtureInventory = INGAME.actorNowPlaying!!.inventory override fun getPlayerInventory(): ActorInventory = INGAME.actorNowPlaying!!.inventory
private val catBar: UIItemCatBar private val catBar: UIItemCatBar
private val itemListChest: UITemplateHalfInventory private val itemListChest: UITemplateHalfInventory

View File

@@ -14,10 +14,10 @@ import net.torvald.unicode.getKeycapPC
/** /**
* Created by minjaesong on 2024-02-18. * Created by minjaesong on 2024-02-18.
*/ */
class UITechView(val full: UIInventoryFull?, private val colourTheme: InventoryCellColourTheme = UIItemInventoryCellCommonRes.defaultInventoryCellTheme, class UITechView(val inventoryUI: UIInventoryFull?, val parentContainer: UICrafting, private val colourTheme: InventoryCellColourTheme = UIItemInventoryCellCommonRes.defaultInventoryCellTheme,
) : UICanvas( ) : UICanvas(
toggleKeyLiteral = if (full == null) "control_key_inventory" else null, toggleKeyLiteral = if (inventoryUI == null) "control_key_inventory" else null,
toggleButtonLiteral = if (full == null) "control_gamepad_start" else null toggleButtonLiteral = if (inventoryUI == null) "control_gamepad_start" else null
) { ) {
override var width = Toolkit.drawWidth override var width = Toolkit.drawWidth
@@ -34,10 +34,10 @@ class UITechView(val full: UIInventoryFull?, private val colourTheme: InventoryC
// private val navbarX = posX1 + UIItemListNavBarVertical.LIST_TO_CONTROL_GAP // private val navbarX = posX1 + UIItemListNavBarVertical.LIST_TO_CONTROL_GAP
// private val navbarY = posY1 // private val navbarY = posY1
private val navbarX = full!!.transitionalCraftingUI.itemListCraftable.navRemoCon.posX + 12 private val navbarX = parentContainer.transitionalCraftingUI.itemListCraftable.navRemoCon.posX + 12
private val navbarY = full!!.transitionalCraftingUI.itemListCraftable.navRemoCon.posY - 8 private val navbarY = parentContainer.transitionalCraftingUI.itemListCraftable.navRemoCon.posY - 8
private val navbarWidth = UIItemListNavBarVertical.WIDTH private val navbarWidth = UIItemListNavBarVertical.WIDTH
private val navbarHeight = full!!.transitionalCraftingUI.itemListCraftable.height private val navbarHeight = parentContainer.transitionalCraftingUI.itemListCraftable.height
private val panelX = 32 + navbarX private val panelX = 32 + navbarX
private val panelY = navbarY private val panelY = navbarY
@@ -61,8 +61,7 @@ class UITechView(val full: UIInventoryFull?, private val colourTheme: InventoryC
highlightable = true highlightable = true
).also { ).also {
it.clickOnceListener = { _, _ -> it.clickOnceListener = { _, _ ->
full?.transitionPanel?.setLeftUIto(0) parentContainer.showCraftingUI()
full?.transitionPanel?.uis?.get(0)?.show()
it.highlighted = false it.highlighted = false
} }
} }

View File

@@ -1,14 +1,18 @@
package net.torvald.terrarum.modulebasegame.ui package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.CreditSingleton import net.torvald.terrarum.CreditSingleton
import net.torvald.terrarum.ceilToInt import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.ui.* import net.torvald.terrarum.ui.Toolkit
import java.util.TreeMap import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemTextArea
import net.torvald.terrarum.ui.UIItemVertSlider
import kotlin.math.roundToInt
open class UITitleWallOfText(private val text: List<String>) : UICanvas() { open class UITitleWallOfText(private val text: List<String>) : UICanvas() {
init { init {
@@ -90,11 +94,16 @@ class UISystemInfo(val remoCon: UIRemoCon) : UICanvas() {
private var uptime: Long = 0L private var uptime: Long = 0L
init { init {
// auto resize for fullscreen
val disp = Lwjgl3ApplicationConfiguration.getDisplayMode(Lwjgl3ApplicationConfiguration.getPrimaryMonitor())
v.add("${App.GAME_NAME}" to App.getVERSION_STRING()) v.add("${App.GAME_NAME}" to App.getVERSION_STRING())
v.add("JRE" to System.getProperty("java.version")) v.add("JRE" to System.getProperty("java.version"))
v.add("Gdx" to com.badlogic.gdx.Version.VERSION) v.add("Gdx" to com.badlogic.gdx.Version.VERSION)
v.add("LWJGL" to "${org.lwjgl.Version.VERSION_MAJOR}.${org.lwjgl.Version.VERSION_MINOR}.${org.lwjgl.Version.VERSION_REVISION}") v.add("LWJGL" to "${org.lwjgl.Version.VERSION_MAJOR}.${org.lwjgl.Version.VERSION_MINOR}.${org.lwjgl.Version.VERSION_REVISION}")
v.add("OS" to "${App.OSName} ${App.OSVersion}") v.add("OS" to "${App.OSName} ${App.OSVersion}")
v.add("Display" to "${App.scr.windowW}\u00D7${App.scr.windowH}@${App.scr.magn.times(100).roundToInt()}%, ${disp.bitsPerPixel}bpp (internally ${App.scr.width}\u00D7${App.scr.height})")
v.add("Processor" to "${App.THREAD_COUNT}\u2009\u00D7\u2009${App.processor}") v.add("Processor" to "${App.THREAD_COUNT}\u2009\u00D7\u2009${App.processor}")
v.add("Architecture" to App.systemArch) v.add("Architecture" to App.systemArch)
v.add("CPUID" to App.processorVendor.let { if (it == "null" || it == null) "n/a" else it }) v.add("CPUID" to App.processorVendor.let { if (it == "null" || it == null) "n/a" else it })

View File

@@ -7,6 +7,7 @@ import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing
import net.torvald.terrarum.ui.* import net.torvald.terrarum.ui.*
@@ -36,7 +37,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
override fun getNegotiator() = negotiator override fun getNegotiator() = negotiator
override fun getFixtureInventory(): FixtureInventory = chestInventory override fun getFixtureInventory(): FixtureInventory = chestInventory
override fun getPlayerInventory(): FixtureInventory = INGAME.actorNowPlaying!!.inventory override fun getPlayerInventory(): ActorInventory = INGAME.actorNowPlaying!!.inventory
private val catBar: UIItemCatBar private val catBar: UIItemCatBar
private val itemListChest: UIItemInventoryItemGrid private val itemListChest: UIItemInventoryItemGrid
@@ -155,7 +156,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
itemListChest.rebuild(catBar.catIconsMeaning[catBar.selectedIndex]) itemListChest.rebuild(catBar.catIconsMeaning[catBar.selectedIndex])
itemListPlayer.rebuild(catBar.catIconsMeaning[catBar.selectedIndex]) itemListPlayer.rebuild(catBar.catIconsMeaning[catBar.selectedIndex])
encumbrancePerc = getPlayerInventory().capacity.toFloat() / getPlayerInventory().maxCapacity encumbrancePerc = (getPlayerInventory().capacity / getPlayerInventory().maxCapacityByActor).toFloat()
isEncumbered = getPlayerInventory().isEncumbered isEncumbered = getPlayerInventory().isEncumbered
} }

View File

@@ -332,16 +332,16 @@ internal object TerragenTest : NoiseMaker {
Block.STONE_MARBLE to Color(0.8f, 0.8f, 0.8f, 1f) Block.STONE_MARBLE to Color(0.8f, 0.8f, 0.8f, 1f)
) )
private val COPPER_ORE = 0//x00e9c8ff.toInt() private val COPPER_ORE = 0x00e9c8ff.toInt()
private val IRON_ORE = 0//xff7e74ff.toInt() private val IRON_ORE = 0xff7e74ff.toInt()
private val COAL_ORE = 0//x383314ff.toInt() private val COAL_ORE = 0x383314ff.toInt()
private val ZINC_ORE = 0//xefde76ff.toInt() private val ZINC_ORE = 0xefde76ff.toInt()
private val TIN_ORE = 0//xcd8b62ff.toInt() private val TIN_ORE = 0xcd8b62ff.toInt()
private val GOLD_ORE = 0//xffcc00ff.toInt() private val GOLD_ORE = 0xffcc00ff.toInt()
private val SILVER_ORE = 0//xd5d9f9ff.toInt() private val SILVER_ORE = 0xd5d9f9ff.toInt()
private val LEAD_ORE = 0//xff9300ff.toInt() private val LEAD_ORE = 0xff9300ff.toInt()
private val QUARTZ = 0//x55ff33ff.toInt() private val QUARTZ = 0x55ff33ff.toInt()
private val AMETHYST = 0//xee77ffff.toInt() private val AMETHYST = 0xee77ffff.toInt()
private val ROCKSALT = 0xff00ffff.toInt() private val ROCKSALT = 0xff00ffff.toInt()
private val NITRE = 0xdbd6a1ff.toInt() private val NITRE = 0xdbd6a1ff.toInt()
@@ -684,7 +684,7 @@ internal object TerragenTest : NoiseMaker {
Joise(groundScalingCached), Joise(groundScalingCached),
Joise(caveScaling), Joise(caveScaling),
Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:1", 0.026, 0.010, 0.517, 1.0)), Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:1", 0.026, 0.010, 0.517, 1.0)),
Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:2", 0.045, 0.011, 0.517, 1.0)), Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:2", 0.031, 0.011, 0.521, 1.0)),
Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:3", 0.017, 0.070, 0.511, 3.8)), Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:3", 0.017, 0.070, 0.511, 3.8)),
Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:4", 0.019, 0.011, 0.511, 1.0)), Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:4", 0.019, 0.011, 0.511, 1.0)),
Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:5", 0.017, 0.017, 0.511, 1.0)), Joise(generateOreVeinModule(caveAttenuateBiasScaledCache, seed shake "ores@basegame:5", 0.017, 0.017, 0.511, 1.0)),

View File

@@ -3,11 +3,8 @@ package net.torvald.terrarum.utils
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import net.torvald.terrarum.App import net.torvald.terrarum.App
import java.awt.Desktop import java.awt.Desktop
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.StringSelection
import java.awt.datatransfer.UnsupportedFlavorException
import java.io.File import java.io.File
import java.net.URL
/** /**
* Created by minjaesong on 2016-07-31. * Created by minjaesong on 2016-07-31.
@@ -15,7 +12,7 @@ import java.io.File
object Clipboard { object Clipboard {
private val IS_MACOS = App.operationSystem == "OSX" private val IS_MACOS = App.operationSystem == "OSX"
fun fetch(): String = Gdx.app.clipboard.contents fun fetch(): String = Gdx.app.clipboard.contents ?: ""
fun copy(s: String) { fun copy(s: String) {
Gdx.app.clipboard.contents = s Gdx.app.clipboard.contents = s
@@ -32,3 +29,10 @@ object OpenFile {
Desktop.getDesktop().open(file) Desktop.getDesktop().open(file)
} }
} }
object OpenURL {
private val IS_MACOS = App.operationSystem == "OSX"
operator fun invoke(url: URL) {
Gdx.net.openURI(url.toURI().toString())
}
}

View File

@@ -37,7 +37,10 @@ object WorldCamera {
// zoomed coords. Currently only being used by the lightmaprenderer. // zoomed coords. Currently only being used by the lightmaprenderer.
// What about others? We just waste 3/4 of the framebuffer // What about others? We just waste 3/4 of the framebuffer
val zoomedX: Int val zoomedX: Int
get() = x + (width * zoomSamplePoint).toInt() get() {
val t = (if (App.getConfigBoolean("fx_streamerslayout")) App.scr.chatWidth / 2 else 0).toFloat()
return x + (width * zoomSamplePoint - (t * (zoom - 1f)) / 2f).toInt()
}
val zoomedY: Int val zoomedY: Int
get() = y + (height * zoomSamplePoint).toInt() get() = y + (height * zoomSamplePoint).toInt()

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More