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="BuildArtifacts" enabled="true">
<artifact name="ModuleComputers" />
<artifact name="MusicPlayer" />
<artifact name="TerrarumBuild" />
</option>
<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"
"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"
"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"
# 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"
# 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"
"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"
@@ -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"
# 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"
"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"
"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"
"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"
"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,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,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,SCAFFOLDING,NORANDTILE,WOODEN"
# 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"
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
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 */
"workbench": "",
"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 */
"workbench": "",
"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 */
"workbench": "",
"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 */
"workbench": "",
"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 */
]
},
"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 */
"workbench": "basiccrafting",
@@ -59,7 +65,25 @@
"item@basegame:6": { /* storage chest */
"workbench": "basiccrafting",
"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": [
[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 */
"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 */
"workbench": "",
"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 */
"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": {
"workbench": "basiccrafting",
"ingredients": [[1, 6, "$WOOD", 2, "item@basegame:18"]]
"ingredients": [[1, 5, "$WOOD", 2, "item@basegame:18"]]
},*/
"item@basegame:15": { /* wooden mallet */
"workbench": "basiccrafting",
"ingredients": [[1, 6, "$WOOD", 2, "item@basegame:18"]]
"ingredients": [[1, 5, "$WOOD", 2, "item@basegame:18"]]
},
"item@basegame:23": { /* stone pick */
"workbench": "basiccrafting",
"ingredients": [[1, 6, "$ROCK", 2, "item@basegame:18"]]
"ingredients": [[1, 5, "$ROCK", 2, "item@basegame:18"]]
},
"item@basegame:24": { /* stone axe */
"workbench": "basiccrafting",
"ingredients": [[1, 6, "$ROCK", 2, "item@basegame:18"]]
"ingredients": [[1, 5, "$ROCK", 2, "item@basegame:18"]]
},
"item@basegame:1": { /* copper pick */
"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 */
"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 */
"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 */
"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 */
"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 */
"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 */
"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 */
"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 */
"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,
"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
6;net.torvald.terrarum.modulebasegame.gameitems.ItemStorageChest;FIXTURE,STORAGE
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
10;net.torvald.terrarum.modulebasegame.gameitems.ItemTypewriter;FIXTURE,PRINTING
11;net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar;FIXTURE
@@ -20,7 +20,7 @@ id;classname;tags
19;net.torvald.terrarum.modulebasegame.gameitems.AxeCopper;TOOL,AXE
20;net.torvald.terrarum.modulebasegame.gameitems.AxeIron;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
24;net.torvald.terrarum.modulebasegame.gameitems.AxeStone;TOOL,AXE
25;net.torvald.terrarum.modulebasegame.gameitems.ItemClayBall;
@@ -32,6 +32,16 @@ id;classname;tags
31;net.torvald.terrarum.modulebasegame.gameitems.ItemGunpowder;POWDER,EXPLOSIVE
32;net.torvald.terrarum.modulebasegame.gameitems.ItemCherryBomb;EXPLOSIVE,THROWABLE
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
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_USE_CODE": "Use Code",
"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!",
"GAME_ACTION_GRAPPLE": "Grapple",
"GAME_ACTION_QUICKSEL": "Quick Select",

View File

@@ -16,6 +16,9 @@
"TOOLTIP_item@basegame:4": "Breaks down walls",
"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: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: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 */
@@ -31,6 +34,7 @@
"TOOLTIP_item@basegame:20": "Cuts trees",
"TOOLTIP_item@basegame:21": "Cuts trees",
"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:24": "Cuts trees",
"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: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:36": "Creates wires from metal ingots",
"TOOLTIP_item@basegame:114": "A precious fuel for the steel production",

View File

@@ -3,6 +3,7 @@
"ITEM_CHARCOAL": "Charcoal",
"ITEM_CHERRY_BOMB": "Bomb",
"ITEM_COAL_COKE": "Coal Coke",
"ITEM_COPPER_BULB": "Copper Bulb",
"ITEM_DOOR_OAK": "Oak Door",
"ITEM_DOOR_EBONY": "Ebony Door",
"ITEM_DOOR_BIRCH": "Birch Door",
@@ -37,6 +38,7 @@
"ITEM_INGOT_ZINC": "Zinc Ingot",
"ITEM_JUKEBOX": "Jukebox",
"ITEM_LOGIC_SIGNAL_EMITTER": "Logic Signal Emitter",
"ITEM_LOGIC_SIGNAL_SWITCH": "Logic Signal Switch",
"ITEM_LOGS_BIRCH": "Birch Logs",
"ITEM_LOGS_EBONY": "Ebony Logs",
"ITEM_LOGS_OAK": "Oak Logs",
@@ -65,11 +67,16 @@
"ITEM_SLEDGEHAMMER_STEEL": "Steel Sledgehammer",
"ITEM_SMELTER_SMALL": "Small Smelter",
"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_TURNTABLE": "Turntable",
"ITEM_TYPEWRITER": "Typewriter",
"ITEM_WIRE": "Wire",
"ITEM_WIRE_CUTTER": "Wire Cutter",
"ITEM_WIRE_ROLLING_MILL": "Wire Rolling Mill",
"ITEM_WOOD_STICK": "Stick",
"ITEM_WOODEN_MALLET": "Wooden Mallet",
"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_RENAME": "이름 바꾸기",
"MENU_LABEL_USE_CODE": "코드 사용",
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "채굴 시 광석 툴팁 보이기",
"MENU_OPTIONS_MAX_CRAFTING": "한번에 제작할 최대 아이템 수",
"MENU_UPDATE_UPDATE_AVAILABLE": "새 업데이트가 있습니다!",
"GAME_ACTION_GRAPPLE": "매달리기",
"GAME_ACTION_QUICKSEL": "빠른 선택",

View File

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

View File

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

View File

@@ -44,10 +44,10 @@ package=net.torvald.terrarum.modulebasegame
entrypoint=net.torvald.terrarum.modulebasegame.EntryPoint
# 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/)
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";
# 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"
"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";""
"4";"0.019";"0.011";"0.511";"1.0";"a16x16";"zinc (sphalerite)";""
"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
8192;8192;WIRE_RED;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,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
8194;8194;WIRE_BLUE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,2,4;1
#8195;8195;WIRE_BUNDLE;signal;digital_3bits;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,0;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
8197;8197;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,4,4;1
8198;8198;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,5,4;1
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;"SIGNALWIRE"
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;"SIGNALWIRE"
#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;"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;"POWERWIRE_HIGH"
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)
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
package=net.torvald.terrarum.musicplayer
entrypoint=net.torvald.terrarum.musicplayer.EntryPoint
releasedate=2024-02-19
version=1.0.0
releasedate=2024-03-03
version=1.0.1
jar=MusicPlayer.jar
jarhash=c8896ce5b2aa79057e1324a701c1c5bd4099a8a651f044a120ad700cedfbb16e
dependency=basegame 0.4.0
jarhash=53248a70a8cbfbcdd76e11549a132400305e91785ff98af514e68e8cafacdc19
dependency=basegame 0.4.1

View File

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

View File

@@ -282,7 +282,6 @@ $BULLET Music:
- music/discs/lucid_dream.ogg
- music/discs/railway.ogg
- music/discs/welded.ogg
℗ 2021, 2022, 2023, 2024 Orstphone
Check out the original tracks on:
Apple Music: <https://music.apple.com/kr/artist/orstphone/1587723053>
@@ -300,7 +299,6 @@ $BULLET Foleys:
- ambient/season/diurnal_winter.*.ogg
- ambient/season/matutinal.*.ogg
- ambient/season/nocturnal.*.ogg
℗ 2011, 2013, 2015, 2020, 2021 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/door/wooden_open.*.ogg
- effects/door/wooden_close.*.ogg
℗ 2020, 2021, 2022 Nox Sound
Sound from <https://freesound.org/people/Nox_Sound>
- effects/static/phono_pops.ogg
℗ 2011 Veezay
Sound from <https://freesound.org/people/veezay>
- effects/static/tape_hiss.ogg
℗ 2017 Stephen Holdaway
Sound from <https://freesound.org/people/stecman>
- effects/static/film_pops_lowpass.ogg
℗ 2015 Joe DeShon
Sound from <https://freesound.org/people/joedeshon>
- effects/static/bonfire.ogg
℗ 2019 DrinkingWindGames
Sound from <https://freesound.org/people/DrinkingWindGames>
- effects/explosion/bang_bomb.ogg
℗ 2019 Richwise
Sound from <https://freesound.org/people/richwise>
- effects/explosion/fuse.ogg
- effects/explosion/fuse_continue.ogg
℗ 2012, 2015 j1987 and 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:
- convolution/EchoThief - *.bin
EchoThief Impulse Response Library
℗ 2013-2023 Chris Warren <cwarren@sdsu.edu>
- convolution/Soundwoofer - *.bin
Soundwoofer Free Impulse Response Library
℗ 2018 Soundwoofer Team
<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) {
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(
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 inventoryCategory = if (isWall) Category.WALL else Category.BLOCK
override var canBeDynamic = false

View File

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

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.serialise.toUint
import java.net.URL
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.*
@@ -48,6 +49,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
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
*
*/
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.1: 2278
// 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.4.0: 3631
// Commit counts up to the Release 0.4.1: 3678
// val VERSION_SNAPSHOT = Snapshot(0) // for normal dev
// 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
*/
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
*/
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
@@ -144,6 +152,10 @@ class AudioMixer : Disposable {
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 {
// serial precessing
while (processing) {
@@ -168,6 +180,8 @@ class AudioMixer : Disposable {
while (processing && !masterTrack.pcmQueue.isEmpty) {
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...

View File

@@ -147,7 +147,7 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
private val readBuf = ByteArray(fetchSize * 4)
init {
printdbg(this, "App.audioMixerBufferSize=${App.audioBufferSize}")
// printdbg(this, "App.audioMixerBufferSize=${App.audioBufferSize}")
}
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
}
var bufEmpty = true; private set
override fun run() {
// while (running) { // 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 samplesR1: FloatArray
var bufEmpty = false
bufEmpty = false
// get samples and apply the fader
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 {
init {

View File

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

View File

@@ -53,7 +53,7 @@ class OreCodex {
private fun setProp(modname: String, key: Int, record: CSVRecord) {
val prop = OreProp()
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" }
oreProps[prop.id] = prop

View File

@@ -39,15 +39,15 @@ class WireCodex {
* @param module name of the module
* @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")
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() }
}
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")
val csvParser = org.apache.commons.csv.CSVParser.parse(
@@ -57,10 +57,10 @@ class WireCodex {
val csvRecordList = csvParser.records
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 {
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)
/*return*/t
}
wireProps[id]?.let(blockRegisterHook)
}
CommonResourcePool.loadAll()
}
fun getAll() = wireProps.values
@@ -134,6 +137,7 @@ class WireCodex {
prop.inputType = record.get("inputtype") ?: prop.accepts
prop.outputType = record.get("outputtype") ?: prop.accepts
prop.canBranch = record.boolVal("branching")
prop.tags = record.get("tags").split(',').map { it.trim().toUpperCase() }.toHashSet()
wireProps[prop.id] = prop

View File

@@ -24,4 +24,18 @@ class WireProp {
* Mainly intended to be used by third-party modules
*/
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)
*
* Example passwords would be:
* aryll -> beedle -> ciela -> daruk -> ... -> linebeck -> mido -> navi -> ...
* aryll -> beedle -> ciela -> daruk -> epona -> ... -> linebeck -> mido -> navi -> ...
*
* Notes:
* 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("hash: $hashedPwd")
if ("c40232ae7b8020da3ab1449a015e7cc23f249a790856b63b1b69c6a5de019fed".equals(hashedPwd, ignoreCase = true)) {
if ("4a26c5cd64195c4a52d2e3770e56c1d0c65861d2a03b47f8ba5d25ca033b9c42".equals(hashedPwd, ignoreCase = true)) {
// beedle
val msg = if (a) "Locked" else "Authenticated"
Echo(msg)

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum.gameactors
import net.torvald.random.HQRNG
import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.App.printdbgerr
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.audio.MusicContainer
@@ -160,6 +161,10 @@ abstract class Actor : Comparable<Actor>, Runnable {
musicTracks[music] = track
musicTracks1.add(track.name)
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.maxVolumeFun = { volume }
it.volume = volume
doSomethingWithTrack(it)
// it.play()
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: Vector2) = setPosition(pos.x, pos.y)
fun setPositionFromCentrePoint(pos: Vector2) = setPosition(pos.x, pos.y + (hitbox.height) / 2)
/**
* ONLY FOR INITIAL SETUP

View File

@@ -524,9 +524,17 @@ open class GameWorld(
if (wiringGraph[blockAddr]!![itemID] == null)
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) {
val (x, y) = coerceXY(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.App.*
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.blockproperties.Block
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.gameitems.GameItem
import net.torvald.terrarum.gameitems.mouseInInteractableRange
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
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.weather.WeatherMixer
import net.torvald.terrarum.weather.WeatherMixer.render
import net.torvald.terrarum.worlddrawer.BlocksDrawer
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray
import org.dyn4j.geometry.Vector2
import kotlin.system.exitProcess
@@ -206,6 +215,17 @@ object IngameRenderer : Disposable {
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(
frameDelta: Float,
gamePaused: Boolean,
@@ -248,6 +268,8 @@ object IngameRenderer : Disposable {
drawToRGB(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
drawToA(frameDelta, actorsRenderBehind, actorsRenderMiddle, actorsRenderMidTop, actorsRenderFront, actorsRenderOverlay, particlesContainer)
drawOverlayActors(frameDelta, actorsRenderOverlay)
if (player != null && player is Pocketed) drawAimGuide(frameDelta, player)
}
batch.color = Color.WHITE
@@ -287,12 +309,7 @@ object IngameRenderer : Disposable {
blendNormalStraightAlpha(batch)
batch.shader = shaderBlendGlow
shaderBlendGlow.setUniformi("tex1", 1)
batch.draw(rgbTex,
-0.5f * rgbTex.regionWidth * zoom + 0.5f * rgbTex.regionWidth,
-0.5f * rgbTex.regionHeight * zoom + 0.5f * rgbTex.regionHeight,
rgbTex.regionWidth * zoom,
rgbTex.regionHeight * zoom
)
batch.drawFramebufferWithZoom(rgbTex, zoom)
}
}
@@ -304,12 +321,7 @@ object IngameRenderer : Disposable {
batch.inUse {
blendNormalStraightAlpha(batch)
batch.shader = null
batch.draw(rgbTex,
-0.5f * rgbTex.regionWidth * zoom + 0.5f * rgbTex.regionWidth,
-0.5f * rgbTex.regionHeight * zoom + 0.5f * rgbTex.regionHeight,
rgbTex.regionWidth * zoom,
rgbTex.regionHeight * zoom
)
batch.drawFramebufferWithZoom(rgbTex, zoom)
// indicator
batch.color = Color.RED
@@ -331,12 +343,7 @@ object IngameRenderer : Disposable {
batch.inUse {
blendNormalStraightAlpha(batch)
batch.shader = null
batch.draw(aTex,
-0.5f * aTex.regionWidth * zoom + 0.5f * aTex.regionWidth,
-0.5f * aTex.regionHeight * zoom + 0.5f * aTex.regionHeight,
aTex.regionWidth * zoom,
aTex.regionHeight * zoom
)
batch.drawFramebufferWithZoom(aTex, zoom)
// indicator
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() {
if (!initDone) {

View File

@@ -319,6 +319,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
(!tileProp.isSolid && !wallProp.isSolid).toInt().toFloat()
}
)
loadedTime_t = App.getTIME_T()
}
data class NewGameParams(
@@ -493,6 +495,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
App.savegameWorlds[world.worldIndex] = SavegameCollection.collectFromBaseFilename(File(worldsDir), worldSavefileName)
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
onSuccessful()
loadedTime_t = App.getTIME_T()
}
}
}
@@ -1412,6 +1418,9 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
val timeDiff = System.nanoTime() - start
debugTimers.put("Last Autosave Duration", timeDiff)
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.ui.Toolkit
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.worlddrawer.WorldCamera
import net.torvald.util.CircularArray
@@ -494,18 +496,47 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
// update available!
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(
batch,
Lang["MENU_UPDATE_UPDATE_AVAILABLE"],
UIRemoCon.menubarOffX + UIRemoCon.UIRemoConElement.paddingLeft / 2 + uiRemoCon.posX,
UIRemoCon.menubarOffY - uiRemoCon.height + uiRemoCon.posY
tx, ty1
)
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() {
}

View File

@@ -589,7 +589,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
private fun applyVelo(x: Int): Double {
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
}

View File

@@ -8,6 +8,7 @@ import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.ui.UIQuickslotBar
import net.torvald.terrarum.sqr
/**
* Created by minjaesong on 2016-03-15.
@@ -38,6 +39,21 @@ class ActorInventory() : FixtureInventory() {
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.)
*

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]
*/
open fun canSpawnOnThisFloor(itemID: ItemID): Boolean {
return true
val blockprop = BlockCodex[itemID]
return blockprop.isSolid || blockprop.isPlatform
}
fun canSpawnHere(posX0: Int, posY0: Int): Boolean {
@@ -277,7 +278,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
val xs = posX until posX + blockBox.width
cannotSpawn = cannotSpawn or xs.any { x ->
world!!.getTileFromTerrain(x, y).let {
!BlockCodex[it].isSolid || !canSpawnOnThisFloor(it)
!canSpawnOnThisFloor(it)
}
}
}

View File

@@ -1,11 +1,9 @@
package net.torvald.terrarum.modulebasegame.gameactors
import com.badlogic.gdx.Gdx
import net.torvald.gdx.graphics.Cvec
import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.*
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.NullFilter
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.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.ui.UICrafting
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
@@ -81,6 +78,8 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
private var nextDelay = 0.25f
private var spawnTimer = 0f
@Transient private var audioStatus = 0
override fun updateImpl(delta: Float) {
super.updateImpl(delta)
@@ -108,17 +107,32 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
// manage audio
getTrackByAudio(static).let {
if (it != null && !it.isPlaying) {
startAudio(static) {
it.filters[filterIndex] = Gain(0f)
// printdbg(this, "Checking out track ${it?.name}")
if (it != null) {
if (audioStatus == 0) {
startAudio(static) {
it.filters[filterIndex] = Gain(0f)
audioStatus = 1
}
}
}
}
getTrackByAudio(static)?.let {
if (it.filters[filterIndex] !is Gain) // just in case...
it.filters[filterIndex] = Gain(0f)
else {
// printdbg(this, "Track is null! (old audio status=$audioStatus")
audioStatus = 0
}
(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.
*/
val encumberment: Double
open val encumberment: Double
get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER)
0.0
else if (capacityMode == CAPACITY_MODE_WEIGHT)
@@ -332,6 +332,10 @@ class InventoryPair : Comparable<InventoryPair> {
operator fun component2() = qty
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)

View File

@@ -7,6 +7,9 @@ import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
/**
* Created by minjaesong on 2021-08-08.
*/
class FixtureLogicSignalEmitter : Electric {
@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
// FIXME this code is also killing the audio played by the other fixture (FixtureFurnaceAndAnvil)
getTrackByAudio(static).let {
if (it == null || (temperature > 0f && !it.isPlaying)) {
if (it == null || (temperature > 0f && !it.isPlaying && !it.playRequested.get())) {
startAudio(static) {
it.filters[filterIndex] = Gain(0f)
}
@@ -300,12 +301,13 @@ class FixtureSmelterBasic : FixtureBase, CraftingStation {
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.langpack.Lang
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.ui.*
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -12,13 +15,11 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2019-07-08.
*/
internal class FixtureStorageChest : FixtureBase {
class FixtureStorageChest : FixtureBase {
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1),
mainUI = UIStorageChest(),
inventory = FixtureInventory(40, CAPACITY_MODE_COUNT),
inventory = FixtureInventory(MAXCAP_NUM, MAXCAP_MODE),
nameFun = { Lang["ITEM_STORAGE_CHEST"] }
) {
@@ -36,6 +37,50 @@ internal class FixtureStorageChest : FixtureBase {
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)
}
@@ -47,8 +92,80 @@ internal class FixtureStorageChest : FixtureBase {
(mainUI as UIStorageChest).chestInventory = this.inventory!!
(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
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.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
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
/**

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?) {
if (item == null) return
// check equipposition of the given item
if (item.equipPosition == GameItem.EquipPosition.NULL)
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)) {
//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")
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
// Relevant Actorvalue is NOT being updated on time
// They're being safely handled by UIItemInventoryElem*.touchDown() and ActorInventory.remove
// NOTE: DON'T TOUCH QUICKSLOT HERE
// Relevant Actorvalue is NOT being updated on time
// 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?) {
itemID?.let {
unequipItem(ItemCodex[itemID])
} ?: return
unequipItem(ItemCodex[itemID])
}
// no need for equipSlot(Int)
@@ -50,7 +53,13 @@ interface Pocketed {
if (slot < 0 || slot > GameItem.EquipPosition.INDEX_MAX)
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)) {
val actionInterval = actorvalue.getAsDouble(AVKey.ACTION_INTERVAL)!!
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()) {
PickaxeCore.makeNoiseTileTouching(actor, tile)
@@ -131,7 +133,7 @@ object AxeCore {
INGAME.world.inflictTerrainDamage(
x, y,
Calculate.hatchetPower(actor, item?.material) * swingDmgToFrameDmg,
Calculate.hatchetPower(actor, item?.material) * swingDmgToFrameDmg * axePowerMult,
false
).let { (tileBroken, _) ->
// 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.gameactors.FixtureLogicSignalEmitter
/**
* Created by minjaesong on 2021-08-08.
*/
class ItemLogicSignalEmitter(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter") {
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.terrarum.BlockCodex
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.gameactors.ActorWithBody
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 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) {

View File

@@ -6,7 +6,7 @@ import net.torvald.terrarum.gameitems.ItemID
class ItemSeedOak(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingOak") {
override var originalName = "ITEM_SEED_OAK"
override var baseMass = 10.0
override var baseMass = 1.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
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") {
override var originalName = "ITEM_SEED_EBONY"
override var baseMass = 10.0
override var baseMass = 1.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
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") {
override var originalName = "ITEM_SEED_BIRCH"
override var baseMass = 10.0
override var baseMass = 1.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
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") {
override var originalName = "ITEM_SEED_ROSEWOOD"
override var baseMass = 10.0
override var baseMass = 1.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
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.
*/
class ItemStorageChest(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChest") {
override var dynamicID: ItemID = originalID
override var baseMass = FixtureTikiTorch.MASS
override val canBeDynamic = false
@@ -20,5 +19,46 @@ class ItemStorageChest(originalID: ItemID) : FixtureItemBase(originalID, "net.to
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/storage_chest.tga")
override var baseToolSize: Double? = baseMass
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 ->
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 (throwPos, throwForce) = getThrowPosAndVector(actor)
val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody
lobbed.setPosition(playerCentrePos)
lobbed.externalV.set(powX, powY)
lobbed.setPositionFromCentrePoint(throwPos)
lobbed.externalV.set(throwForce)
setupLobbedActor(lobbed)
Terrarum.ingame?.queueActorAddition(lobbed)
@@ -52,6 +44,24 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
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 net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.WireCodex
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
@@ -26,6 +27,7 @@ class WirePieceSignalWire(originalID: ItemID, private val atlasID: String, priva
init {
equipPosition = GameItem.EquipPosition.HAND_GRIP
originalName = "ITEM_WIRE"
tags.addAll(WireCodex[originalID].tags)
}
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long {

View File

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

View File

@@ -1,593 +1,84 @@
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.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
import net.torvald.terrarum.App
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemHorizontalFadeSlide
/**
* 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.
* Created by minjaesong on 2024-03-02.
*/
class UICrafting(val full: UIInventoryFull?) : UICanvas(
toggleKeyLiteral = if (full == null) "control_key_inventory" else null,
toggleButtonLiteral = if (full == 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
internal val transitionalCraftingUI = UICraftingWorkbench(full, this)
internal val transitionalTechtreePanel = UITechView(full, this)
val transitionPanel = UIItemHorizontalFadeSlide(
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() {
// 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()
transitionalCraftingUI.resetUI()
transitionalTechtreePanel.resetUI()
}
private fun resetSpinner() {
spinnerCraftCount.resetToSmallest()
itemListIngredients.numberMultiplier = 1L
itemListCraftable.numberMultiplier = 1L
fun showCraftingUI() {
transitionPanel.setLeftUIto(0)
transitionalCraftingUI.show()
}
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().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
fun showTechViewUI() {
transitionPanel.setLeftUIto(1)
transitionalTechtreePanel.show()
}
override fun updateImpl(delta: Float) {
// NO super.update due to an infinite recursion
this.uiItems.forEach { it.update(delta) }
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) {
// 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)
if (full == null) {
UIInventoryFull.drawBackground(batch, opacity)
}
blendNormalStraightAlpha(batch)
uiItems.forEach { it.render(frameDelta, batch, camera) }
}
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() {
transitionPanel.dispose()
}
companion object {
data class RecipeIngredientRecord(
val selectedItem: ItemID,
val howManyPlayerHas: Long,
val howManyRecipeWants: Long,
val craftingStationAvailable: Boolean,
)
init {
addUIitem(transitionPanel)
}
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 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)
}
}
override fun setPosition(x: Int, y: Int) {
transitionalCraftingUI.setPosition(x, y)
transitionalTechtreePanel.setPosition(x, y)
}
}

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.langpack.Lang
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.FixtureInventory
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELLS_HOR
@@ -36,7 +37,7 @@ internal class UIInventoryCells(
val weightBarWidth = UIItemInventoryElemSimple.height * 2f + UIItemInventoryItemGrid.listGap
// 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
// encumbrance meter
val encumbranceText = Lang["GAME_INVENTORY_ENCUMBRANCE"]
@@ -75,7 +76,7 @@ internal class UIInventoryCells(
else
"${(actorInventory.capacity * 100L).toLong() / 100.0}"
INGAME.setTooltipMessage("$capaStr/${actorInventory.maxCapacity}.0")
INGAME.setTooltipMessage("$capaStr/${actorInventory.maxCapacityByActor}")
tooltipShowing[10001] = true
}
else {

View File

@@ -140,10 +140,10 @@ class UIInventoryFull(
}
internal var xEnd = (Toolkit.drawWidth + internalWidth).div(2).toFloat()
private set
internal var yEnd = -YPOS_CORRECTION + (App.scr.height + internalHeight).div(2).toFloat()
private set
internal val xEnd: Float
get() = (Toolkit.drawWidth + internalWidth).div(2).toFloat()
internal val yEnd: Float
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
@@ -247,7 +247,6 @@ class UIInventoryFull(
// private val transitionalMinimap = UIInventoryMinimap(this)
internal val transitionalCraftingUI = UICrafting(this)
internal val transitionalTechTreeViewUI = UITechView(this)
internal val transitionalItemCells = UIInventoryCells(this)
internal val transitionalEscMenu = UIInventoryEscMenu(this)
val transitionPanel = UIItemHorizontalFadeSlide(
@@ -257,7 +256,7 @@ class UIInventoryFull(
width,
App.scr.height,
1f,
listOf(transitionalCraftingUI, transitionalTechTreeViewUI),
listOf(transitionalCraftingUI),
listOf(transitionalItemCells),
listOf(transitionalEscMenu)
)
@@ -320,7 +319,6 @@ class UIInventoryFull(
transitionPanel.forcePosition(0)
catBar.setSelectedPanel(0)
transitionalCraftingUI.resetUI()
transitionalTechTreeViewUI.resetUI()
it.setAsOpen()
}
@@ -442,9 +440,6 @@ class UIInventoryFull(
offsetX = ((width - internalWidth) / 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.ItemCodex
import net.torvald.terrarum.ui.UIItemCatBar
import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.gameitems.GameItem
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.
*/
class UIItemCraftingCandidateGrid(
parentUI: UICrafting,
parentUI: UICraftingWorkbench,
initialX: Int, initialY: Int,
horizontalCells: Int, verticalCells: Int,
drawScrollOnRightside: Boolean = false,
@@ -83,7 +82,7 @@ class UIItemCraftingCandidateGrid(
private fun isCraftable(player: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List<String>): Boolean {
// 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}")
it.howManyPlayerHas <= 0L || !it.craftingStationAvailable
}
@@ -114,14 +113,14 @@ class UIItemCraftingCandidateGrid(
if (currentFilter1 == CAT_ALL)
CraftingRecipeCodex.props.forEach { (_, recipes) ->
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)
}
}
}
else
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)
}
}

View File

@@ -11,6 +11,7 @@ import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.ui.Movement
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import net.torvald.unicode.getKeycapConsole
import net.torvald.unicode.getKeycapPC
import kotlin.math.roundToInt
@@ -70,6 +71,13 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
internal lateinit var cellLoadThread: Thread
init {
CommonResourcePool.addToLoadingList("gradtile32") {
TextureRegionPack("assets/graphics/gui/gradtile32.tga", 1, 32)
}
CommonResourcePool.loadAll()
}
fun advanceMode() {
App.printdbg(this, "Load playerUUID: ${UILoadGovernor.playerUUID}, worldUUID: ${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()
val cells = playerCells
val grad = CommonResourcePool.getAsTextureRegionPack("gradtile32")
val w = 4096f
lateinit var savePixmap: Pixmap
sliderFBO.inAction(camera, batch) {
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
full.setCameraPosition(batch, camera, 0f, 0f)
batch.color = Color.WHITE
batch.inUse {
blendNormalStraightAlpha(batch)
for (index in 0 until cells.size) {
val it = cells[index]
@@ -195,49 +205,30 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
if (App.getConfigBoolean("fx_streamerslayout"))
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*)
//savePixmap.setColor(1f,1f,1f,0f)
savePixmap.setColor(0f, 0f, 0f, 0f)
savePixmap.fillRectangle(0, savePixmap.height - titleTopGradStart, savePixmap.width, titleTopGradStart)
// top grad
for (y in titleTopGradStart until titleTopGradEnd) {
val alpha = (y - titleTopGradStart).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)
// wipe out top and bottom
blendAlphaMask(batch)
batch.color = Color.WHITE
batch.draw(grad.get(3,0), 0f, 0f, w, titleTopGradStart.toFloat())
batch.draw(grad.get(1,0), 0f, titleTopGradStart.toFloat(), w, grad.tileH.toFloat())
batch.draw(grad.get(2,0), 0f, titleTopGradEnd.toFloat(), w, (titleBottomGradStart - titleTopGradEnd).toFloat())
batch.draw(grad.get(0,0), 0f, titleBottomGradStart.toFloat(), w, grad.tileH.toFloat())
batch.draw(grad.get(3,0), 0f, titleBottomGradEnd.toFloat(), w, 4096f)
}
}
// 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)
val saveTex = TextureRegion(Texture(savePixmap)); saveTex.flip(false, true)
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
App.fontGame.draw(batch, controlHelp, posX + full.uiX.toFloat(), controlHelperY.toFloat())
}
saveTex.texture.dispose()
savePixmap.dispose()
batch.begin()

View File

@@ -7,6 +7,7 @@ import net.torvald.colourutil.cieluv_getGradient
import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg
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.FixtureSmelterBasic
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
@@ -357,9 +358,7 @@ class UISmelterBasic(val smelter: FixtureSmelterBasic) : UICanvas(
// let itemlists be sorted
inventoryFilter = { _: InventoryPair -> true }
playerThings.rebuild(FILTER_CAT_ALL)
encumbrancePerc = getPlayerInventory().let {
it.capacity.toFloat() / it.maxCapacity
}
encumbrancePerc = getPlayerInventory().encumberment.toFloat()
}
private var inventoryFilter = { _: InventoryPair -> true }
@@ -368,17 +367,13 @@ class UISmelterBasic(val smelter: FixtureSmelterBasic) : UICanvas(
// let itemlists be sorted
inventoryFilter = filter
playerThings.rebuild(filter)
encumbrancePerc = getPlayerInventory().let {
it.capacity.toFloat() / it.maxCapacity
}
encumbrancePerc = getPlayerInventory().encumberment.toFloat()
}
private fun itemListUpdateKeepCurrentFilter() {
// let itemlists be sorted
playerThings.rebuild(inventoryFilter)
encumbrancePerc = getPlayerInventory().let {
it.capacity.toFloat() / it.maxCapacity
}
encumbrancePerc = getPlayerInventory().encumberment.toFloat()
}
init {

View File

@@ -7,6 +7,7 @@ import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitems.GameItem
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.ui.UIInventoryFull.Companion.getWidthOfCells
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing
@@ -44,7 +45,7 @@ internal class UIStorageChest : UICanvas(
override fun getNegotiator() = negotiator
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 itemListChest: UITemplateHalfInventory

View File

@@ -14,10 +14,10 @@ import net.torvald.unicode.getKeycapPC
/**
* 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(
toggleKeyLiteral = if (full == null) "control_key_inventory" else null,
toggleButtonLiteral = if (full == null) "control_gamepad_start" else null
toggleKeyLiteral = if (inventoryUI == null) "control_key_inventory" else null,
toggleButtonLiteral = if (inventoryUI == null) "control_gamepad_start" else null
) {
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 navbarY = posY1
private val navbarX = full!!.transitionalCraftingUI.itemListCraftable.navRemoCon.posX + 12
private val navbarY = full!!.transitionalCraftingUI.itemListCraftable.navRemoCon.posY - 8
private val navbarX = parentContainer.transitionalCraftingUI.itemListCraftable.navRemoCon.posX + 12
private val navbarY = parentContainer.transitionalCraftingUI.itemListCraftable.navRemoCon.posY - 8
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 panelY = navbarY
@@ -61,8 +61,7 @@ class UITechView(val full: UIInventoryFull?, private val colourTheme: InventoryC
highlightable = true
).also {
it.clickOnceListener = { _, _ ->
full?.transitionPanel?.setLeftUIto(0)
full?.transitionPanel?.uis?.get(0)?.show()
parentContainer.showCraftingUI()
it.highlighted = false
}
}

View File

@@ -1,14 +1,18 @@
package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.CreditSingleton
import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.ui.*
import java.util.TreeMap
import net.torvald.terrarum.ui.Toolkit
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() {
init {
@@ -90,11 +94,16 @@ class UISystemInfo(val remoCon: UIRemoCon) : UICanvas() {
private var uptime: Long = 0L
init {
// auto resize for fullscreen
val disp = Lwjgl3ApplicationConfiguration.getDisplayMode(Lwjgl3ApplicationConfiguration.getPrimaryMonitor())
v.add("${App.GAME_NAME}" to App.getVERSION_STRING())
v.add("JRE" to System.getProperty("java.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("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("Architecture" to App.systemArch)
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.gameitems.GameItem
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.ui.UIItemInventoryCellCommonRes.tooltipShowing
import net.torvald.terrarum.ui.*
@@ -36,7 +37,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
override fun getNegotiator() = negotiator
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 itemListChest: UIItemInventoryItemGrid
@@ -155,7 +156,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
itemListChest.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
}

View File

@@ -332,16 +332,16 @@ internal object TerragenTest : NoiseMaker {
Block.STONE_MARBLE to Color(0.8f, 0.8f, 0.8f, 1f)
)
private val COPPER_ORE = 0//x00e9c8ff.toInt()
private val IRON_ORE = 0//xff7e74ff.toInt()
private val COAL_ORE = 0//x383314ff.toInt()
private val ZINC_ORE = 0//xefde76ff.toInt()
private val TIN_ORE = 0//xcd8b62ff.toInt()
private val GOLD_ORE = 0//xffcc00ff.toInt()
private val SILVER_ORE = 0//xd5d9f9ff.toInt()
private val LEAD_ORE = 0//xff9300ff.toInt()
private val QUARTZ = 0//x55ff33ff.toInt()
private val AMETHYST = 0//xee77ffff.toInt()
private val COPPER_ORE = 0x00e9c8ff.toInt()
private val IRON_ORE = 0xff7e74ff.toInt()
private val COAL_ORE = 0x383314ff.toInt()
private val ZINC_ORE = 0xefde76ff.toInt()
private val TIN_ORE = 0xcd8b62ff.toInt()
private val GOLD_ORE = 0xffcc00ff.toInt()
private val SILVER_ORE = 0xd5d9f9ff.toInt()
private val LEAD_ORE = 0xff9300ff.toInt()
private val QUARTZ = 0x55ff33ff.toInt()
private val AMETHYST = 0xee77ffff.toInt()
private val ROCKSALT = 0xff00ffff.toInt()
private val NITRE = 0xdbd6a1ff.toInt()
@@ -684,7 +684,7 @@ internal object TerragenTest : NoiseMaker {
Joise(groundScalingCached),
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: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: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)),

View File

@@ -3,11 +3,8 @@ package net.torvald.terrarum.utils
import com.badlogic.gdx.Gdx
import net.torvald.terrarum.App
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.net.URL
/**
* Created by minjaesong on 2016-07-31.
@@ -15,7 +12,7 @@ import java.io.File
object Clipboard {
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) {
Gdx.app.clipboard.contents = s
@@ -31,4 +28,11 @@ object OpenFile {
if (IS_MACOS) return // at this point macOS might as well be a bane of existence for "some" devs Apple fanboys think they are not worthy of existence
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.
// What about others? We just waste 3/4 of the framebuffer
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
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