mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-09 01:54:04 +09:00
Compare commits
143 Commits
v0.3.3
...
v0.4.0-23w
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4510cbb617 | ||
|
|
2f11988353 | ||
|
|
beb7f1fb73 | ||
|
|
31b328fb48 | ||
|
|
797bad3014 | ||
|
|
5d32e6da33 | ||
|
|
bf2826438f | ||
|
|
e4dc3ac146 | ||
|
|
19f08de756 | ||
|
|
94a207d72a | ||
|
|
3cc51aa774 | ||
|
|
6f0f756fe4 | ||
|
|
37138656f8 | ||
|
|
026cfa5284 | ||
|
|
31e19874ae | ||
|
|
f2974fc854 | ||
|
|
a3e0f7b0b3 | ||
|
|
98c94017ba | ||
|
|
4bea5e9bf9 | ||
|
|
79ffaf6294 | ||
|
|
cada008fca | ||
|
|
46234d3d9d | ||
|
|
eaef2f0c6a | ||
|
|
6ae39d38e3 | ||
|
|
1128fb7f0e | ||
|
|
3acefebfcb | ||
|
|
1ddd012e19 | ||
|
|
4cffe64286 | ||
|
|
8a1dfbeedd | ||
|
|
47a7e55910 | ||
|
|
1aa00d564d | ||
|
|
4c04267cb8 | ||
|
|
b39a4bd008 | ||
|
|
b49556a5a1 | ||
|
|
9bb7ab6956 | ||
|
|
b0bdfd9f43 | ||
|
|
2be8bb2aea | ||
|
|
6b24182de2 | ||
|
|
15f27726b8 | ||
|
|
cbbe5d3e34 | ||
|
|
706f5ac507 | ||
|
|
aef55bdc22 | ||
|
|
fa21800541 | ||
|
|
8d23714832 | ||
|
|
ef6aa842c8 | ||
|
|
0079bc5378 | ||
|
|
3f3e4ad2e7 | ||
|
|
4c09588dc2 | ||
|
|
3764ee21e9 | ||
|
|
f199307353 | ||
|
|
4244a2c395 | ||
|
|
6df348bf86 | ||
|
|
b8b0611479 | ||
|
|
4de7722fc3 | ||
|
|
4262dbec5e | ||
|
|
868e41ee70 | ||
|
|
f07182dfb6 | ||
|
|
56974eeb8c | ||
|
|
757207cf9b | ||
|
|
cc5b9616fe | ||
|
|
f7c32e74cd | ||
|
|
33e93b8e10 | ||
|
|
acae5dab8b | ||
|
|
991a16e6a7 | ||
|
|
76d6579ce9 | ||
|
|
208bf79353 | ||
|
|
00f8d8f850 | ||
|
|
0f82a67a63 | ||
|
|
23a78fc345 | ||
|
|
ffac61fbc5 | ||
|
|
19f1eb2278 | ||
|
|
012d3482dc | ||
|
|
2bd54c8316 | ||
|
|
1667e622bd | ||
|
|
9da2be0b17 | ||
|
|
c83c83a395 | ||
|
|
8e2f3254ff | ||
|
|
98813fb4df | ||
|
|
9a233b8c55 | ||
|
|
98d7c9f326 | ||
|
|
43cb9ec00e | ||
|
|
074c27c6cc | ||
|
|
5322cb7b2b | ||
|
|
a8b44c1cac | ||
|
|
a5a2c98041 | ||
|
|
18ab292e24 | ||
|
|
9145acf741 | ||
|
|
228b0962d6 | ||
|
|
18b2b3c8d6 | ||
|
|
d1d75b88ca | ||
|
|
d9deabb644 | ||
|
|
a432099f19 | ||
|
|
5806388bee | ||
|
|
56d915cd71 | ||
|
|
143f789ea1 | ||
|
|
1b2940637c | ||
|
|
872ab8d946 | ||
|
|
ed2a46e1a6 | ||
|
|
d53ab6ffee | ||
|
|
69345eab57 | ||
|
|
6e90d3521b | ||
|
|
e88b595320 | ||
|
|
f37a28eb17 | ||
|
|
d57f23d4f1 | ||
|
|
6634a8dccb | ||
|
|
647c7ea865 | ||
|
|
90eb033431 | ||
|
|
20f2f2f7b1 | ||
|
|
1af172d354 | ||
|
|
35c46d9a91 | ||
|
|
8613d804e7 | ||
|
|
1cce4e6ee2 | ||
|
|
0a65794756 | ||
|
|
d5074e30eb | ||
|
|
228c9b8127 | ||
|
|
3c79586410 | ||
|
|
d546b081f0 | ||
|
|
4362966128 | ||
|
|
108c4d3e3f | ||
|
|
fd65541c35 | ||
|
|
65997764e6 | ||
|
|
d8abec381b | ||
|
|
58fa1dd56c | ||
|
|
93f1430c5c | ||
|
|
93d33b793c | ||
|
|
3a3d789777 | ||
|
|
6bf535e968 | ||
|
|
00ca1d3e1a | ||
|
|
552cfd5f06 | ||
|
|
e63300339e | ||
|
|
1e15719b9c | ||
|
|
64d30728ff | ||
|
|
3b32242a2b | ||
|
|
26936fde09 | ||
|
|
caffdbf861 | ||
|
|
e76ff58b3e | ||
|
|
8f1ca485f6 | ||
|
|
23c445f014 | ||
|
|
d9218a2dd6 | ||
|
|
dd1e53f761 | ||
|
|
d8cafe7f12 | ||
|
|
ae3a6e9c61 | ||
|
|
f5bc2c9be3 |
Binary file not shown.
Binary file not shown.
BIN
assets/graphics/logo.png
LFS
Normal file
BIN
assets/graphics/logo.png
LFS
Normal file
Binary file not shown.
Binary file not shown.
@@ -32,7 +32,9 @@
|
|||||||
"MENU_OPTIONS_BLUR": "Blur",
|
"MENU_OPTIONS_BLUR": "Blur",
|
||||||
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console",
|
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console",
|
||||||
"MENU_OPTIONS_DITHER": "Dithering",
|
"MENU_OPTIONS_DITHER": "Dithering",
|
||||||
|
"MENU_OPTIONS_ENABLE_SCRIPT_MODS": "Enable Script Mods",
|
||||||
"MENU_OPTIONS_JVM_HEAP_MAX": "Max Heap Memory",
|
"MENU_OPTIONS_JVM_HEAP_MAX": "Max Heap Memory",
|
||||||
|
"MENU_OPTIONS_LIGHT_UPDATE_PASSES": "Light Calculation Depth",
|
||||||
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "Show notification for",
|
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "Show notification for",
|
||||||
"MENU_OPTIONS_PARTICLES": "Particles",
|
"MENU_OPTIONS_PARTICLES": "Particles",
|
||||||
"MENU_OPTIONS_PERFORMANCE": "Performance",
|
"MENU_OPTIONS_PERFORMANCE": "Performance",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ERROR_FILE_NOT_FOUND": "File not found.",
|
"ERROR_FILE_NOT_FOUND": "File not found.",
|
||||||
|
"ERROR_SAVE_IS_FROM_NEWER_VERSION": "Saved game is newer than the current game version.",
|
||||||
"GAME_32BIT_WARNING1": "It looks like you’re running a 32-Bit version of Java.",
|
"GAME_32BIT_WARNING1": "It looks like you’re running a 32-Bit version of Java.",
|
||||||
"GAME_32BIT_WARNING2": "Please download and install the latest 64-Bit Java at:",
|
"GAME_32BIT_WARNING2": "Please download and install the latest 64-Bit Java at:",
|
||||||
"GAME_32BIT_WARNING3": "https://www.java.com/en/download/",
|
"GAME_32BIT_WARNING3": "https://www.java.com/en/download/",
|
||||||
@@ -7,11 +8,18 @@
|
|||||||
"GAME_APPLE_ROSETTA_WARNING2": "Please use the native build for improved performance and gameplay experiences.",
|
"GAME_APPLE_ROSETTA_WARNING2": "Please use the native build for improved performance and gameplay experiences.",
|
||||||
"APP_NOMODULE_1": "No Module is currently loaded.",
|
"APP_NOMODULE_1": "No Module is currently loaded.",
|
||||||
"APP_NOMODULE_2": "Please configure your Load Order and restart:",
|
"APP_NOMODULE_2": "Please configure your Load Order and restart:",
|
||||||
"MENU_LABEL_KEYCONFIG_HELP1": "Click On the Keycap to Assign Actions",
|
|
||||||
"GAME_PREV_SAVE_WAS_LOADED1": "The most recently saved game was corrupted.",
|
"GAME_PREV_SAVE_WAS_LOADED1": "The most recently saved game was corrupted.",
|
||||||
"GAME_PREV_SAVE_WAS_LOADED2": "The previously saved game was loaded.",
|
"GAME_PREV_SAVE_WAS_LOADED2": "The previously saved game was loaded.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE1": "The Autosave is more recent than the manual save.",
|
"GAME_MORE_RECENT_AUTOSAVE1": "The Autosave is more recent than the manual save.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE2": "Please select the saved game you wish to play:",
|
"GAME_MORE_RECENT_AUTOSAVE2": "Please select the saved game you wish to play:",
|
||||||
|
"MENU_IO_LOAD_UPDATING_BLOCK_MAPPINGS": "Updating Block Mappings...",
|
||||||
|
"MENU_IO_WORLDGEN_CARVING_EARTH": "Carving Earth...",
|
||||||
|
"MENU_IO_WORLDGEN_PAINTING_GREEN": "Painting Green...",
|
||||||
|
"MENU_IO_WORLDGEN_GROWING_MINERALS": "Growing Minerals...",
|
||||||
|
"MENU_IO_WORLDGEN_POSITIONING_ROCKS": "Positioning Rocks...",
|
||||||
|
"MENU_IO_WORLDGEN_RETICULATING_SPLINES": "Reticulating Splines...",
|
||||||
|
"MENU_LABEL_KEYCONFIG_HELP1": "Click On the Keycap to Assign Actions",
|
||||||
"MENU_LABEL_SAVE_WILL_BE_DELETED": "The selected save file will be deleted.",
|
"MENU_LABEL_SAVE_WILL_BE_DELETED": "The selected save file will be deleted.",
|
||||||
"MENU_LABEL_UNSAVED_PROGRESS_WILL_BE_LOST": "Unsaved progress will be lost."
|
"MENU_LABEL_UNSAVED_PROGRESS_WILL_BE_LOST": "Unsaved progress will be lost.",
|
||||||
|
"MENU_LABEL_WARN_ACE": "Script mods may damage your game or result in other unexpected behaviour.\nOnly use the mods you know they can be trusted."
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,9 @@
|
|||||||
"MENU_OPTIONS_BLUR": "흐림",
|
"MENU_OPTIONS_BLUR": "흐림",
|
||||||
"MENU_OPTIONS_DEBUG_CONSOLE": "디버그 콘솔",
|
"MENU_OPTIONS_DEBUG_CONSOLE": "디버그 콘솔",
|
||||||
"MENU_OPTIONS_DITHER": "디더링",
|
"MENU_OPTIONS_DITHER": "디더링",
|
||||||
|
"MENU_OPTIONS_ENABLE_SCRIPT_MODS": "스크립트 모드 활성화",
|
||||||
"MENU_OPTIONS_JVM_HEAP_MAX": "최대 힙 메모리",
|
"MENU_OPTIONS_JVM_HEAP_MAX": "최대 힙 메모리",
|
||||||
|
"MENU_OPTIONS_LIGHT_UPDATE_PASSES": "빛 계산 반복 횟수",
|
||||||
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "알림 표시 시간",
|
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "알림 표시 시간",
|
||||||
"MENU_OPTIONS_PARTICLES": "입자 수",
|
"MENU_OPTIONS_PARTICLES": "입자 수",
|
||||||
"MENU_OPTIONS_PERFORMANCE": "성능",
|
"MENU_OPTIONS_PERFORMANCE": "성능",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ERROR_FILE_NOT_FOUND": "파일을 찾을 수 없습니다.",
|
"ERROR_FILE_NOT_FOUND": "파일을 찾을 수 없습니다.",
|
||||||
|
"ERROR_SAVE_IS_FROM_NEWER_VERSION": "저장된 게임이 현재 게임보다 더 최신입니다.",
|
||||||
"GAME_32BIT_WARNING1": "32비트 버전의 Java를 사용중인 것 같습니다.",
|
"GAME_32BIT_WARNING1": "32비트 버전의 Java를 사용중인 것 같습니다.",
|
||||||
"GAME_32BIT_WARNING2": "아래 링크에서 최신 64비트 Java를 내려받아 설치해주세요.",
|
"GAME_32BIT_WARNING2": "아래 링크에서 최신 64비트 Java를 내려받아 설치해주세요.",
|
||||||
"GAME_32BIT_WARNING3": "https://www.java.com/ko/download/",
|
"GAME_32BIT_WARNING3": "https://www.java.com/ko/download/",
|
||||||
@@ -7,11 +8,18 @@
|
|||||||
"GAME_APPLE_ROSETTA_WARNING2": "최적의 성능과 게임 경험을 위해 Apple Silicon용 빌드의 게임을 이용해 주십시오.",
|
"GAME_APPLE_ROSETTA_WARNING2": "최적의 성능과 게임 경험을 위해 Apple Silicon용 빌드의 게임을 이용해 주십시오.",
|
||||||
"APP_NOMODULE_1": "현재 불러와진 모듈이 없습니다.",
|
"APP_NOMODULE_1": "현재 불러와진 모듈이 없습니다.",
|
||||||
"APP_NOMODULE_2": "다음의 파일에서 불러오기 순서를 설정하고 게임을 재시작하십시오.",
|
"APP_NOMODULE_2": "다음의 파일에서 불러오기 순서를 설정하고 게임을 재시작하십시오.",
|
||||||
"MENU_LABEL_KEYCONFIG_HELP1": "키캡을 클릭해 컨트롤을 배정하십시오",
|
|
||||||
"GAME_PREV_SAVE_WAS_LOADED1": "가장 최근에 저장된 게임이 손상되었습니다.",
|
"GAME_PREV_SAVE_WAS_LOADED1": "가장 최근에 저장된 게임이 손상되었습니다.",
|
||||||
"GAME_PREV_SAVE_WAS_LOADED2": "이전에 저장된 게임을 불러왔습니다.",
|
"GAME_PREV_SAVE_WAS_LOADED2": "이전에 저장된 게임을 불러왔습니다.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE1": "자동 저장된 게임이 수동으로 저장한 게임보다 더 최신입니다.",
|
"GAME_MORE_RECENT_AUTOSAVE1": "자동 저장된 게임이 수동으로 저장한 게임보다 더 최신입니다.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE2": "불러올 게임을 선택해 주십시오.",
|
"GAME_MORE_RECENT_AUTOSAVE2": "불러올 게임을 선택해 주십시오.",
|
||||||
|
"MENU_IO_LOAD_UPDATING_BLOCK_MAPPINGS": "Updating Block Mappings...",
|
||||||
|
"MENU_IO_WORLDGEN_CARVING_EARTH": "Carving Earth...",
|
||||||
|
"MENU_IO_WORLDGEN_PAINTING_GREEN": "Painting Green...",
|
||||||
|
"MENU_IO_WORLDGEN_GROWING_MINERALS": "Growing Minerals...",
|
||||||
|
"MENU_IO_WORLDGEN_POSITIONING_ROCKS": "Positioning Rocks...",
|
||||||
|
"MENU_IO_WORLDGEN_RETICULATING_SPLINES": "Reticulating Splines...",
|
||||||
|
"MENU_LABEL_KEYCONFIG_HELP1": "키캡을 클릭해 컨트롤을 배정하십시오",
|
||||||
"MENU_LABEL_SAVE_WILL_BE_DELETED": "선택된 세이브가 삭제됩니다.",
|
"MENU_LABEL_SAVE_WILL_BE_DELETED": "선택된 세이브가 삭제됩니다.",
|
||||||
"MENU_LABEL_UNSAVED_PROGRESS_WILL_BE_LOST": "저장하지 않은 진행 상황을 잃게 됩니다."
|
"MENU_LABEL_UNSAVED_PROGRESS_WILL_BE_LOST": "저장하지 않은 진행 상황을 잃게 됩니다.",
|
||||||
|
"MENU_LABEL_WARN_ACE": "스크립트 모드는 게임을 손상시키거나 다른 예상치 못한 결과를 가져올 수 있습니다.\n신뢰할 수 있는 모드만을 사용하십시오."
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/mods/basegame/blocks/112.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/112.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
assets/mods/basegame/blocks/273.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/273.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/274.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/274.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/275.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/275.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,25 +1,25 @@
|
|||||||
"id";"drop";"spawn";"name";"shdr";"shdg";"shdb";"shduv";"str";"dsty";"mate";"solid";"wall";"grav";"dlfn";"fv";"fr";"lumr";"lumg";"lumb";"lumuv";"colour";"vscs";"refl";"tags"
|
"id";"drop";"spawn";"name";"shdr";"shdg";"shdb";"shduv";"str";"dsty";"mate";"solid";"wall";"grav";"dlfn";"fv";"fr";"lumr";"lumg";"lumb";"lumuv";"colour";"vscs";"refl";"tags"
|
||||||
"0";"0";"0";"BLOCK_AIR";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INCONSEQUENTIAL,AIR"
|
"0";"0";"0";"BLOCK_AIR";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"AIIR";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INCONSEQUENTIAL,AIR,NORANDTILE"
|
||||||
"1";"0";"0";"BLOCK_UPDATE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INTERNAL"
|
"1";"0";"0";"BLOCK_UPDATE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"AIIR";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INTERNAL,NORANDTILE"
|
||||||
"16";"17";"17";"BLOCK_STONE";"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"
|
"16";"17";"17";"BLOCK_STONE";"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
"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,NATURAL"
|
"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,NATURAL"
|
||||||
"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"
|
"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"
|
||||||
"32";"32";"32";"BLOCK_DIRT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL"
|
"32";"32";"32";"BLOCK_DIRT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL"
|
||||||
"33";"32";"32";"BLOCK_GRASS";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
"33";"32";"32";"BLOCK_GRASS";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"34";"34";"34";"BLOCK_GRASSWALL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
"34";"34";"34";"BLOCK_GRASSWALL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"35";"35";"35";"BLOCK_FOLIAGE_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LEAVES,NATURAL"
|
#"35";"35";"35";"BLOCK_FOLIAGE_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"36";"36";"36";"BLOCK_FOLIAGE_LIME";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LEAVES,NATURAL"
|
#"36";"36";"36";"BLOCK_FOLIAGE_LIME";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"37";"37";"37";"BLOCK_FOLIAGE_GOLD";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LEAVES,NATURAL"
|
#"37";"37";"37";"BLOCK_FOLIAGE_GOLD";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"38";"38";"38";"BLOCK_FOLIAGE_RED";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LEAVES,NATURAL"
|
#"38";"38";"38";"BLOCK_FOLIAGE_RED";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"39";"39";"39";"BLOCK_FOLIAGE_ICEBLUE";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LEAVES,NATURAL"
|
#"39";"39";"39";"BLOCK_FOLIAGE_ICEBLUE";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"40";"40";"40";"BLOCK_FOLIAGE_PURPLE";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LEAVES,NATURAL"
|
#"40";"40";"40";"BLOCK_FOLIAGE_PURPLE";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||||
"48";"48";"48";"BLOCK_PLANK_NORMAL";"0.1252";"0.1252";"0.1252";"0.1252";"16";"740";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD"
|
"48";"48";"48";"BLOCK_PLANK_NORMAL";"0.1252";"0.1252";"0.1252";"0.1252";"16";"740";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD,NORANDTILE"
|
||||||
"49";"49";"49";"BLOCK_PLANK_EBONY";"0.1252";"0.1252";"0.1252";"0.1252";"19";"1200";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD"
|
"49";"49";"49";"BLOCK_PLANK_EBONY";"0.1252";"0.1252";"0.1252";"0.1252";"19";"1200";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD,NORANDTILE"
|
||||||
"50";"50";"50";"BLOCK_PLANK_BIRCH";"0.1252";"0.1252";"0.1252";"0.1252";"15";"670";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD"
|
"50";"50";"50";"BLOCK_PLANK_BIRCH";"0.1252";"0.1252";"0.1252";"0.1252";"15";"670";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD,NORANDTILE"
|
||||||
"51";"51";"51";"BLOCK_PLANK_ROSEWOOD";"0.1252";"0.1252";"0.1252";"0.1252";"17";"900";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD"
|
"51";"51";"51";"BLOCK_PLANK_ROSEWOOD";"0.1252";"0.1252";"0.1252";"0.1252";"17";"900";"WOOD";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"WOOD,NORANDTILE"
|
||||||
"64";"64";"64";"BLOCK_TRUNK_NORMAL";"0.0312";"0.0312";"0.0312";"0.0312";"16";"740";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
"64";"64";"64";"BLOCK_TRUNK_NORMAL";"0.0312";"0.0312";"0.0312";"0.0312";"16";"740";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
||||||
"65";"65";"65";"BLOCK_TRUNK_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"19";"1200";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
"65";"65";"65";"BLOCK_TRUNK_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"19";"1200";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
||||||
"66";"66";"66";"BLOCK_TRUNK_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"15";"670";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
"66";"66";"66";"BLOCK_TRUNK_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"15";"670";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
||||||
@@ -32,23 +32,27 @@
|
|||||||
"85";"85";"85";"BLOCK_SAND_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
"85";"85";"85";"BLOCK_SAND_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
||||||
"96";"96";"96";"BLOCK_GRAVEL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
"96";"96";"96";"BLOCK_GRAVEL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
||||||
"97";"97";"97";"BLOCK_GRAVEL_GREY";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
"97";"97";"97";"BLOCK_GRAVEL_GREY";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
||||||
"112";"112";"112";"BLOCK_ORE_MALACHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
"112";"112";"112";"BLOCK_FOLIAGE_NORMAL";"0.0312";"0.0312";"0.0312";"0.0312";"16";"740";"GRSS";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,LEAVES,NATURAL"
|
||||||
"113";"113";"113";"BLOCK_ORE_HEMATITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
#"113";"113";"113";"BLOCK_FOLIAGE_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"19";"1200";"GRSS";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,LEAVES,NATURAL"
|
||||||
"114";"114";"114";"BLOCK_ORE_NATURAL_GOLD";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
#"114";"114";"114";"BLOCK_FOLIAGE_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"15";"670";"GRSS";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,LEAVES,NATURAL"
|
||||||
"115";"115";"115";"BLOCK_ORE_COAL";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
#"115";"115";"115";"BLOCK_FOLIAGE_ROSEWOOD";"0.0312";"0.0312";"0.0312";"0.0312";"17";"900";"GRSS";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,LEAVES,NATURAL"
|
||||||
"116";"116";"116";"BLOCK_ORE_SPHALERITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
#"112";"112";"112";"BLOCK_ORE_MALACHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
||||||
"117";"117";"117";"BLOCK_ORE_RUTILE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
#"113";"113";"113";"BLOCK_ORE_HEMATITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
||||||
"128";"128";"128";"BLOCK_GEM_RUBY";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
#"114";"114";"114";"BLOCK_ORE_NATURAL_GOLD";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
||||||
"129";"129";"129";"BLOCK_GEM_EMERALD";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
#"115";"115";"115";"BLOCK_ORE_COAL";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
||||||
"130";"130";"130";"BLOCK_GEM_SAPPHIRE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
#"116";"116";"116";"BLOCK_ORE_SPHALERITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
||||||
"131";"131";"131";"BLOCK_GEM_TOPAZ";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
#"117";"117";"117";"BLOCK_ORE_RUTILE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
||||||
"132";"132";"132";"BLOCK_GEM_DIAMOND";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
#"128";"128";"128";"BLOCK_GEM_RUBY";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
"133";"133";"133";"BLOCK_GEM_AMETHYST";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
#"129";"129";"129";"BLOCK_GEM_EMERALD";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
"134";"134";"134";"BLOCK_GEM_QUARTZ";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
#"130";"130";"130";"BLOCK_GEM_SAPPHIRE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
|
#"131";"131";"131";"BLOCK_GEM_TOPAZ";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
|
#"132";"132";"132";"BLOCK_GEM_DIAMOND";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
|
#"133";"133";"133";"BLOCK_GEM_AMETHYST";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
|
#"134";"134";"134";"BLOCK_GEM_QUARTZ";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
"144";"144";"144";"BLOCK_SNOW";"0.1252";"0.1252";"0.1252";"0.1252";"24";"500";"SNOW";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"SNOW,NATURAL,COLD"
|
"144";"144";"144";"BLOCK_SNOW";"0.1252";"0.1252";"0.1252";"0.1252";"24";"500";"SNOW";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"SNOW,NATURAL,COLD"
|
||||||
"145";"N/A";"N/A";"BLOCK_ICE_FRAGILE";"0.0508";"0.0508";"0.0508";"0.0508";"5";"930";"ICEI";"1";"0";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL,FRAGILE,COLD"
|
"145";"N/A";"N/A";"BLOCK_ICE_FRAGILE";"0.0508";"0.0508";"0.0508";"0.0508";"5";"930";"ICEI";"1";"0";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL,FRAGILE,COLD"
|
||||||
"146";"146";"146";"BLOCK_ICE_NATURAL";"0.1016";"0.1016";"0.1016";"0.1016";"35";"930";"ICEI";"1";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL,COLD"
|
#"146";"146";"146";"BLOCK_ICE_NATURAL";"0.1016";"0.1016";"0.1016";"0.1016";"35";"930";"ICEI";"1";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL,COLD"
|
||||||
"147";"147";"147";"BLOCK_ICE_CLEAR_MAGICAL";"0.1252";"0.1252";"0.1252";"0.1252";"48";"3720";"ICEX";"1";"1";"N/A";"0";"0";"4";"0.0744";"0.1252";"0.2268";"0.0000";"N/A";"N/A";"0.0";"ICE,COLD"
|
#"147";"147";"147";"BLOCK_ICE_CLEAR_MAGICAL";"0.1252";"0.1252";"0.1252";"0.1252";"48";"3720";"ICEX";"1";"1";"N/A";"0";"0";"4";"0.0744";"0.1252";"0.2268";"0.0000";"N/A";"N/A";"0.0";"ICE,COLD"
|
||||||
"148";"148";"148";"BLOCK_GLASS_CRUDE";"0.0876";"0.0424";"0.0876";"0.1252";"5";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS"
|
"148";"148";"148";"BLOCK_GLASS_CRUDE";"0.0876";"0.0424";"0.0876";"0.1252";"5";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
||||||
@@ -57,82 +61,80 @@
|
|||||||
"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"
|
"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"
|
||||||
"164";"164";"164";"BLOCK_PLATFORM_ROSEWOOD";"0.0312";"0.0312";"0.0312";"0.0312";"5";"900";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM"
|
"164";"164";"164";"BLOCK_PLATFORM_ROSEWOOD";"0.0312";"0.0312";"0.0312";"0.0312";"5";"900";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM"
|
||||||
"176";"176";"176";"BLOCK_TORCH";"0.0312";"0.0312";"0.0312";"0.0312";"1";"800";"FXTR";"0";"0";"N/A";"1";"0";"16";"1.0000";"0.6372";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"176";"176";"176";"BLOCK_TORCH";"0.0312";"0.0312";"0.0312";"0.0312";"1";"800";"FXTR";"0";"0";"N/A";"1";"0";"16";"1.0000";"0.6372";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
||||||
"177";"177";"177";"BLOCK_TORCH_FROST";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1100";"FXTR";"0";"0";"N/A";"1";"0";"16";"0.3048";"0.4848";"1.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
#"177";"177";"177";"BLOCK_TORCH_FROST";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1100";"FXTR";"0";"0";"N/A";"1";"0";"16";"0.3048";"0.4848";"1.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
||||||
"192";"176";"176";"BLOCK_TORCH";"0.0312";"0.0312";"0.0312";"0.0312";"1";"800";"FXTR";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"192";"176";"176";"BLOCK_TORCH";"0.0312";"0.0312";"0.0312";"0.0312";"1";"800";"FXTR";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
||||||
"193";"177";"177";"BLOCK_TORCH_FROST";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1100";"FXTR";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
#"193";"177";"177";"BLOCK_TORCH_FROST";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1100";"FXTR";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
||||||
"208";"208";"208";"BLOCK_ILLUMINATOR_WHITE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.9270";"0.9414";"0.8519";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"208";"208";"208";"BLOCK_ILLUMINATOR_WHITE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.9270";"0.9414";"0.8519";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"209";"209";"209";"BLOCK_ILLUMINATOR_YELLOW";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"1.0000";"0.8408";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"209";"209";"209";"BLOCK_ILLUMINATOR_YELLOW";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"1.0000";"0.8408";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"210";"210";"210";"BLOCK_ILLUMINATOR_ORANGE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"1.0000";"0.5294";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"210";"210";"210";"BLOCK_ILLUMINATOR_ORANGE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"1.0000";"0.5294";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"211";"211";"211";"BLOCK_ILLUMINATOR_RED";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.9188";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"211";"211";"211";"BLOCK_ILLUMINATOR_RED";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.9188";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"212";"212";"212";"BLOCK_ILLUMINATOR_FUCHSIA";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.9188";"0.0000";"0.7156";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"212";"212";"212";"BLOCK_ILLUMINATOR_FUCHSIA";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.9188";"0.0000";"0.7156";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"213";"213";"213";"BLOCK_ILLUMINATOR_PURPLE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.7156";"0.0000";"0.9188";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"213";"213";"213";"BLOCK_ILLUMINATOR_PURPLE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.7156";"0.0000";"0.9188";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"214";"214";"214";"BLOCK_ILLUMINATOR_BLUE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.1996";"0.9188";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"214";"214";"214";"BLOCK_ILLUMINATOR_BLUE";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.1996";"0.9188";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"215";"215";"215";"BLOCK_ILLUMINATOR_CYAN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.4621";"1.4188";"1.2368";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"215";"215";"215";"BLOCK_ILLUMINATOR_CYAN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.4621";"1.4188";"1.2368";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"216";"216";"216";"BLOCK_ILLUMINATOR_GREEN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.2112";"1.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"216";"216";"216";"BLOCK_ILLUMINATOR_GREEN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.2112";"1.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"217";"217";"217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.1252";"0.4068";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"217";"217";"217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.1252";"0.4068";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"218";"218";"218";"BLOCK_ILLUMINATOR_BROWN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.3324";"0.1252";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"218";"218";"218";"BLOCK_ILLUMINATOR_BROWN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.3324";"0.1252";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"219";"219";"219";"BLOCK_ILLUMINATOR_TAN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.5864";"0.4068";"0.2032";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"219";"219";"219";"BLOCK_ILLUMINATOR_TAN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.5864";"0.4068";"0.2032";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"220";"220";"220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.7392";"0.7392";"0.7392";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"220";"220";"220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.7392";"0.7392";"0.7392";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"221";"221";"221";"BLOCK_ILLUMINATOR_GREY_MED";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.4576";"0.4576";"0.4576";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"221";"221";"221";"BLOCK_ILLUMINATOR_GREY_MED";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.4576";"0.4576";"0.4576";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"222";"222";"222";"BLOCK_ILLUMINATOR_GREY_DARK";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.2540";"0.2540";"0.2540";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"222";"222";"222";"BLOCK_ILLUMINATOR_GREY_DARK";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.2540";"0.2540";"0.2540";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"223";"223";"223";"BLOCK_ILLUMINATOR_BLACK";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.2140";"0.0000";"0.4932";"3.7499";"N/A";"N/A";"0.0";"LIGHT"
|
"223";"223";"223";"BLOCK_ILLUMINATOR_BLACK";"0.0312";"0.0312";"0.0312";"0.0312";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.2140";"0.0000";"0.4932";"3.7499";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"224";"208";"208";"BLOCK_ILLUMINATOR_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"224";"208";"208";"BLOCK_ILLUMINATOR_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"225";"209";"209";"BLOCK_ILLUMINATOR_YELLOW";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"225";"209";"209";"BLOCK_ILLUMINATOR_YELLOW";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"226";"210";"210";"BLOCK_ILLUMINATOR_ORANGE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"226";"210";"210";"BLOCK_ILLUMINATOR_ORANGE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"227";"211";"211";"BLOCK_ILLUMINATOR_RED";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"227";"211";"211";"BLOCK_ILLUMINATOR_RED";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"228";"212";"212";"BLOCK_ILLUMINATOR_FUCHSIA";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"228";"212";"212";"BLOCK_ILLUMINATOR_FUCHSIA";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"229";"213";"213";"BLOCK_ILLUMINATOR_PURPLE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"229";"213";"213";"BLOCK_ILLUMINATOR_PURPLE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"230";"214";"214";"BLOCK_ILLUMINATOR_BLUE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"230";"214";"214";"BLOCK_ILLUMINATOR_BLUE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"231";"215";"215";"BLOCK_ILLUMINATOR_CYAN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"231";"215";"215";"BLOCK_ILLUMINATOR_CYAN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"232";"216";"216";"BLOCK_ILLUMINATOR_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"232";"216";"216";"BLOCK_ILLUMINATOR_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"233";"217";"217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"233";"217";"217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"234";"218";"218";"BLOCK_ILLUMINATOR_BROWN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"234";"218";"218";"BLOCK_ILLUMINATOR_BROWN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"235";"219";"219";"BLOCK_ILLUMINATOR_TAN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"235";"219";"219";"BLOCK_ILLUMINATOR_TAN";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"236";"220";"220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"236";"220";"220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"237";"221";"221";"BLOCK_ILLUMINATOR_GREY_MED";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"237";"221";"221";"BLOCK_ILLUMINATOR_GREY_MED";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"238";"222";"222";"BLOCK_ILLUMINATOR_GREY_DARK";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"238";"222";"222";"BLOCK_ILLUMINATOR_GREY_DARK";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"239";"223";"223";"BLOCK_ILLUMINATOR_BLACK";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL"
|
"239";"223";"223";"BLOCK_ILLUMINATOR_BLACK";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,UNLIT,INTERNAL,NORANDTILE"
|
||||||
"240";"240";"240";"BLOCK_SANDSTONE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE"
|
"240";"240";"240";"BLOCK_SANDSTONE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE,NORANDTILE"
|
||||||
"241";"241";"241";"BLOCK_SANDSTONE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE"
|
"241";"241";"241";"BLOCK_SANDSTONE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE,NORANDTILE"
|
||||||
"242";"242";"242";"BLOCK_SANDSTONE_RED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE"
|
"242";"242";"242";"BLOCK_SANDSTONE_RED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE,NORANDTILE"
|
||||||
"243";"243";"243";"BLOCK_SANDSTONE_DESERT";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE"
|
"243";"243";"243";"BLOCK_SANDSTONE_DESERT";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE,NORANDTILE"
|
||||||
"244";"244";"244";"BLOCK_SANDSTONE_BLACK";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE"
|
"244";"244";"244";"BLOCK_SANDSTONE_BLACK";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE,NORANDTILE"
|
||||||
"245";"245";"245";"BLOCK_SANDSTONE_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE"
|
"245";"245";"245";"BLOCK_SANDSTONE_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"48";"1900";"ROCK";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.16";"STONE,NORANDTILE"
|
||||||
"256";"256";"256";"BLOCK_LANTERN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1800";"FXTR";"0";"0";"N/A";"0";"0";"16";"1.0000";"0.6372";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"256";"256";"256";"BLOCK_LANTERN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1800";"FXTR";"0";"0";"N/A";"0";"0";"16";"1.0000";"0.6372";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"257";"257";"257";"BLOCK_SUNSTONE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"ROCK";"1";"0";"N/A";"2";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"257";"257";"257";"BLOCK_SUNSTONE";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"ROCK";"1";"0";"N/A";"2";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT,NORANDTILE"
|
||||||
"258";"258";"258";"BLOCK_DAYLIGHT_CAPACITOR";"0.1252";"0.1252";"0.1252";"0.1252";"1";"2500";"GLAS";"1";"0";"N/A";"3";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"LIGHT"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
"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"
|
"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"
|
||||||
|
|
||||||
"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.0";"THERMOPLASTIC"
|
"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.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"289";"289";"289";"BLOCK_PLASTIC_YELLOW"; "0.0894";"0.0919";"0.1234";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"289";"289";"289";"BLOCK_PLASTIC_YELLOW"; "0.0894";"0.0919";"0.1234";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"290";"290";"290";"BLOCK_PLASTIC_ORANGE"; "0.0892";"0.0981";"0.1240";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"290";"290";"290";"BLOCK_PLASTIC_ORANGE"; "0.0892";"0.0981";"0.1240";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"291";"291";"291";"BLOCK_PLASTIC_RED"; "0.0905";"0.1230";"0.1245";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"291";"291";"291";"BLOCK_PLASTIC_RED"; "0.0905";"0.1230";"0.1245";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"292";"292";"292";"BLOCK_PLASTIC_FUCHSIA"; "0.0905";"0.1237";"0.0941";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"292";"292";"292";"BLOCK_PLASTIC_FUCHSIA"; "0.0905";"0.1237";"0.0941";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"293";"293";"293";"BLOCK_PLASTIC_PURPLE"; "0.0941";"0.1234";"0.0905";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"293";"293";"293";"BLOCK_PLASTIC_PURPLE"; "0.0941";"0.1234";"0.0905";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"294";"294";"294";"BLOCK_PLASTIC_BLUE"; "0.1218";"0.1078";"0.0905";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"294";"294";"294";"BLOCK_PLASTIC_BLUE"; "0.1218";"0.1078";"0.0905";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"295";"295";"295";"BLOCK_PLASTIC_CYAN"; "0.1032";"0.0892";"0.0914";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"295";"295";"295";"BLOCK_PLASTIC_CYAN"; "0.1032";"0.0892";"0.0914";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"296";"296";"296";"BLOCK_PLASTIC_GREEN"; "0.1078";"0.0892";"0.1231";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"296";"296";"296";"BLOCK_PLASTIC_GREEN"; "0.1078";"0.0892";"0.1231";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"297";"297";"297";"BLOCK_PLASTIC_GREEN_DARK"; "0.1109";"0.1010";"0.1240";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"297";"297";"297";"BLOCK_PLASTIC_GREEN_DARK"; "0.1109";"0.1010";"0.1240";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"298";"298";"298";"BLOCK_PLASTIC_BROWN"; "0.1032";"0.1109";"0.1245";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"298";"298";"298";"BLOCK_PLASTIC_BROWN"; "0.1032";"0.1109";"0.1245";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"299";"299";"299";"BLOCK_PLASTIC_TAN"; "0.0967";"0.1010";"0.1078";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"299";"299";"299";"BLOCK_PLASTIC_TAN"; "0.0967";"0.1010";"0.1078";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"300";"300";"300";"BLOCK_PLASTIC_GREY_LIGHT"; "0.0938";"0.0938";"0.0938";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"300";"300";"300";"BLOCK_PLASTIC_GREY_LIGHT"; "0.0938";"0.0938";"0.0938";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"301";"301";"301";"BLOCK_PLASTIC_GREY_MED"; "0.0997";"0.0997";"0.0997";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"301";"301";"301";"BLOCK_PLASTIC_GREY_MED"; "0.0997";"0.0997";"0.0997";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"302";"302";"302";"BLOCK_PLASTIC_GREY_DARK"; "0.1059";"0.1059";"0.1059";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"302";"302";"302";"BLOCK_PLASTIC_GREY_DARK"; "0.1059";"0.1059";"0.1059";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"0";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
"303";"303";"303";"BLOCK_PLASTIC_BLACK"; "0.1197";"0.1197";"0.1197";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"3";"N/A";"N/A";"0.0";"THERMOPLASTIC"
|
"303";"303";"303";"BLOCK_PLASTIC_BLACK"; "0.1197";"0.1197";"0.1197";"0.1752";"36";"660";"PLST";"1";"1";"N/A";"0";"0";"16";"0";"0";"0";"3";"N/A";"N/A";"0.0";"THERMOPLASTIC,NORANDTILE"
|
||||||
|
|
||||||
|
|
||||||
"4090";"N/A";"N/A";"ACTORBLOCK_TILING_PLACEHOLDER";"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";"INTERNAL,ACTORBLOCK,DORENDER"
|
"4090";"N/A";"N/A";"ACTORBLOCK_TILING_PLACEHOLDER";"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";"INTERNAL,ACTORBLOCK,DORENDER,NORANDTILE"
|
||||||
"4091";"N/A";"N/A";"ACTORBLOCK_NO_COLLISION";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"4";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK"
|
"4091";"N/A";"N/A";"ACTORBLOCK_NO_COLLISION";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"4";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK,NORANDTILE"
|
||||||
"4092";"N/A";"N/A";"ACTORBLOCK_FULL_COLLISION";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"1";"0";"N/A";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK"
|
"4092";"N/A";"N/A";"ACTORBLOCK_FULL_COLLISION";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"1";"0";"N/A";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK,NORANDTILE"
|
||||||
"4093";"N/A";"N/A";"ACTORBLOCK_ALLOW_MOVE_DOWN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK,PLATFORM"
|
"4093";"N/A";"N/A";"ACTORBLOCK_ALLOW_MOVE_DOWN";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"16";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK,PLATFORM,NORANDTILE"
|
||||||
"4094";"N/A";"N/A";"ACTORBLOCK_NO_PASS_RIGHT";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"4";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK"
|
"4094";"N/A";"N/A";"ACTORBLOCK_NO_PASS_RIGHT";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"4";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK,NORANDTILE"
|
||||||
"4095";"N/A";"N/A";"ACTORBLOCK_NO_PASS_LEFT";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"4";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK"
|
"4095";"N/A";"N/A";"ACTORBLOCK_NO_PASS_LEFT";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"N/A";"0";"0";"4";"0.0";"0.0";"0.0";"0.0";"N/A";"N/A";"0.0";"INTERNAL,ACTORBLOCK,NORANDTILE"
|
||||||
"65536";"N/A";"N/A";"BLOCK_WATER";"0.1016";"0.0744";"0.0508";"0.0826";"100";"1000";"WATR";"0";"0";"0";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"005599A6";"16";"0.0";"NATURAL"
|
"-1";"N/A";"N/A";"BLOCK_NULL";"4.0000";"4.0000";"4.0000";"4.0000";"-1";"2600";"NULL";"0";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INTERNAL,NORANDTILE"
|
||||||
"65537";"N/A";"N/A";"BLOCK_LAVA";"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK";"0";"0";"0";"0";"0";"16";"0.7664";"0.2032";"0.0000";"0.0000";"FF4600E6";"32";"0.0";"NATURAL"
|
|
||||||
"-1";"N/A";"N/A";"BLOCK_NULL";"4.0000";"4.0000";"4.0000";"4.0000";"-1";"2600";"NULL";"0";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"INTERNAL"
|
|
||||||
|
|
||||||
|
|
||||||
## Notes ##
|
## Notes ##
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 13 and column 2.
|
49
assets/mods/basegame/books/btex.xml
Normal file
49
assets/mods/basegame/books/btex.xml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<btex cover="hardcover" inner="standard" papersize="standard">
|
||||||
|
<cover>
|
||||||
|
<title>The Way to Mastery of Lorem Ipsum<br />Or, How To Write and Publish a Book</title>
|
||||||
|
<author>Terran Publishing</author>
|
||||||
|
<edition>Test Edition</edition>
|
||||||
|
</cover>
|
||||||
|
|
||||||
|
<toc><tableofcontents /></toc>
|
||||||
|
|
||||||
|
<manuscript>
|
||||||
|
|
||||||
|
<chapter>What Is a Book</chapter>
|
||||||
|
|
||||||
|
<p>This example book is designed to give you the exampe of the Book Language.</p>
|
||||||
|
|
||||||
|
<section>What Really Is a Book</section>
|
||||||
|
|
||||||
|
<p>A book is a collection of texts printed in a special way that allows them to be read easily, with enumerable pages and insertion of other helpful resources, such as illustrations and hyperlinks.</p>
|
||||||
|
|
||||||
|
<newpage />
|
||||||
|
|
||||||
|
<fullpagebox>
|
||||||
|
<span colour="grey">
|
||||||
|
<p>this page is intentionally left blank</p>
|
||||||
|
</span>
|
||||||
|
</fullpagebox>
|
||||||
|
|
||||||
|
<chapter>Writing Book Using Pen and Papers</chapter>
|
||||||
|
|
||||||
|
<p>If you open a book on a writing table, you will be welcomed with a toolbar used to put other book elements, such as chapters, sections.</p>
|
||||||
|
|
||||||
|
<chapter>Writing Book Using Typewriter</chapter>
|
||||||
|
|
||||||
|
<p>Typewriters can only write single style of font, therefore chapters and sections are not available.</p>
|
||||||
|
|
||||||
|
<chapter>Writing Book using Computer</chapter>
|
||||||
|
|
||||||
|
<p>Writing book using a computer requires a use of the Book Typesetting Engine Extended, or <BTeX /></p>
|
||||||
|
|
||||||
|
<section>Full Control of the Shape</section>
|
||||||
|
|
||||||
|
<p>With <BTeX /> you can fully control how your publishing would look like, from a pile of papers that look like they have been typed out using typewriter, a pile of papers but a fully-featured printouts that have illustrations in it, to a fully-featured hardcover book.</p>
|
||||||
|
|
||||||
|
<p>This style is controlled using the <code>cover</code> attribute on the root tag, with following values: <code>typewriter</code>, <code>printout</code>, <code>hardcover</code></p>
|
||||||
|
|
||||||
|
<p>Typewriter and Printout are considered not bound and readers will only see one page at a time, while Hardcover is considered bound and two pages are presented to the readers.</p>
|
||||||
|
|
||||||
|
</manuscript>
|
||||||
|
</btex>
|
||||||
60
assets/mods/basegame/books/examination.btex
Normal file
60
assets/mods/basegame/books/examination.btex
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
\usestyle{examination}
|
||||||
|
|
||||||
|
\begin{blocklut}
|
||||||
|
\0\{basegame:0}
|
||||||
|
\1\{basegame:32}
|
||||||
|
\100\{wall@basegame:32}
|
||||||
|
\end{blocklut}
|
||||||
|
|
||||||
|
|
||||||
|
\begin{examination}
|
||||||
|
|
||||||
|
\section{Introduction}
|
||||||
|
|
||||||
|
\begin{tiles}{5x4}
|
||||||
|
\terr{
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,0,0,0,1,
|
||||||
|
1,0,0,0,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
}
|
||||||
|
\wall{
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,1,1,1,1,
|
||||||
|
1,1,1,1,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
}
|
||||||
|
\end{tiles}
|
||||||
|
|
||||||
|
This is the first page of the Examination.
|
||||||
|
|
||||||
|
Examination is a way to instruct the player certain gameplay concepts.
|
||||||
|
|
||||||
|
The system is popularised by the Minecraft Mod called ``Create'', of which it was called Pondering.
|
||||||
|
|
||||||
|
Terrarum borrows the concept and implements it using its own language.
|
||||||
|
|
||||||
|
\section{Language}
|
||||||
|
|
||||||
|
\begin{tiles}{5x4}
|
||||||
|
\terr{
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,0,1,0,1,
|
||||||
|
1,0,1,0,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
}
|
||||||
|
\wall{
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,1,1,1,1,
|
||||||
|
1,1,1,1,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
}
|
||||||
|
\end{tiles}
|
||||||
|
|
||||||
|
Examination relies on the script written in \BTeX.
|
||||||
|
|
||||||
|
\BTeX\ is a \TeX-inspired language to write texts to be displayed onto the game, one example being a book.
|
||||||
|
|
||||||
|
Examination is a special format of the "book" that operates on the same book system.
|
||||||
|
|
||||||
|
\end{examination}
|
||||||
57
assets/mods/basegame/books/examination.xml
Normal file
57
assets/mods/basegame/books/examination.xml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<btex def="examination">
|
||||||
|
<blocklut>
|
||||||
|
<pair key="0" value="basegame:0" />
|
||||||
|
<pair key="1" value="basegame:32" />
|
||||||
|
</blocklut>
|
||||||
|
|
||||||
|
<manuscript>
|
||||||
|
<section>Introduction</section>
|
||||||
|
|
||||||
|
<tiles w="5" h="4">
|
||||||
|
<terr>
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,0,0,0,1,
|
||||||
|
1,0,0,0,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
</terr>
|
||||||
|
<wall>
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,1,1,1,1,
|
||||||
|
1,1,1,1,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
</wall>
|
||||||
|
</tiles>
|
||||||
|
|
||||||
|
<p>This is the first page of the Examination.</p>
|
||||||
|
|
||||||
|
<p>Examination is a way to instruct the player certain gameplay concepts.</p>
|
||||||
|
|
||||||
|
<p>The system is popularised by the Minecraft Mod called “Create”, of which it was called Pondering.</p>
|
||||||
|
|
||||||
|
<p>Terrarum borrows the concept and implements it using its own language.</p>
|
||||||
|
|
||||||
|
<section>Language</section>
|
||||||
|
|
||||||
|
<tiles w="5" h="4">
|
||||||
|
<terr>
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,0,1,0,1,
|
||||||
|
1,0,1,0,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
</terr>
|
||||||
|
<wall>
|
||||||
|
0,1,1,1,0,
|
||||||
|
1,1,1,1,1,
|
||||||
|
1,1,1,1,1,
|
||||||
|
0,1,1,1,0
|
||||||
|
</wall>
|
||||||
|
</tiles>
|
||||||
|
|
||||||
|
<p>Examination relies on the script written in <BTeX />.</p>
|
||||||
|
|
||||||
|
<p><BTeX /> is a XML-like markup language to write texts to be displayed onto the game, one example being a book.</p>
|
||||||
|
|
||||||
|
<p>Examination is a special format of the “book” that operates on the same book system.</p>
|
||||||
|
|
||||||
|
</manuscript>
|
||||||
|
</btex>
|
||||||
@@ -3,6 +3,7 @@ CheatWarnTest
|
|||||||
CodexEdictis
|
CodexEdictis
|
||||||
ExportCodices
|
ExportCodices
|
||||||
ExportMap
|
ExportMap
|
||||||
|
ExportMap2
|
||||||
ExportWorld
|
ExportWorld
|
||||||
ForceGC
|
ForceGC
|
||||||
GetAV
|
GetAV
|
||||||
|
|||||||
|
3
assets/mods/basegame/configplan.csv
Normal file
3
assets/mods/basegame/configplan.csv
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
->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
|
||||||
|
@@ -10,12 +10,12 @@
|
|||||||
"accel": 0.67,
|
"accel": 0.67,
|
||||||
|
|
||||||
"speed": 3.0,
|
"speed": 3.0,
|
||||||
"speedmult": [100,100,100,100,100,100,100],
|
"speedmult": [90,95,98,100,102,105,110],
|
||||||
|
|
||||||
"vertstride": 12,
|
"vertstride": 12,
|
||||||
|
|
||||||
"jumppower": 13.0,
|
"jumppower": 13.0,
|
||||||
"jumppowermult": [100,100,100,100,100,100,100],
|
"jumppowermult": [90,95,98,100,102,105,110],
|
||||||
|
|
||||||
"scale": 1.0,
|
"scale": 1.0,
|
||||||
"scalemult": [100,100,100,100,100,100,100],
|
"scalemult": [100,100,100,100,100,100,100],
|
||||||
|
|||||||
33
assets/mods/basegame/creatures/CreaturePlayer.json
Normal file
33
assets/mods/basegame/creatures/CreaturePlayer.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"racename": "RACE_HUMAN",
|
||||||
|
"racenameplural": "RACE_HUMAN_PLURAL",
|
||||||
|
"baseheight": 40,
|
||||||
|
"basemass": 60.0,
|
||||||
|
|
||||||
|
"strength": 1000,
|
||||||
|
"strengthmult": [100,100,100,100,100,100,100],
|
||||||
|
|
||||||
|
"accel": 0.67,
|
||||||
|
|
||||||
|
"speed": 3.0,
|
||||||
|
"speedmult": [100,100,100,100,100,100,100],
|
||||||
|
|
||||||
|
"vertstride": 12,
|
||||||
|
|
||||||
|
"jumppower": 13.0,
|
||||||
|
"jumppowermult": [100,100,100,100,100,100,100],
|
||||||
|
|
||||||
|
"scale": 1.0,
|
||||||
|
"scalemult": [100,100,100,100,100,100,100],
|
||||||
|
|
||||||
|
"encumbrance": 1000,
|
||||||
|
"defence": 100,
|
||||||
|
"reach": 100,
|
||||||
|
|
||||||
|
"toolsize": 15,
|
||||||
|
|
||||||
|
"intelligent": true,
|
||||||
|
"barehandactionminheight": 80,
|
||||||
|
"basebarehanddiggingsize": 8
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"gameplay_max_crafting": 100
|
"gameplay_max_crafting": 100,
|
||||||
|
"showpickaxetooltip": true
|
||||||
}
|
}
|
||||||
3
assets/mods/basegame/fluids/fluids.csv
Normal file
3
assets/mods/basegame/fluids/fluids.csv
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
"id";"name";"shdr";"shdg";"shdb";"shduv";"str";"dsty";"mate";"lumr";"lumg";"lumb";"lumuv";"colour";"vscs";"refl";"tags"
|
||||||
|
"1";"BLOCK_WATER";"0.1016";"0.0744";"0.0508";"0.0826";"100";"1000";"WATR";"0.0000";"0.0000";"0.0000";"0.0000";"005599A6";"16";"0.0";"NATURAL"
|
||||||
|
"2";"BLOCK_LAVA";"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK"; "0.7664";"0.2032";"0.0000";"0.0000";"FF4600E6";"32";"0.0";"NATURAL,MOLTEN"
|
||||||
|
BIN
assets/mods/basegame/gui/loadscr_layer01.png
LFS
Normal file
BIN
assets/mods/basegame/gui/loadscr_layer01.png
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/gui/loadscr_layer02.png
LFS
Normal file
BIN
assets/mods/basegame/gui/loadscr_layer02.png
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/gui/loadscr_layer03.png
LFS
Normal file
BIN
assets/mods/basegame/gui/loadscr_layer03.png
LFS
Normal file
Binary file not shown.
@@ -12,8 +12,18 @@ id;classname
|
|||||||
11;net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar
|
11;net.torvald.terrarum.modulebasegame.gameitems.ItemWallCalendar
|
||||||
12;net.torvald.terrarum.modulebasegame.gameitems.SledgehammerCopper
|
12;net.torvald.terrarum.modulebasegame.gameitems.SledgehammerCopper
|
||||||
13;net.torvald.terrarum.modulebasegame.gameitems.SledgehammerSteel
|
13;net.torvald.terrarum.modulebasegame.gameitems.SledgehammerSteel
|
||||||
|
14;net.torvald.terrarum.modulebasegame.gameitems.PickaxeWood
|
||||||
|
15;net.torvald.terrarum.modulebasegame.gameitems.SledgehammerWood
|
||||||
16;net.torvald.terrarum.modulebasegame.gameitems.ItemWorkbench
|
16;net.torvald.terrarum.modulebasegame.gameitems.ItemWorkbench
|
||||||
|
17;net.torvald.terrarum.modulebasegame.gameitems.ItemCoalCoke
|
||||||
|
|
||||||
|
128;net.torvald.terrarum.modulebasegame.gameitems.OreCopper
|
||||||
|
129;net.torvald.terrarum.modulebasegame.gameitems.OreIron
|
||||||
|
130;net.torvald.terrarum.modulebasegame.gameitems.OreCoal
|
||||||
|
131;net.torvald.terrarum.modulebasegame.gameitems.OreZinc
|
||||||
|
132;net.torvald.terrarum.modulebasegame.gameitems.OreTin
|
||||||
|
133;net.torvald.terrarum.modulebasegame.gameitems.OreGold
|
||||||
|
134;net.torvald.terrarum.modulebasegame.gameitems.OreSilver
|
||||||
|
|
||||||
256;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorOak
|
256;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorOak
|
||||||
257;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorEbony
|
257;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorEbony
|
||||||
|
|||||||
|
Binary file not shown.
@@ -35,20 +35,6 @@
|
|||||||
"BLOCK_GRAVEL": "Gravel",
|
"BLOCK_GRAVEL": "Gravel",
|
||||||
"BLOCK_GRAVEL_GREY": "Grey Gravel",
|
"BLOCK_GRAVEL_GREY": "Grey Gravel",
|
||||||
|
|
||||||
"BLOCK_ORE_MALACHITE": "Malachite",
|
|
||||||
"BLOCK_ORE_HEMATITE": "Hematite",
|
|
||||||
"BLOCK_ORE_NATURAL_GOLD": "Natural Gold",
|
|
||||||
"BLOCK_ORE_NATURAL_SILVER": "Natural Silver",
|
|
||||||
"BLOCK_ORE_RUTILE": "Rutile",
|
|
||||||
"BLOCK_ORE_AURICHALCUMITE": "Aurichalcumite",
|
|
||||||
|
|
||||||
"BLOCK_GEM_RUBY": "Raw Ruby",
|
|
||||||
"BLOCK_GEM_EMERALD": "Raw Emerald",
|
|
||||||
"BLOCK_GEM_SAPPHIRE": "Raw Sapphire",
|
|
||||||
"BLOCK_GEM_TOPAZ": "Raw Topaz",
|
|
||||||
"BLOCK_GEM_DIAMOND": "Raw Diamond",
|
|
||||||
"BLOCK_GEM_AMETHYST": "Raw Amethyst",
|
|
||||||
|
|
||||||
"BLOCK_SNOW": "Snow",
|
"BLOCK_SNOW": "Snow",
|
||||||
|
|
||||||
"BLOCK_ICE_FRAGILE": "Thin Ice",
|
"BLOCK_ICE_FRAGILE": "Thin Ice",
|
||||||
|
|||||||
@@ -12,9 +12,11 @@
|
|||||||
"MENU_LABEL_PREV_SAVES": "Previous Saves",
|
"MENU_LABEL_PREV_SAVES": "Previous Saves",
|
||||||
"MENU_LABEL_RENAME": "Rename",
|
"MENU_LABEL_RENAME": "Rename",
|
||||||
"MENU_LABEL_USE_CODE": "Use Code",
|
"MENU_LABEL_USE_CODE": "Use Code",
|
||||||
|
"MENU_MODE_BUILDINGMAKER": "POI Editor",
|
||||||
"MENU_MONITOR_CALI_TITLE": "Check Monitor",
|
"MENU_MONITOR_CALI_TITLE": "Check Monitor",
|
||||||
|
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "Show Ores Tooltip When Mining",
|
||||||
|
"MENU_OPTIONS_MAX_CRAFTING": "Max Number of Items For Crafting",
|
||||||
"MENU_UPDATE_UPDATE_AVAILABLE": "Update Available!",
|
"MENU_UPDATE_UPDATE_AVAILABLE": "Update Available!",
|
||||||
"GAME_ACTION_CRAFT": "Craft",
|
|
||||||
"GAME_ACTION_GRAPPLE": "Grapple",
|
"GAME_ACTION_GRAPPLE": "Grapple",
|
||||||
"GAME_ACTION_QUICKSEL": "Quick Select",
|
"GAME_ACTION_QUICKSEL": "Quick Select",
|
||||||
"GAME_ACTION_TELEPORT": "Teleport",
|
"GAME_ACTION_TELEPORT": "Teleport",
|
||||||
|
|||||||
@@ -4,7 +4,20 @@
|
|||||||
"ITEM_DOOR_EBONY": "Ebony Door",
|
"ITEM_DOOR_EBONY": "Ebony Door",
|
||||||
"ITEM_DOOR_BIRCH": "Birch Door",
|
"ITEM_DOOR_BIRCH": "Birch Door",
|
||||||
"ITEM_DOOR_ROSEWOOD": "Rosewood Door",
|
"ITEM_DOOR_ROSEWOOD": "Rosewood Door",
|
||||||
|
"ITEM_GEM_RUBY": "Raw Ruby",
|
||||||
|
"ITEM_GEM_EMERALD": "Raw Emerald",
|
||||||
|
"ITEM_GEM_SAPPHIRE": "Raw Sapphire",
|
||||||
|
"ITEM_GEM_TOPAZ": "Raw Topaz",
|
||||||
|
"ITEM_GEM_DIAMOND": "Raw Diamond",
|
||||||
|
"ITEM_GEM_AMETHYST": "Raw Amethyst",
|
||||||
"ITEM_LOGIC_SIGNAL_EMITTER": "Logic Signal Emitter",
|
"ITEM_LOGIC_SIGNAL_EMITTER": "Logic Signal Emitter",
|
||||||
|
"ITEM_ORE_CASSITERITE": "Tin Ore",
|
||||||
|
"ITEM_ORE_COAL": "Coal",
|
||||||
|
"ITEM_ORE_HAEMATITE": "Iron Ore",
|
||||||
|
"ITEM_ORE_MALACHITE": "Copper Ore",
|
||||||
|
"ITEM_ORE_NATURAL_GOLD": "Natural Gold",
|
||||||
|
"ITEM_ORE_NATURAL_SILVER": "Natural Silver",
|
||||||
|
"ITEM_ORE_SPHALERITE": "Zinc Ore",
|
||||||
"ITEM_PICK_COPPER": "Copper Pickaxe",
|
"ITEM_PICK_COPPER": "Copper Pickaxe",
|
||||||
"ITEM_PICK_IRON": "Iron Pickaxe",
|
"ITEM_PICK_IRON": "Iron Pickaxe",
|
||||||
"ITEM_PICK_STEEL": "Steel Pickaxe",
|
"ITEM_PICK_STEEL": "Steel Pickaxe",
|
||||||
|
|||||||
@@ -35,20 +35,6 @@
|
|||||||
"BLOCK_GRAVEL": "자갈",
|
"BLOCK_GRAVEL": "자갈",
|
||||||
"BLOCK_GRAVEL_GREY": "회색 자갈",
|
"BLOCK_GRAVEL_GREY": "회색 자갈",
|
||||||
|
|
||||||
"BLOCK_ORE_MALACHITE": "공작석",
|
|
||||||
"BLOCK_ORE_HEMATITE": "적철석",
|
|
||||||
"BLOCK_ORE_NATURAL_GOLD": "금덩어리",
|
|
||||||
"BLOCK_ORE_NATURAL_SILVER": "은덩어리",
|
|
||||||
"BLOCK_ORE_RUTILE": "금홍석",
|
|
||||||
"BLOCK_ORE_AURICHALCUMITE": "진금석",
|
|
||||||
|
|
||||||
"BLOCK_GEM_RUBY": "홍옥석",
|
|
||||||
"BLOCK_GEM_EMERALD": "취옥석",
|
|
||||||
"BLOCK_GEM_SAPPHIRE": "청옥석",
|
|
||||||
"BLOCK_GEM_TOPAZ": "황옥석",
|
|
||||||
"BLOCK_GEM_DIAMOND": "금강석",
|
|
||||||
"BLOCK_GEM_AMETHYST": "자수정석",
|
|
||||||
|
|
||||||
"BLOCK_SNOW": "눈",
|
"BLOCK_SNOW": "눈",
|
||||||
|
|
||||||
"BLOCK_ICE_FRAGILE": "살얼음",
|
"BLOCK_ICE_FRAGILE": "살얼음",
|
||||||
|
|||||||
@@ -13,8 +13,9 @@
|
|||||||
"MENU_LABEL_RENAME": "이름 바꾸기",
|
"MENU_LABEL_RENAME": "이름 바꾸기",
|
||||||
"MENU_LABEL_USE_CODE": "코드 사용",
|
"MENU_LABEL_USE_CODE": "코드 사용",
|
||||||
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
|
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
|
||||||
|
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "채굴 시 광석 툴팁 보이기",
|
||||||
|
"MENU_OPTIONS_MAX_CRAFTING": "한번에 제작할 최대 아이템 수",
|
||||||
"MENU_UPDATE_UPDATE_AVAILABLE": "새 업데이트가 있습니다!",
|
"MENU_UPDATE_UPDATE_AVAILABLE": "새 업데이트가 있습니다!",
|
||||||
"GAME_ACTION_CRAFT": "제작하기",
|
|
||||||
"GAME_ACTION_GRAPPLE": "매달리기",
|
"GAME_ACTION_GRAPPLE": "매달리기",
|
||||||
"GAME_ACTION_QUICKSEL": "빠른 선택",
|
"GAME_ACTION_QUICKSEL": "빠른 선택",
|
||||||
"GAME_ACTION_TELEPORT": "텔레포트하기",
|
"GAME_ACTION_TELEPORT": "텔레포트하기",
|
||||||
|
|||||||
@@ -4,7 +4,20 @@
|
|||||||
"ITEM_DOOR_EBONY": "흑단 문",
|
"ITEM_DOOR_EBONY": "흑단 문",
|
||||||
"ITEM_DOOR_BIRCH": "백단 문",
|
"ITEM_DOOR_BIRCH": "백단 문",
|
||||||
"ITEM_DOOR_ROSEWOOD": "자단 문",
|
"ITEM_DOOR_ROSEWOOD": "자단 문",
|
||||||
|
"ITEM_GEM_RUBY": "홍옥석",
|
||||||
|
"ITEM_GEM_EMERALD": "취옥석",
|
||||||
|
"ITEM_GEM_SAPPHIRE": "청옥석",
|
||||||
|
"ITEM_GEM_TOPAZ": "황옥석",
|
||||||
|
"ITEM_GEM_DIAMOND": "금강석",
|
||||||
|
"ITEM_GEM_AMETHYST": "자수정석",
|
||||||
"ITEM_LOGIC_SIGNAL_EMITTER": "신호발생기",
|
"ITEM_LOGIC_SIGNAL_EMITTER": "신호발생기",
|
||||||
|
"ITEM_ORE_CASSITERITE": "주석석",
|
||||||
|
"ITEM_ORE_COAL": "석탄",
|
||||||
|
"ITEM_ORE_HAEMATITE": "철광석",
|
||||||
|
"ITEM_ORE_MALACHITE": "동광석",
|
||||||
|
"ITEM_ORE_NATURAL_GOLD": "금덩이",
|
||||||
|
"ITEM_ORE_NATURAL_SILVER": "은덩이",
|
||||||
|
"ITEM_ORE_SPHALERITE": "아연석",
|
||||||
"ITEM_PICK_COPPER": "구리 곡괭이",
|
"ITEM_PICK_COPPER": "구리 곡괭이",
|
||||||
"ITEM_PICK_IRON": "철 곡괭이",
|
"ITEM_PICK_IRON": "철 곡괭이",
|
||||||
"ITEM_PICK_STEEL": "강철 곡괭이",
|
"ITEM_PICK_STEEL": "강철 곡괭이",
|
||||||
|
|||||||
@@ -1,17 +1,28 @@
|
|||||||
idst;tens;impf;dsty;fmod;endurance;tcond;reach;comments
|
idst;tens;impf;dsty;fmod;endurance;tcond;reach;rcs;comments
|
||||||
ROCK;15;210;3000;1;0.42;1.0;5;data is that of marble
|
WOOD;10;10;800;1;0.173;0.17;5;18;just a generic wood
|
||||||
OORE;15;210;3000;1;0.42;1.0;5;data is that of marble
|
ROCK;15;210;3000;1;0.42;2.9;5;48;data is that of marble
|
||||||
OGEM;15;210;3000;1;0.42;1.0;5;data is that of marble
|
OORE;15;210;3000;1;0.42;2.9;5;100;data is that of marble
|
||||||
CUPR;210;770;8960;2;1.00;401.0;5;copper
|
OGEM;15;210;3000;1;0.42;2.9;5;80;data is that of marble
|
||||||
EGLS;33;1000;2325;4;0.82;1.0;6;elven glass/moldavite
|
CUPR;210;770;8960;2;1.00;401.0;5;120;copper
|
||||||
IRON;350;1085;7874;5;1.42;1.0;6;not wrought iron,just natural iron
|
EGLS;33;1000;2325;4;0.82;1.0;6;10;elven glass/moldavite
|
||||||
ARGN;170;595;10490;9;0.91;1.0;6;argentum/silver
|
IRON;350;1085;7874;5;1.42;80.4;6;120;not wrought iron,just natural iron
|
||||||
STAL;531;2520;7874;14;1.73;1.0;7;steel
|
ARGN;170;595;10490;9;0.91;429.0;6;120;argentum/silver
|
||||||
EAUR;768;0;8192;21;1.36;1.0;7;elven aurichalcum
|
AURM;120;350;19300;9;0.88;318.0;6;120;aurum/gold
|
||||||
TIAL;900;0;4420;33;2.16;1.0;8;titanium alloy (Ti6Al4V)
|
STAL;531;2520;7874;14;1.73;26.0;7;120;steel
|
||||||
ADMT;2000;4090;2700;71;3.42;1.0;8;adamant
|
EAUR;768;0;8192;21;1.36;1.0;7;120;elven aurichalcum
|
||||||
OOZE;20;0;1000;1;0.08;0.5;0;genetic ooze,data is about human skin
|
TIAL;900;0;4420;33;2.16;1.0;8;120;titanium alloy (Ti6Al4V)
|
||||||
BONE;130;0;2000;1;0.23;0.55;4;data is that of bovine bone
|
ADMT;2000;4090;2700;71;3.42;1.0;8;120;adamant
|
||||||
|
OOZE;20;0;1000;1;0.08;0.5;0;10;genetic ooze,data is about human skin
|
||||||
|
BONE;130;0;2000;1;0.23;0.55;4;10;data is that of bovine bone
|
||||||
|
BRAS;315;1015;8530;3;1.00;120;5;120;brass
|
||||||
|
BRNZ;310;843;8770;3;1.20;75;5;120;bronze
|
||||||
|
TINN;220;350;7310;2;1.00;69;5;120;tin
|
||||||
|
ZINC;90;525;7140;2;1.00;116;5;120;zinc
|
||||||
|
DIRT;1;1;1400;0.0;0.0;36;0;10;dirt
|
||||||
|
PLST;1;1;1400;0.0;0.0;36;0;16;TODO plastic (polyethylene)
|
||||||
|
AIIR;1;1;1;0.0;0.0;36;0;1;air
|
||||||
|
SAND;1;1;2400;0.0;0.0;36;0;36;sand
|
||||||
|
GRVL;1;1;2400;0.0;0.0;36;0;36;gravel
|
||||||
|
|
||||||
# idst: ID_STRING, ALL CAPS
|
# idst: ID_STRING, ALL CAPS
|
||||||
#
|
#
|
||||||
@@ -33,6 +44,8 @@ BONE;130;0;2000;1;0.23;0.55;4;data is that of bovine bone
|
|||||||
#
|
#
|
||||||
# reach: Tool Reach in blocks. Default is 6 (iron)
|
# reach: Tool Reach in blocks. Default is 6 (iron)
|
||||||
#
|
#
|
||||||
|
# rcs: Radar Cross Section -- how well the material reflects the radio wave used by the Ground Penetrating Radar.
|
||||||
|
#
|
||||||
# Comments: do nothing;do not parse
|
# Comments: do nothing;do not parse
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|||||||
|
@@ -47,7 +47,7 @@ entrypoint=net.torvald.terrarum.modulebasegame.EntryPoint
|
|||||||
releasedate=2023-10-06
|
releasedate=2023-10-06
|
||||||
|
|
||||||
# The version, must follow Semver 2.0.0 scheme (https://semver.org/)
|
# The version, must follow Semver 2.0.0 scheme (https://semver.org/)
|
||||||
version=0.3.3
|
version=0.4.0
|
||||||
|
|
||||||
# External JAR that the module is compiled. If your module requires yet another library, the JAR must be compiled as a "Fatjar";
|
# External JAR that the module is compiled. If your module requires yet another library, the JAR must be compiled as a "Fatjar";
|
||||||
# Due to security reasons, loading an arbitrary JAR is not allowed.
|
# Due to security reasons, loading an arbitrary JAR is not allowed.
|
||||||
|
|||||||
BIN
assets/mods/basegame/ores/1.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/1.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/ores/2.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/2.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/ores/3.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/3.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/ores/4.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/4.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/ores/5.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/5.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/ores/6.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/6.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/ores/7.tga
LFS
Normal file
BIN
assets/mods/basegame/ores/7.tga
LFS
Normal file
Binary file not shown.
20
assets/mods/basegame/ores/ores.csv
Normal file
20
assets/mods/basegame/ores/ores.csv
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
"id";"item";"tags"
|
||||||
|
"1";"item@basegame:128";"COPPER,MALACHITE"
|
||||||
|
"2";"item@basegame:129";"IRON,HAEMATITE"
|
||||||
|
"3";"item@basegame:130";"COAL,CARBON"
|
||||||
|
"4";"item@basegame:131";"ZINC,SPHALERITE"
|
||||||
|
"5";"item@basegame:132";"TIN,CASSITERITE"
|
||||||
|
"6";"item@basegame:133";"GOLD,NATURAL_GOLD"
|
||||||
|
"7";"item@basegame:134";"SILVER,NATURAL_SILVER"
|
||||||
|
# "8";"item@basegame:135";"GEM,RUBY"
|
||||||
|
# "9";"item@basegame:136";"GEM,EMERALD"
|
||||||
|
#"10";"item@basegame:137";"GEM,SAPPHIRE"
|
||||||
|
#"11";"item@basegame:138";"GEM,TOPAZ"
|
||||||
|
#"12";"item@basegame:139";"GEM,DIAMOND"
|
||||||
|
#"13";"item@basegame:140";"GEM,SIO2,AMETHYST"
|
||||||
|
#"14";"item@basegame:141";"GEM,SIO2,QUARTZ"
|
||||||
|
#"15";"item@basegame:142";"LEAD,GALENA"
|
||||||
|
#"16";"item@basegame:143";"TITANIUM,RUTILE"
|
||||||
|
|
||||||
|
#"256";"macro@BASETILE";"GRASS"
|
||||||
|
#"257";"macro@BASETILE";"MOSS"
|
||||||
|
Can't render this file because it contains an unexpected character in line 9 and column 3.
|
29
assets/mods/basegame/ores/worldgen.csv
Normal file
29
assets/mods/basegame/ores/worldgen.csv
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
"id";"freq";"power";"scale";"ratio";"tiling";"comment"
|
||||||
|
"1";"0.032";"0.010";"0.507";"1.0";"a16x16";"copper (malachite)"
|
||||||
|
"2";"0.056";"0.011";"0.507";"1.0";"a16x16";"iron (haematite)"
|
||||||
|
"3";"0.021";"0.070";"0.501";"3.8";"a16x4";"coal"
|
||||||
|
"4";"0.024";"0.011";"0.501";"1.0";"a16x16";"zinc (sphalerite)"
|
||||||
|
"5";"0.021";"0.020";"0.501";"1.0";"a16x16";"tin (cassiterite)"
|
||||||
|
"6";"0.011";"0.300";"0.465";"1.0";"a16x16";"natural gold"
|
||||||
|
"7";"0.016";"0.300";"0.467";"1.0";"a16x16";"natural silver"
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# id: ore ID to spawn, the ID must exist on the ores.csv
|
||||||
|
#
|
||||||
|
# freq: frequency value used to set up noise generator. Larger = ore veins are closer together
|
||||||
|
# power: power value (as in: randomNumber ^ power) used to set up the noise generator. Larger = veins are larger as you go deeper. 0.01 almost negates this effect
|
||||||
|
# scale: scale value used to set up the noise generator. Larger = thicker veins. A valid value tend to play around the 0.5; you'll need figure out this value by trial and error
|
||||||
|
# ratio: how elongated (or squeeze) the ore veins are. >1.0 = stretched horizontally, <1.0 = stretched vertically
|
||||||
|
#
|
||||||
|
# tiling: determines how the tiles are tiled
|
||||||
|
# - a16: use 4-neighbour autotiling (16 possible cases)
|
||||||
|
# - a16x4: 4 variants of a16 (typically 4 rotations, or 2 rotations x 2 flips)
|
||||||
|
# - a16x8: 8 variants of a16 (typically 4 rotations x 2 flips) -- horz/vert flip do not matter, both produces same sets of shapes
|
||||||
|
# - a16x16: 16 variants of a16 (typically 4 rotations x 2 flips x 2 styles)
|
||||||
|
# - a47: use 8-neighbour autotiling (47 possible cases)
|
||||||
|
# - a47x4: 4 variants of a47 (typically 4 rotations, or 2 rotations x 2 flips)
|
||||||
|
# - r16: use the hash of the tile position as a variant selection, module 16
|
||||||
|
# - r8: use the hash of the tile position as a variant selection, module 8
|
||||||
|
#
|
||||||
|
# comment: human-readable comments, not actually parsed
|
||||||
|
BIN
assets/mods/basegame/splashback.png
LFS
Normal file
BIN
assets/mods/basegame/splashback.png
LFS
Normal file
Binary file not shown.
676
src/com/badlogic/gdx/backends/lwjgl3/Lwjgl3Application.java
Normal file
676
src/com/badlogic/gdx/backends/lwjgl3/Lwjgl3Application.java
Normal file
@@ -0,0 +1,676 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright 2011 See AUTHORS file.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
package com.badlogic.gdx.backends.lwjgl3;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationLogger;
|
||||||
|
import com.badlogic.gdx.backends.lwjgl3.audio.Lwjgl3Audio;
|
||||||
|
import com.badlogic.gdx.backends.lwjgl3.audio.OpenALLwjgl3Audio;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.GLVersion;
|
||||||
|
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||||
|
import org.lwjgl.opengl.AMDDebugOutput;
|
||||||
|
import org.lwjgl.opengl.ARBDebugOutput;
|
||||||
|
import org.lwjgl.opengl.GL;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL43;
|
||||||
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
|
import org.lwjgl.opengl.GLUtil;
|
||||||
|
import org.lwjgl.opengl.KHRDebug;
|
||||||
|
import org.lwjgl.system.Callback;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Application;
|
||||||
|
import com.badlogic.gdx.ApplicationListener;
|
||||||
|
import com.badlogic.gdx.Audio;
|
||||||
|
import com.badlogic.gdx.Files;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.Graphics;
|
||||||
|
import com.badlogic.gdx.Input;
|
||||||
|
import com.badlogic.gdx.LifecycleListener;
|
||||||
|
import com.badlogic.gdx.Net;
|
||||||
|
import com.badlogic.gdx.Preferences;
|
||||||
|
import com.badlogic.gdx.backends.lwjgl3.audio.mock.MockAudio;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.Clipboard;
|
||||||
|
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||||
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
|
import com.badlogic.gdx.utils.SharedLibraryLoader;
|
||||||
|
import org.lwjgl.system.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This version of code is based on GDX 1.12.0 and was modified for the Terrarum project.
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2023-11-08.
|
||||||
|
*/
|
||||||
|
public class Lwjgl3Application implements Lwjgl3ApplicationBase {
|
||||||
|
private final Lwjgl3ApplicationConfiguration config;
|
||||||
|
final Array<Lwjgl3Window> windows = new Array<Lwjgl3Window>();
|
||||||
|
private volatile Lwjgl3Window currentWindow;
|
||||||
|
private Lwjgl3Audio audio;
|
||||||
|
private final Files files;
|
||||||
|
private final Net net;
|
||||||
|
private final ObjectMap<String, Preferences> preferences = new ObjectMap<String, Preferences>();
|
||||||
|
private final Lwjgl3Clipboard clipboard;
|
||||||
|
private int logLevel = LOG_INFO;
|
||||||
|
private ApplicationLogger applicationLogger;
|
||||||
|
private volatile boolean running = true;
|
||||||
|
private final Array<Runnable> runnables = new Array<Runnable>();
|
||||||
|
private final Array<Runnable> executedRunnables = new Array<Runnable>();
|
||||||
|
private final Array<LifecycleListener> lifecycleListeners = new Array<LifecycleListener>();
|
||||||
|
private static GLFWErrorCallback errorCallback;
|
||||||
|
private static GLVersion glVersion;
|
||||||
|
private static Callback glDebugCallback;
|
||||||
|
private final Sync sync;
|
||||||
|
|
||||||
|
static void initializeGlfw () {
|
||||||
|
if (errorCallback == null) {
|
||||||
|
if (SharedLibraryLoader.isMac) loadGlfwAwtMacos();
|
||||||
|
Lwjgl3NativesLoader.load();
|
||||||
|
errorCallback = GLFWErrorCallback.createPrint(Lwjgl3ApplicationConfiguration.errorStream);
|
||||||
|
GLFW.glfwSetErrorCallback(errorCallback);
|
||||||
|
if (SharedLibraryLoader.isMac) GLFW.glfwInitHint(GLFW.GLFW_ANGLE_PLATFORM_TYPE, GLFW.GLFW_ANGLE_PLATFORM_TYPE_METAL);
|
||||||
|
GLFW.glfwInitHint(GLFW.GLFW_JOYSTICK_HAT_BUTTONS, GLFW.GLFW_FALSE);
|
||||||
|
if (!GLFW.glfwInit()) {
|
||||||
|
throw new GdxRuntimeException("Unable to initialize GLFW");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadANGLE () {
|
||||||
|
try {
|
||||||
|
Class angleLoader = Class.forName("com.badlogic.gdx.backends.lwjgl3.angle.ANGLELoader");
|
||||||
|
Method load = angleLoader.getMethod("load");
|
||||||
|
load.invoke(angleLoader);
|
||||||
|
} catch (ClassNotFoundException t) {
|
||||||
|
return;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new GdxRuntimeException("Couldn't load ANGLE.", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void postLoadANGLE () {
|
||||||
|
try {
|
||||||
|
Class angleLoader = Class.forName("com.badlogic.gdx.backends.lwjgl3.angle.ANGLELoader");
|
||||||
|
Method load = angleLoader.getMethod("postGlfwInit");
|
||||||
|
load.invoke(angleLoader);
|
||||||
|
} catch (ClassNotFoundException t) {
|
||||||
|
return;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new GdxRuntimeException("Couldn't load ANGLE.", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadGlfwAwtMacos () {
|
||||||
|
try {
|
||||||
|
Class loader = Class.forName("com.badlogic.gdx.backends.lwjgl3.awt.GlfwAWTLoader");
|
||||||
|
Method load = loader.getMethod("load");
|
||||||
|
File sharedLib = (File)load.invoke(loader);
|
||||||
|
Configuration.GLFW_LIBRARY_NAME.set(sharedLib.getAbsolutePath());
|
||||||
|
Configuration.GLFW_CHECK_THREAD0.set(false);
|
||||||
|
} catch (ClassNotFoundException t) {
|
||||||
|
return;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new GdxRuntimeException("Couldn't load GLFW AWT for macOS.", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Lwjgl3Application (ApplicationListener listener) {
|
||||||
|
this(listener, new Lwjgl3ApplicationConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Lwjgl3Application (ApplicationListener listener, Lwjgl3ApplicationConfiguration config) {
|
||||||
|
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) loadANGLE();
|
||||||
|
initializeGlfw();
|
||||||
|
setApplicationLogger(new Lwjgl3ApplicationLogger());
|
||||||
|
|
||||||
|
this.config = config = Lwjgl3ApplicationConfiguration.copy(config);
|
||||||
|
if (config.title == null) config.title = listener.getClass().getSimpleName();
|
||||||
|
|
||||||
|
Gdx.app = this;
|
||||||
|
if (!config.disableAudio) {
|
||||||
|
try {
|
||||||
|
this.audio = createAudio(config);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
log("Lwjgl3Application", "Couldn't initialize audio, disabling audio", t);
|
||||||
|
this.audio = new MockAudio();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.audio = new MockAudio();
|
||||||
|
}
|
||||||
|
Gdx.audio = audio;
|
||||||
|
this.files = Gdx.files = createFiles();
|
||||||
|
this.net = Gdx.net = new Lwjgl3Net(config);
|
||||||
|
this.clipboard = new Lwjgl3Clipboard();
|
||||||
|
|
||||||
|
this.sync = new Sync();
|
||||||
|
|
||||||
|
Lwjgl3Window window = createWindow(config, listener, 0);
|
||||||
|
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) postLoadANGLE();
|
||||||
|
windows.add(window);
|
||||||
|
try {
|
||||||
|
loop();
|
||||||
|
cleanupWindows();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
if (t instanceof RuntimeException)
|
||||||
|
throw (RuntimeException)t;
|
||||||
|
else
|
||||||
|
throw new GdxRuntimeException(t);
|
||||||
|
} finally {
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void loop () {
|
||||||
|
Array<Lwjgl3Window> closedWindows = new Array<Lwjgl3Window>();
|
||||||
|
while (running && windows.size > 0) {
|
||||||
|
// System.out.println("aaaaaaaaaaaaaaaaaaaaa");
|
||||||
|
|
||||||
|
// audio.update(); // is handled on net.torvald.terrarum.AudioManager.update(float)
|
||||||
|
|
||||||
|
boolean haveWindowsRendered = false;
|
||||||
|
closedWindows.clear();
|
||||||
|
int targetFramerate = -2;
|
||||||
|
for (Lwjgl3Window window : windows) {
|
||||||
|
window.makeCurrent();
|
||||||
|
currentWindow = window;
|
||||||
|
if (targetFramerate == -2) targetFramerate = window.getConfig().foregroundFPS;
|
||||||
|
synchronized (lifecycleListeners) {
|
||||||
|
haveWindowsRendered |= window.update();
|
||||||
|
}
|
||||||
|
if (window.shouldClose()) {
|
||||||
|
closedWindows.add(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GLFW.glfwPollEvents();
|
||||||
|
|
||||||
|
boolean shouldRequestRendering;
|
||||||
|
synchronized (runnables) {
|
||||||
|
shouldRequestRendering = runnables.size > 0;
|
||||||
|
executedRunnables.clear();
|
||||||
|
executedRunnables.addAll(runnables);
|
||||||
|
runnables.clear();
|
||||||
|
}
|
||||||
|
for (Runnable runnable : executedRunnables) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
if (shouldRequestRendering) {
|
||||||
|
// Must follow Runnables execution so changes done by Runnables are reflected
|
||||||
|
// in the following render.
|
||||||
|
for (Lwjgl3Window window : windows) {
|
||||||
|
if (!window.getGraphics().isContinuousRendering()) window.requestRendering();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Lwjgl3Window closedWindow : closedWindows) {
|
||||||
|
if (windows.size == 1) {
|
||||||
|
// Lifecycle listener methods have to be called before ApplicationListener methods. The
|
||||||
|
// application will be disposed when _all_ windows have been disposed, which is the case,
|
||||||
|
// when there is only 1 window left, which is in the process of being disposed.
|
||||||
|
for (int i = lifecycleListeners.size - 1; i >= 0; i--) {
|
||||||
|
LifecycleListener l = lifecycleListeners.get(i);
|
||||||
|
l.pause();
|
||||||
|
l.dispose();
|
||||||
|
}
|
||||||
|
lifecycleListeners.clear();
|
||||||
|
}
|
||||||
|
closedWindow.dispose();
|
||||||
|
|
||||||
|
windows.removeValue(closedWindow, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveWindowsRendered) {
|
||||||
|
// Sleep a few milliseconds in case no rendering was requested
|
||||||
|
// with continuous rendering disabled.
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000 / config.idleFPS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
} else if (targetFramerate > 0) {
|
||||||
|
sync.sync(targetFramerate); // sleep as needed to meet the target framerate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanupWindows () {
|
||||||
|
synchronized (lifecycleListeners) {
|
||||||
|
for (LifecycleListener lifecycleListener : lifecycleListeners) {
|
||||||
|
lifecycleListener.pause();
|
||||||
|
lifecycleListener.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Lwjgl3Window window : windows) {
|
||||||
|
window.dispose();
|
||||||
|
}
|
||||||
|
windows.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanup () {
|
||||||
|
Lwjgl3Cursor.disposeSystemCursors();
|
||||||
|
audio.dispose();
|
||||||
|
errorCallback.free();
|
||||||
|
errorCallback = null;
|
||||||
|
if (glDebugCallback != null) {
|
||||||
|
glDebugCallback.free();
|
||||||
|
glDebugCallback = null;
|
||||||
|
}
|
||||||
|
GLFW.glfwTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationListener getApplicationListener () {
|
||||||
|
return currentWindow.getListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics getGraphics () {
|
||||||
|
return currentWindow.getGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Audio getAudio () {
|
||||||
|
return audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Input getInput () {
|
||||||
|
return currentWindow.getInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Files getFiles () {
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Net getNet () {
|
||||||
|
return net;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug (String tag, String message) {
|
||||||
|
if (logLevel >= LOG_DEBUG) getApplicationLogger().debug(tag, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug (String tag, String message, Throwable exception) {
|
||||||
|
if (logLevel >= LOG_DEBUG) getApplicationLogger().debug(tag, message, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log (String tag, String message) {
|
||||||
|
if (logLevel >= LOG_INFO) getApplicationLogger().log(tag, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log (String tag, String message, Throwable exception) {
|
||||||
|
if (logLevel >= LOG_INFO) getApplicationLogger().log(tag, message, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error (String tag, String message) {
|
||||||
|
if (logLevel >= LOG_ERROR) getApplicationLogger().error(tag, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error (String tag, String message, Throwable exception) {
|
||||||
|
if (logLevel >= LOG_ERROR) getApplicationLogger().error(tag, message, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLogLevel (int logLevel) {
|
||||||
|
this.logLevel = logLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLogLevel () {
|
||||||
|
return logLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationLogger (ApplicationLogger applicationLogger) {
|
||||||
|
this.applicationLogger = applicationLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationLogger getApplicationLogger () {
|
||||||
|
return applicationLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationType getType () {
|
||||||
|
return ApplicationType.Desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getVersion () {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getJavaHeap () {
|
||||||
|
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getNativeHeap () {
|
||||||
|
return getJavaHeap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Preferences getPreferences (String name) {
|
||||||
|
if (preferences.containsKey(name)) {
|
||||||
|
return preferences.get(name);
|
||||||
|
} else {
|
||||||
|
Preferences prefs = new Lwjgl3Preferences(
|
||||||
|
new Lwjgl3FileHandle(new File(config.preferencesDirectory, name), config.preferencesFileType));
|
||||||
|
preferences.put(name, prefs);
|
||||||
|
return prefs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Clipboard getClipboard () {
|
||||||
|
return clipboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postRunnable (Runnable runnable) {
|
||||||
|
synchronized (runnables) {
|
||||||
|
runnables.add(runnable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exit () {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLifecycleListener (LifecycleListener listener) {
|
||||||
|
synchronized (lifecycleListeners) {
|
||||||
|
lifecycleListeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeLifecycleListener (LifecycleListener listener) {
|
||||||
|
synchronized (lifecycleListeners) {
|
||||||
|
lifecycleListeners.removeValue(listener, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lwjgl3Audio createAudio (Lwjgl3ApplicationConfiguration config) {
|
||||||
|
return new OpenALLwjgl3Audio(config.audioDeviceSimultaneousSources, config.audioDeviceBufferCount,
|
||||||
|
config.audioDeviceBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Lwjgl3Input createInput (Lwjgl3Window window) {
|
||||||
|
return new DefaultLwjgl3Input(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Files createFiles () {
|
||||||
|
return new Lwjgl3Files();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a new {@link Lwjgl3Window} using the provided listener and {@link Lwjgl3WindowConfiguration}.
|
||||||
|
*
|
||||||
|
* This function only just instantiates a {@link Lwjgl3Window} and returns immediately. The actual window creation is postponed
|
||||||
|
* with {@link Application#postRunnable(Runnable)} until after all existing windows are updated. */
|
||||||
|
public Lwjgl3Window newWindow (ApplicationListener listener, Lwjgl3WindowConfiguration config) {
|
||||||
|
Lwjgl3ApplicationConfiguration appConfig = Lwjgl3ApplicationConfiguration.copy(this.config);
|
||||||
|
appConfig.setWindowConfiguration(config);
|
||||||
|
if (appConfig.title == null) appConfig.title = listener.getClass().getSimpleName();
|
||||||
|
return createWindow(appConfig, listener, windows.get(0).getWindowHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Lwjgl3Window createWindow (final Lwjgl3ApplicationConfiguration config, ApplicationListener listener,
|
||||||
|
final long sharedContext) {
|
||||||
|
final Lwjgl3Window window = new Lwjgl3Window(listener, config, this);
|
||||||
|
if (sharedContext == 0) {
|
||||||
|
// the main window is created immediately
|
||||||
|
createWindow(window, config, sharedContext);
|
||||||
|
} else {
|
||||||
|
// creation of additional windows is deferred to avoid GL context trouble
|
||||||
|
postRunnable(new Runnable() {
|
||||||
|
public void run () {
|
||||||
|
createWindow(window, config, sharedContext);
|
||||||
|
windows.add(window);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createWindow (Lwjgl3Window window, Lwjgl3ApplicationConfiguration config, long sharedContext) {
|
||||||
|
long windowHandle = createGlfwWindow(config, sharedContext);
|
||||||
|
window.create(windowHandle);
|
||||||
|
window.setVisible(config.initialVisible);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
GL11.glClearColor(config.initialBackgroundColor.r, config.initialBackgroundColor.g, config.initialBackgroundColor.b,
|
||||||
|
config.initialBackgroundColor.a);
|
||||||
|
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
|
||||||
|
GLFW.glfwSwapBuffers(windowHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static long createGlfwWindow (Lwjgl3ApplicationConfiguration config, long sharedContextWindow) {
|
||||||
|
GLFW.glfwDefaultWindowHints();
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, config.windowResizable ? GLFW.GLFW_TRUE : GLFW.GLFW_FALSE);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_MAXIMIZED, config.windowMaximized ? GLFW.GLFW_TRUE : GLFW.GLFW_FALSE);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_AUTO_ICONIFY, config.autoIconify ? GLFW.GLFW_TRUE : GLFW.GLFW_FALSE);
|
||||||
|
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_RED_BITS, config.r);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_GREEN_BITS, config.g);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_BLUE_BITS, config.b);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_ALPHA_BITS, config.a);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_STENCIL_BITS, config.stencil);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_DEPTH_BITS, config.depth);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_SAMPLES, config.samples);
|
||||||
|
|
||||||
|
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.GL30
|
||||||
|
|| config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.GL31
|
||||||
|
|| config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.GL32) {
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, config.gles30ContextMajorVersion);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, config.gles30ContextMinorVersion);
|
||||||
|
if (SharedLibraryLoader.isMac) {
|
||||||
|
// hints mandatory on OS X for GL 3.2+ context creation, but fail on Windows if the
|
||||||
|
// WGL_ARB_create_context extension is not available
|
||||||
|
// see: http://www.glfw.org/docs/latest/compat.html
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) {
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_CREATION_API, GLFW.GLFW_EGL_CONTEXT_API);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_CLIENT_API, GLFW.GLFW_OPENGL_ES_API);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.transparentFramebuffer) {
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_TRANSPARENT_FRAMEBUFFER, GLFW.GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.debug) {
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_DEBUG_CONTEXT, GLFW.GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
long windowHandle = 0;
|
||||||
|
|
||||||
|
if (config.fullscreenMode != null) {
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_REFRESH_RATE, config.fullscreenMode.refreshRate);
|
||||||
|
windowHandle = GLFW.glfwCreateWindow(config.fullscreenMode.width, config.fullscreenMode.height, config.title,
|
||||||
|
config.fullscreenMode.getMonitor(), sharedContextWindow);
|
||||||
|
} else {
|
||||||
|
GLFW.glfwWindowHint(GLFW.GLFW_DECORATED, config.windowDecorated ? GLFW.GLFW_TRUE : GLFW.GLFW_FALSE);
|
||||||
|
windowHandle = GLFW.glfwCreateWindow(config.windowWidth, config.windowHeight, config.title, 0, sharedContextWindow);
|
||||||
|
}
|
||||||
|
if (windowHandle == 0) {
|
||||||
|
throw new GdxRuntimeException("Couldn't create window");
|
||||||
|
}
|
||||||
|
Lwjgl3Window.setSizeLimits(windowHandle, config.windowMinWidth, config.windowMinHeight, config.windowMaxWidth,
|
||||||
|
config.windowMaxHeight);
|
||||||
|
if (config.fullscreenMode == null) {
|
||||||
|
if (config.windowX == -1 && config.windowY == -1) {
|
||||||
|
int windowWidth = Math.max(config.windowWidth, config.windowMinWidth);
|
||||||
|
int windowHeight = Math.max(config.windowHeight, config.windowMinHeight);
|
||||||
|
if (config.windowMaxWidth > -1) windowWidth = Math.min(windowWidth, config.windowMaxWidth);
|
||||||
|
if (config.windowMaxHeight > -1) windowHeight = Math.min(windowHeight, config.windowMaxHeight);
|
||||||
|
|
||||||
|
long monitorHandle = GLFW.glfwGetPrimaryMonitor();
|
||||||
|
if (config.windowMaximized && config.maximizedMonitor != null) {
|
||||||
|
monitorHandle = config.maximizedMonitor.monitorHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntBuffer areaXPos = BufferUtils.createIntBuffer(1);
|
||||||
|
IntBuffer areaYPos = BufferUtils.createIntBuffer(1);
|
||||||
|
IntBuffer areaWidth = BufferUtils.createIntBuffer(1);
|
||||||
|
IntBuffer areaHeight = BufferUtils.createIntBuffer(1);
|
||||||
|
GLFW.glfwGetMonitorWorkarea(monitorHandle, areaXPos, areaYPos, areaWidth, areaHeight);
|
||||||
|
|
||||||
|
GLFW.glfwSetWindowPos(windowHandle, Math.max(0, areaXPos.get(0) + areaWidth.get(0) / 2 - windowWidth / 2),
|
||||||
|
Math.max(0, areaYPos.get(0) + areaHeight.get(0) / 2 - windowHeight / 2));
|
||||||
|
} else {
|
||||||
|
GLFW.glfwSetWindowPos(windowHandle, config.windowX, config.windowY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.windowMaximized) {
|
||||||
|
GLFW.glfwMaximizeWindow(windowHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config.windowIconPaths != null) {
|
||||||
|
Lwjgl3Window.setIcon(windowHandle, config.windowIconPaths, config.windowIconFileType);
|
||||||
|
}
|
||||||
|
GLFW.glfwMakeContextCurrent(windowHandle);
|
||||||
|
GLFW.glfwSwapInterval(config.vSyncEnabled ? 1 : 0);
|
||||||
|
if (config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20) {
|
||||||
|
try {
|
||||||
|
Class gles = Class.forName("org.lwjgl.opengles.GLES");
|
||||||
|
gles.getMethod("createCapabilities").invoke(gles);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new GdxRuntimeException("Couldn't initialize GLES", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GL.createCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
initiateGL(config.glEmulation == Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20);
|
||||||
|
if (!glVersion.isVersionEqualToOrHigher(2, 0))
|
||||||
|
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
|
||||||
|
+ GL11.glGetString(GL11.GL_VERSION) + "\n" + glVersion.getDebugVersionString());
|
||||||
|
|
||||||
|
if (config.glEmulation != Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20 && !supportsFBO()) {
|
||||||
|
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
|
||||||
|
+ GL11.glGetString(GL11.GL_VERSION) + ", FBO extension: false\n" + glVersion.getDebugVersionString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.debug) {
|
||||||
|
glDebugCallback = GLUtil.setupDebugMessageCallback(config.debugStream);
|
||||||
|
setGLDebugMessageControl(GLDebugMessageSeverity.NOTIFICATION, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return windowHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initiateGL (boolean useGLES20) {
|
||||||
|
if (!useGLES20) {
|
||||||
|
String versionString = GL11.glGetString(GL11.GL_VERSION);
|
||||||
|
String vendorString = GL11.glGetString(GL11.GL_VENDOR);
|
||||||
|
String rendererString = GL11.glGetString(GL11.GL_RENDERER);
|
||||||
|
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Class gles = Class.forName("org.lwjgl.opengles.GLES20");
|
||||||
|
Method getString = gles.getMethod("glGetString", int.class);
|
||||||
|
String versionString = (String)getString.invoke(gles, GL11.GL_VERSION);
|
||||||
|
String vendorString = (String)getString.invoke(gles, GL11.GL_VENDOR);
|
||||||
|
String rendererString = (String)getString.invoke(gles, GL11.GL_RENDERER);
|
||||||
|
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new GdxRuntimeException("Couldn't get GLES version string.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean supportsFBO () {
|
||||||
|
// FBO is in core since OpenGL 3.0, see https://www.opengl.org/wiki/Framebuffer_Object
|
||||||
|
return glVersion.isVersionEqualToOrHigher(3, 0) || GLFW.glfwExtensionSupported("GL_EXT_framebuffer_object")
|
||||||
|
|| GLFW.glfwExtensionSupported("GL_ARB_framebuffer_object");
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum GLDebugMessageSeverity {
|
||||||
|
HIGH(GL43.GL_DEBUG_SEVERITY_HIGH, KHRDebug.GL_DEBUG_SEVERITY_HIGH, ARBDebugOutput.GL_DEBUG_SEVERITY_HIGH_ARB,
|
||||||
|
AMDDebugOutput.GL_DEBUG_SEVERITY_HIGH_AMD), MEDIUM(GL43.GL_DEBUG_SEVERITY_MEDIUM, KHRDebug.GL_DEBUG_SEVERITY_MEDIUM,
|
||||||
|
ARBDebugOutput.GL_DEBUG_SEVERITY_MEDIUM_ARB, AMDDebugOutput.GL_DEBUG_SEVERITY_MEDIUM_AMD), LOW(
|
||||||
|
GL43.GL_DEBUG_SEVERITY_LOW, KHRDebug.GL_DEBUG_SEVERITY_LOW, ARBDebugOutput.GL_DEBUG_SEVERITY_LOW_ARB,
|
||||||
|
AMDDebugOutput.GL_DEBUG_SEVERITY_LOW_AMD), NOTIFICATION(GL43.GL_DEBUG_SEVERITY_NOTIFICATION,
|
||||||
|
KHRDebug.GL_DEBUG_SEVERITY_NOTIFICATION, -1, -1);
|
||||||
|
|
||||||
|
final int gl43, khr, arb, amd;
|
||||||
|
|
||||||
|
GLDebugMessageSeverity (int gl43, int khr, int arb, int amd) {
|
||||||
|
this.gl43 = gl43;
|
||||||
|
this.khr = khr;
|
||||||
|
this.arb = arb;
|
||||||
|
this.amd = amd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enables or disables GL debug messages for the specified severity level. Returns false if the severity level could not be
|
||||||
|
* set (e.g. the NOTIFICATION level is not supported by the ARB and AMD extensions).
|
||||||
|
*
|
||||||
|
* See {@link Lwjgl3ApplicationConfiguration#enableGLDebugOutput(boolean, PrintStream)} */
|
||||||
|
public static boolean setGLDebugMessageControl (GLDebugMessageSeverity severity, boolean enabled) {
|
||||||
|
GLCapabilities caps = GL.getCapabilities();
|
||||||
|
final int GL_DONT_CARE = 0x1100; // not defined anywhere yet
|
||||||
|
|
||||||
|
if (caps.OpenGL43) {
|
||||||
|
GL43.glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, severity.gl43, (IntBuffer)null, enabled);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps.GL_KHR_debug) {
|
||||||
|
KHRDebug.glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, severity.khr, (IntBuffer)null, enabled);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps.GL_ARB_debug_output && severity.arb != -1) {
|
||||||
|
ARBDebugOutput.glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, severity.arb, (IntBuffer)null, enabled);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps.GL_AMD_debug_output && severity.amd != -1) {
|
||||||
|
AMDDebugOutput.glDebugMessageEnableAMD(GL_DONT_CARE, severity.amd, (IntBuffer)null, enabled);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
93
src/net/torvald/btex/BTeXDocument.kt
Normal file
93
src/net/torvald/btex/BTeXDocument.kt
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package net.torvald.terrarum.btex
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-10-28.
|
||||||
|
*/
|
||||||
|
class BTeXDocument {
|
||||||
|
var context = "tome" // tome (cover=hardcover), sheets (cover=typewriter or cover=printout), examination (def=examination)
|
||||||
|
var font = "default" // default or typewriter
|
||||||
|
var inner = "standard"
|
||||||
|
var papersize = "standard"
|
||||||
|
|
||||||
|
var pageWidth = 420
|
||||||
|
var pageHeight = 25 * 24
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DEFAULT_PAGE_BACK = Color(0xe1e1d7ff.toInt())
|
||||||
|
val DEFAULT_PAGE_FORE = Color(0x131311ff)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val pages = ArrayList<BTeXPage>()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun addNewPage(back: Color = DEFAULT_PAGE_BACK) {
|
||||||
|
pages.add(BTeXPage(back, pageWidth, pageHeight))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun appendDrawCall(drawCall: BTeXDrawCall) {
|
||||||
|
pages.last().appendDrawCall(drawCall)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun render(batch: SpriteBatch, page: Int, x: Int, y: Int) {
|
||||||
|
pages[page].render(batch, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BTeXPage(
|
||||||
|
val back: Color,
|
||||||
|
val width: Int,
|
||||||
|
val height: Int,
|
||||||
|
) {
|
||||||
|
private val drawCalls = ArrayList<BTeXDrawCall>()
|
||||||
|
|
||||||
|
fun appendDrawCall(drawCall: BTeXDrawCall) {
|
||||||
|
drawCalls.add(drawCall)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun render(batch: SpriteBatch, x: Int, y: Int) {
|
||||||
|
batch.color = back
|
||||||
|
Toolkit.fillArea(batch, x, y, width, height)
|
||||||
|
drawCalls.forEach {
|
||||||
|
it.draw(batch, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BTeXDrawCall(
|
||||||
|
val posX: Int,
|
||||||
|
val posY: Int,
|
||||||
|
val theme: String,
|
||||||
|
val colour: Color,
|
||||||
|
val font: BitmapFont,
|
||||||
|
val text: String? = null,
|
||||||
|
val texture: TextureRegion? = null,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun draw(batch: SpriteBatch, x: Int, y: Int) {
|
||||||
|
val px = (posX + x).toFloat()
|
||||||
|
val py = (posY + y).toFloat()
|
||||||
|
|
||||||
|
if (theme == "code") {
|
||||||
|
// todo draw code background
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.color = colour
|
||||||
|
|
||||||
|
if (text != null && texture == null) {
|
||||||
|
font.draw(batch, text, px, py)
|
||||||
|
}
|
||||||
|
else if (text == null && texture != null) {
|
||||||
|
batch.draw(texture, px, py)
|
||||||
|
}
|
||||||
|
else throw Error("Text and Texture are both non-null")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
159
src/net/torvald/btex/BTeXParser.kt
Normal file
159
src/net/torvald/btex/BTeXParser.kt
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
package net.torvald.btex
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.btex.BTeXDocument
|
||||||
|
import net.torvald.terrarum.btex.BTeXDrawCall
|
||||||
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
import org.xml.sax.Attributes
|
||||||
|
import org.xml.sax.helpers.DefaultHandler
|
||||||
|
import java.io.*
|
||||||
|
import java.util.*
|
||||||
|
import javax.xml.parsers.SAXParserFactory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-10-28.
|
||||||
|
*/
|
||||||
|
object BTeXParser {
|
||||||
|
|
||||||
|
operator fun invoke(file: FileHandle) = invoke(file.file())
|
||||||
|
|
||||||
|
operator fun invoke(file: File): BTeXDocument {
|
||||||
|
val doc = BTeXDocument()
|
||||||
|
val parser = SAXParserFactory.newDefaultInstance().newSAXParser()
|
||||||
|
val stream = FileInputStream(file)
|
||||||
|
parser.parse(stream, BTeXHandler(doc))
|
||||||
|
return doc
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BTeXHandler(val doc: BTeXDocument) : DefaultHandler() {
|
||||||
|
private val DEFAULT_FONTCOL = Color(0x222222ff)
|
||||||
|
private val LINE_HEIGHT = 24
|
||||||
|
|
||||||
|
private var cover = ""
|
||||||
|
private var inner = ""
|
||||||
|
private var papersize = ""
|
||||||
|
private var def = ""
|
||||||
|
|
||||||
|
private var pageWidth = 420
|
||||||
|
private var pageLines = 25
|
||||||
|
private var pageHeight = 25 * LINE_HEIGHT
|
||||||
|
|
||||||
|
private val blockLut = HashMap<String, ItemID>()
|
||||||
|
|
||||||
|
private val tagStack = ArrayList<String>() // index zero should be "btex"
|
||||||
|
|
||||||
|
|
||||||
|
private var spanColour: String? = null
|
||||||
|
|
||||||
|
|
||||||
|
private var typeX = 0
|
||||||
|
private var typeY = 0
|
||||||
|
|
||||||
|
override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
|
||||||
|
val tag = qName; if (tagStack.isEmpty() && tag != "btex") throw BTeXParsingException("Document is not btex")
|
||||||
|
tagStack.add(tag)
|
||||||
|
|
||||||
|
val attribs = HashMap<String, String>().also {
|
||||||
|
it.putAll((0 until attributes.length).map { attributes.getQName(it) to attributes.getValue(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
val mode = tagStack.getOrNull(1)
|
||||||
|
|
||||||
|
when (tag) {
|
||||||
|
"btex" -> {
|
||||||
|
if (attribs.containsKey("def"))
|
||||||
|
def = attribs["def"]!!
|
||||||
|
else {
|
||||||
|
cover = attribs["cover"] ?: "printout"
|
||||||
|
inner = attribs["inner"] ?: "standard"
|
||||||
|
papersize = attribs["papersize"] ?: "standard"
|
||||||
|
|
||||||
|
pageWidth = pageWidthMap[papersize]!!
|
||||||
|
pageLines = pageHeightMap[papersize]!!
|
||||||
|
pageHeight = pageLines * LINE_HEIGHT
|
||||||
|
|
||||||
|
doc.pageWidth = pageWidth
|
||||||
|
doc.pageHeight = pageHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"pair" -> {
|
||||||
|
if (tagStack.size == 3 && mode == "blocklut") {
|
||||||
|
blockLut[attribs["key"]!!] = attribs["value"]!!
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw BTeXParsingException("<pair> used outside of <blocklut>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"span" -> {
|
||||||
|
attribs["span"]?.let {
|
||||||
|
spanColour = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endElement(uri: String, localName: String, qName: String) {
|
||||||
|
tagStack.removeLast()
|
||||||
|
|
||||||
|
when (qName) {
|
||||||
|
"span" -> {
|
||||||
|
spanColour = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun characters(ch: CharArray, start: Int, length: Int) {
|
||||||
|
val str = String(ch.sliceArray(start until start+length)).replace('\n',' ').replace(Regex(" +"), " ").trim()
|
||||||
|
val font = getFont()
|
||||||
|
advanceCursorPre(font.getWidth(str), 0)
|
||||||
|
doc.appendDrawCall(BTeXDrawCall(typeX, typeY, inner, getSpanColour(), font, str))
|
||||||
|
advanceCursorPost(font.getWidth(str), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun advanceCursorPre(w: Int, h: Int) {
|
||||||
|
if (typeX + w > pageWidth) {
|
||||||
|
typeY += LINE_HEIGHT
|
||||||
|
typeX = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeY + h > pageHeight) {
|
||||||
|
typeX = 0
|
||||||
|
typeY = 0
|
||||||
|
doc.addNewPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun advanceCursorPost(w: Int, h: Int) {
|
||||||
|
typeX += w
|
||||||
|
typeY += h
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getFont() = when (cover) {
|
||||||
|
"typewriter" -> TODO()
|
||||||
|
else -> App.fontGame
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSpanColour(): Color = spanColourMap.getOrDefault(spanColour, DEFAULT_FONTCOL)
|
||||||
|
|
||||||
|
private val spanColourMap = hashMapOf(
|
||||||
|
"grey" to Color.LIGHT_GRAY
|
||||||
|
)
|
||||||
|
|
||||||
|
private val pageWidthMap = hashMapOf(
|
||||||
|
"standard" to 420
|
||||||
|
)
|
||||||
|
private val pageHeightMap = hashMapOf(
|
||||||
|
"standard" to 25
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class BTeXParsingException(s: String) : RuntimeException(s) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,8 +12,8 @@ import com.badlogic.gdx.graphics.glutils.*;
|
|||||||
import com.badlogic.gdx.utils.Disposable;
|
import com.badlogic.gdx.utils.Disposable;
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||||
import com.badlogic.gdx.utils.JsonValue;
|
import com.badlogic.gdx.utils.JsonValue;
|
||||||
import com.badlogic.gdx.utils.SharedLibraryLoader;
|
|
||||||
import com.github.strikerx3.jxinput.XInputDevice;
|
import com.github.strikerx3.jxinput.XInputDevice;
|
||||||
|
import kotlin.text.Charsets;
|
||||||
import net.torvald.getcpuname.GetCpuName;
|
import net.torvald.getcpuname.GetCpuName;
|
||||||
import net.torvald.terrarum.controller.GdxControllerAdapter;
|
import net.torvald.terrarum.controller.GdxControllerAdapter;
|
||||||
import net.torvald.terrarum.controller.TerrarumController;
|
import net.torvald.terrarum.controller.TerrarumController;
|
||||||
@@ -41,6 +41,8 @@ import net.torvald.unsafe.AddressOverflowException;
|
|||||||
import net.torvald.unsafe.DanglingPointerException;
|
import net.torvald.unsafe.DanglingPointerException;
|
||||||
import net.torvald.unsafe.UnsafeHelper;
|
import net.torvald.unsafe.UnsafeHelper;
|
||||||
import net.torvald.util.DebugTimers;
|
import net.torvald.util.DebugTimers;
|
||||||
|
import org.apache.commons.csv.CSVFormat;
|
||||||
|
import org.apache.commons.csv.CSVParser;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
@@ -72,6 +74,11 @@ public class App implements ApplicationListener {
|
|||||||
(VERSION_TAG.isBlank() ? "" : "-"+VERSION_TAG) + (snap == null ? "" : (" (" + snap + ")"));
|
(VERSION_TAG.isBlank() ? "" : "-"+VERSION_TAG) + (snap == null ? "" : (" (" + snap + ")"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final String getVERSION_STRING_WITHOUT_SNAPSHOT() {
|
||||||
|
return String.format("%d.%d.%d", VERSION_RAW >>> 48, (VERSION_RAW & 0xffff000000L) >>> 24, VERSION_RAW & 0xffffffL) +
|
||||||
|
(VERSION_TAG.isBlank() ? "" : "-"+VERSION_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* when FALSE, some assertion and print code will not execute
|
* when FALSE, some assertion and print code will not execute
|
||||||
*/
|
*/
|
||||||
@@ -186,7 +193,6 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean splashDisplayed = false;
|
|
||||||
private static boolean postInitFired = false;
|
private static boolean postInitFired = false;
|
||||||
private static boolean screenshotRequested = false;
|
private static boolean screenshotRequested = false;
|
||||||
private static boolean resizeRequested = false;
|
private static boolean resizeRequested = false;
|
||||||
@@ -242,8 +248,7 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
|
|
||||||
public static Texture[] ditherPatterns = new Texture[4];
|
public static Texture[] ditherPatterns = new Texture[4];
|
||||||
private static ShaderProgram shaderBayerSkyboxFill; // ONLY to be used by the splash screen
|
// public static ShaderProgram shaderHicolour;
|
||||||
public static ShaderProgram shaderHicolour;
|
|
||||||
public static ShaderProgram shaderDebugDiff;
|
public static ShaderProgram shaderDebugDiff;
|
||||||
public static ShaderProgram shaderPassthruRGBA;
|
public static ShaderProgram shaderPassthruRGBA;
|
||||||
public static ShaderProgram shaderColLUT;
|
public static ShaderProgram shaderColLUT;
|
||||||
@@ -254,7 +259,8 @@ public class App implements ApplicationListener {
|
|||||||
public static Mesh fullscreenQuad;
|
public static Mesh fullscreenQuad;
|
||||||
private static OrthographicCamera camera;
|
private static OrthographicCamera camera;
|
||||||
private static FlippingSpriteBatch logoBatch;
|
private static FlippingSpriteBatch logoBatch;
|
||||||
public static TextureRegion logo;
|
public static TextureRegion splashScreenLogo;
|
||||||
|
private static TextureRegion splashBackdrop;
|
||||||
public static AudioDevice audioDevice;
|
public static AudioDevice audioDevice;
|
||||||
|
|
||||||
public static FlippingSpriteBatch batch;
|
public static FlippingSpriteBatch batch;
|
||||||
@@ -339,6 +345,8 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
public static boolean gl40capable = false;
|
public static boolean gl40capable = false;
|
||||||
|
|
||||||
|
public static Thread audioManagerThread;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
long st = System.nanoTime();
|
long st = System.nanoTime();
|
||||||
@@ -475,8 +483,53 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Color splashTextCol = new Color(0x282828FF);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create() {
|
public void create() {
|
||||||
|
File loadOrderFile = new File(App.loadOrderDir);
|
||||||
|
if (loadOrderFile.exists()) {
|
||||||
|
// load modules
|
||||||
|
CSVParser loadOrderCSVparser = null;
|
||||||
|
try {
|
||||||
|
loadOrderCSVparser = CSVParser.parse(
|
||||||
|
loadOrderFile,
|
||||||
|
Charsets.UTF_8,
|
||||||
|
CSVFormat.DEFAULT.withCommentMarker('#')
|
||||||
|
);
|
||||||
|
var loadOrder = loadOrderCSVparser.getRecords();
|
||||||
|
|
||||||
|
if (loadOrder.size() > 0) {
|
||||||
|
var modname = loadOrder.get(0).get(0);
|
||||||
|
|
||||||
|
var textureFile = Gdx.files.internal("assets/mods/"+modname+"/splashback.png");
|
||||||
|
if (textureFile.exists()) {
|
||||||
|
splashBackdrop = new TextureRegion(new Texture(textureFile));
|
||||||
|
splashTextCol = new Color(0xeeeeeeff);
|
||||||
|
}
|
||||||
|
|
||||||
|
var logoFile = Gdx.files.internal("assets/mods/"+modname+"/splashlogo.png");
|
||||||
|
if (logoFile.exists()) {
|
||||||
|
splashScreenLogo = new TextureRegion(new Texture(logoFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {loadOrderCSVparser.close();}
|
||||||
|
catch (IOException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splashBackdrop == null) {
|
||||||
|
splashBackdrop = new TextureRegion(new Texture("assets/graphics/background_white.png"));
|
||||||
|
}
|
||||||
|
if (splashScreenLogo == null) {
|
||||||
|
splashScreenLogo = new TextureRegion(new Texture("assets/graphics/logo.png"));
|
||||||
|
}
|
||||||
|
|
||||||
Gdx.graphics.setContinuousRendering(true);
|
Gdx.graphics.setContinuousRendering(true);
|
||||||
|
|
||||||
GAME_LOCALE = getConfigString("language");
|
GAME_LOCALE = getConfigString("language");
|
||||||
@@ -504,10 +557,6 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
initViewPort(scr.getWidth(), scr.getHeight());
|
initViewPort(scr.getWidth(), scr.getHeight());
|
||||||
|
|
||||||
// logo here :p
|
|
||||||
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
|
|
||||||
logo.flip(false, false);
|
|
||||||
|
|
||||||
// set GL graphics constants
|
// set GL graphics constants
|
||||||
for (int i = 0; i < ditherPatterns.length; i++) {
|
for (int i = 0; i < ditherPatterns.length; i++) {
|
||||||
Texture t = new Texture(Gdx.files.classpath("shaders/dither_512_"+i+".tga"));
|
Texture t = new Texture(Gdx.files.classpath("shaders/dither_512_"+i+".tga"));
|
||||||
@@ -516,9 +565,6 @@ public class App implements ApplicationListener {
|
|||||||
ditherPatterns[i] = t;
|
ditherPatterns[i] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
shaderBayerSkyboxFill = loadShaderFromClasspath("shaders/default.vert",
|
|
||||||
"shaders/float_to_disp_dither_static.frag"
|
|
||||||
);
|
|
||||||
shaderPassthruRGBA = loadShaderFromClasspath("shaders/gl32spritebatch.vert", "shaders/gl32spritebatch.frag");
|
shaderPassthruRGBA = loadShaderFromClasspath("shaders/gl32spritebatch.vert", "shaders/gl32spritebatch.frag");
|
||||||
shaderReflect = loadShaderFromClasspath("shaders/default.vert", "shaders/reflect.frag");
|
shaderReflect = loadShaderFromClasspath("shaders/default.vert", "shaders/reflect.frag");
|
||||||
hq2x = new Hq2x(2);
|
hq2x = new Hq2x(2);
|
||||||
@@ -545,20 +591,22 @@ public class App implements ApplicationListener {
|
|||||||
private FrameBuffer postProcessorOutFBO;
|
private FrameBuffer postProcessorOutFBO;
|
||||||
private FrameBuffer postProcessorOutFBO2;
|
private FrameBuffer postProcessorOutFBO2;
|
||||||
|
|
||||||
@Override
|
private void firePostInit() {
|
||||||
public void render() {
|
if (!postInitFired) {
|
||||||
// Gdx.gl.glDisable(GL20.GL_DITHER);
|
|
||||||
|
|
||||||
if (splashDisplayed && !postInitFired) {
|
|
||||||
postInitFired = true;
|
postInitFired = true;
|
||||||
postInit();
|
postInit();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
// Gdx.gl.glDisable(GL20.GL_DITHER);
|
||||||
|
|
||||||
App.setDebugTime("GDX.rawDelta", (long) (Gdx.graphics.getDeltaTime() * 1000_000_000f));
|
App.setDebugTime("GDX.rawDelta", (long) (Gdx.graphics.getDeltaTime() * 1000_000_000f));
|
||||||
|
|
||||||
|
|
||||||
FrameBufferManager.begin(renderFBO);
|
FrameBufferManager.begin(renderFBO);
|
||||||
gdxClearAndEnableBlend(.094f, .094f, .094f, 0f);
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f);
|
||||||
setCameraPosition(0, 0);
|
setCameraPosition(0, 0);
|
||||||
|
|
||||||
|
|
||||||
@@ -571,6 +619,8 @@ public class App implements ApplicationListener {
|
|||||||
loadTimer += Gdx.graphics.getDeltaTime();
|
loadTimer += Gdx.graphics.getDeltaTime();
|
||||||
|
|
||||||
if (loadTimer >= showupTime) {
|
if (loadTimer >= showupTime) {
|
||||||
|
firePostInit();
|
||||||
|
|
||||||
// hand over the scene control to this single class; Terrarum must call
|
// hand over the scene control to this single class; Terrarum must call
|
||||||
// 'AppLoader.getINSTANCE().screen.render(delta)', this is not redundant at all!
|
// 'AppLoader.getINSTANCE().screen.render(delta)', this is not redundant at all!
|
||||||
|
|
||||||
@@ -590,10 +640,13 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
// draw the screen
|
// draw the screen
|
||||||
else {
|
else {
|
||||||
|
firePostInit();
|
||||||
|
|
||||||
currentScreen.render(UPDATE_RATE);
|
currentScreen.render(UPDATE_RATE);
|
||||||
postProcessorOutFBO = TerrarumPostProcessor.INSTANCE.draw(camera.combined, renderFBO);
|
postProcessorOutFBO = TerrarumPostProcessor.INSTANCE.draw(camera.combined, renderFBO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KeyToggler.INSTANCE.update(currentScreen instanceof TerrarumIngame);
|
KeyToggler.INSTANCE.update(currentScreen instanceof TerrarumIngame);
|
||||||
|
|
||||||
|
|
||||||
@@ -649,7 +702,6 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
splashDisplayed = true;
|
|
||||||
GLOBAL_RENDER_TIMER += 1;
|
GLOBAL_RENDER_TIMER += 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -688,50 +740,78 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void drawSplash() {
|
private void drawSplash() {
|
||||||
getCurrentDitherTex().bind(0);
|
|
||||||
shaderBayerSkyboxFill.bind();
|
|
||||||
shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined);
|
|
||||||
shaderBayerSkyboxFill.setUniformi("u_texture", 0);
|
|
||||||
shaderBayerSkyboxFill.setUniformf("parallax_size", 0f);
|
|
||||||
shaderBayerSkyboxFill.setUniformf("topColor", gradWhiteTop.r, gradWhiteTop.g, gradWhiteTop.b, 1f);
|
|
||||||
shaderBayerSkyboxFill.setUniformf("bottomColor", gradWhiteBottom.r, gradWhiteBottom.g, gradWhiteBottom.b, 1f);
|
|
||||||
fullscreenQuad.render(shaderBayerSkyboxFill, GL20.GL_TRIANGLE_FAN);
|
|
||||||
|
|
||||||
|
|
||||||
setCameraPosition(0f, 0f);
|
setCameraPosition(0f, 0f);
|
||||||
|
|
||||||
|
logoBatch.setColor(Color.WHITE);
|
||||||
|
logoBatch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
|
||||||
int drawWidth = Toolkit.INSTANCE.getDrawWidth();
|
int drawWidth = Toolkit.INSTANCE.getDrawWidth();
|
||||||
int safetyTextLen = fontGame.getWidth(Lang.INSTANCE.get("APP_WARNING_HEALTH_AND_SAFETY", true));
|
int safetyTextLen = fontGame.getWidth(Lang.INSTANCE.get("APP_WARNING_HEALTH_AND_SAFETY", true));
|
||||||
int logoPosX = (drawWidth - logo.getRegionWidth() - safetyTextLen) >>> 1;
|
int logoPosX = (drawWidth - splashScreenLogo.getRegionWidth() - safetyTextLen) >>> 1;
|
||||||
int logoPosY = Math.round(scr.getHeight() / 15f);
|
int logoPosY = Math.round(scr.getHeight() / 15f);
|
||||||
int textY = logoPosY + logo.getRegionHeight() - 16;
|
int textY = logoPosY + splashScreenLogo.getRegionHeight() - 16;
|
||||||
|
|
||||||
|
// draw custom backdrop (if exists)
|
||||||
|
if (splashBackdrop != null) {
|
||||||
|
logoBatch.setShader(null);
|
||||||
|
logoBatch.begin();
|
||||||
|
|
||||||
|
|
||||||
|
var size = ((float) Math.max(scr.getWidth(), scr.getHeight()));
|
||||||
|
var x = 0f;
|
||||||
|
var y = 0f;
|
||||||
|
if (scr.getWidth() > scr.getHeight()) {
|
||||||
|
y = (scr.getHeight() - size) / 2f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x = (scr.getWidth() - size) / 2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
logoBatch.draw(splashBackdrop, x, y, size, size);
|
||||||
|
|
||||||
|
|
||||||
|
logoBatch.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// draw logo reflection
|
// draw logo reflection
|
||||||
logoBatch.setShader(shaderReflect);
|
logoBatch.setShader(shaderReflect);
|
||||||
logoBatch.setColor(Color.WHITE);
|
logoBatch.setColor(Color.WHITE);
|
||||||
logoBatch.begin();
|
logoBatch.begin();
|
||||||
|
|
||||||
if (getConfigBoolean("showhealthmessageonstartup")) {
|
if (getConfigBoolean("showhealthmessageonstartup")) {
|
||||||
logoBatch.draw(logo, logoPosX, logoPosY + logo.getRegionHeight());
|
logoBatch.draw(splashScreenLogo, logoPosX, logoPosY + splashScreenLogo.getRegionHeight());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logoBatch.draw(logo, (drawWidth - logo.getRegionWidth()) / 2f,
|
logoBatch.draw(splashScreenLogo, (drawWidth - splashScreenLogo.getRegionWidth()) / 2f,
|
||||||
(scr.getHeight() - logo.getRegionHeight() * 2) / 2f + logo.getRegionHeight()
|
(scr.getHeight() - splashScreenLogo.getRegionHeight() * 2) / 2f + splashScreenLogo.getRegionHeight()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
logoBatch.end();
|
||||||
|
logoBatch.setShader(null);
|
||||||
|
logoBatch.begin();
|
||||||
|
if (getConfigBoolean("showhealthmessageonstartup")) {
|
||||||
|
logoBatch.draw(splashScreenLogo, logoPosX, logoPosY);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logoBatch.draw(splashScreenLogo, (drawWidth - splashScreenLogo.getRegionWidth()) / 2f,
|
||||||
|
(scr.getHeight() - splashScreenLogo.getRegionHeight() * 2) / 2f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logoBatch.end();
|
logoBatch.end();
|
||||||
|
|
||||||
// draw health messages
|
// draw health messages
|
||||||
logoBatch.setShader(null);
|
|
||||||
logoBatch.begin();
|
|
||||||
|
|
||||||
if (getConfigBoolean("showhealthmessageonstartup")) {
|
if (getConfigBoolean("showhealthmessageonstartup")) {
|
||||||
|
logoBatch.setShader(null);
|
||||||
|
logoBatch.begin();
|
||||||
|
|
||||||
logoBatch.draw(logo, logoPosX, logoPosY);
|
logoBatch.setColor(splashTextCol);
|
||||||
logoBatch.setColor(new Color(0x282828ff));
|
|
||||||
fontGame.draw(logoBatch, Lang.INSTANCE.get("APP_WARNING_HEALTH_AND_SAFETY", true),
|
fontGame.draw(logoBatch, Lang.INSTANCE.get("APP_WARNING_HEALTH_AND_SAFETY", true),
|
||||||
logoPosX + logo.getRegionWidth(),
|
logoPosX + splashScreenLogo.getRegionWidth(),
|
||||||
textY
|
textY
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -747,22 +827,17 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logoBatch.setColor(new Color(0x282828ff));
|
|
||||||
Texture tex1 = CommonResourcePool.INSTANCE.getAsTexture("title_health1");
|
Texture tex1 = CommonResourcePool.INSTANCE.getAsTexture("title_health1");
|
||||||
Texture tex2 = CommonResourcePool.INSTANCE.getAsTexture("title_health2");
|
Texture tex2 = CommonResourcePool.INSTANCE.getAsTexture("title_health2");
|
||||||
int virtualHeight = scr.getHeight() - logoPosY - logo.getRegionHeight() / 4;
|
int virtualHeight = scr.getHeight() - logoPosY - splashScreenLogo.getRegionHeight() / 4;
|
||||||
int virtualHeightOffset = scr.getHeight() - virtualHeight;
|
int virtualHeightOffset = scr.getHeight() - virtualHeight;
|
||||||
logoBatch.drawFlipped(tex1, (drawWidth - tex1.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) - 16, tex1.getWidth(), -tex1.getHeight());
|
logoBatch.drawFlipped(tex1, (drawWidth - tex1.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) - 16, tex1.getWidth(), -tex1.getHeight());
|
||||||
logoBatch.drawFlipped(tex2, (drawWidth - tex2.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) + 16 + tex2.getHeight(), tex2.getWidth(), -tex2.getHeight());
|
logoBatch.drawFlipped(tex2, (drawWidth - tex2.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) + 16 + tex2.getHeight(), tex2.getWidth(), -tex2.getHeight());
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
logoBatch.draw(logo, (drawWidth - logo.getRegionWidth()) / 2f,
|
|
||||||
(scr.getHeight() - logo.getRegionHeight() * 2) / 2f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
logoBatch.end();
|
logoBatch.end();
|
||||||
|
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -840,6 +915,7 @@ public class App implements ApplicationListener {
|
|||||||
public void dispose() {
|
public void dispose() {
|
||||||
System.out.println("Goodbye !");
|
System.out.println("Goodbye !");
|
||||||
|
|
||||||
|
audioManagerThread.interrupt();
|
||||||
|
|
||||||
if (currentScreen != null) {
|
if (currentScreen != null) {
|
||||||
currentScreen.hide();
|
currentScreen.hide();
|
||||||
@@ -854,8 +930,7 @@ public class App implements ApplicationListener {
|
|||||||
for (Texture texture : ditherPatterns) {
|
for (Texture texture : ditherPatterns) {
|
||||||
texture.dispose();
|
texture.dispose();
|
||||||
}
|
}
|
||||||
shaderBayerSkyboxFill.dispose();
|
// shaderHicolour.dispose();
|
||||||
shaderHicolour.dispose();
|
|
||||||
shaderDebugDiff.dispose();
|
shaderDebugDiff.dispose();
|
||||||
shaderPassthruRGBA.dispose();
|
shaderPassthruRGBA.dispose();
|
||||||
shaderColLUT.dispose();
|
shaderColLUT.dispose();
|
||||||
@@ -875,7 +950,8 @@ public class App implements ApplicationListener {
|
|||||||
fontBigNumbers.dispose();
|
fontBigNumbers.dispose();
|
||||||
ItemSlotImageFactory.INSTANCE.dispose();
|
ItemSlotImageFactory.INSTANCE.dispose();
|
||||||
|
|
||||||
logo.getTexture().dispose();
|
splashScreenLogo.getTexture().dispose();
|
||||||
|
splashBackdrop.getTexture().dispose();
|
||||||
|
|
||||||
ModMgr.INSTANCE.disposeMods();
|
ModMgr.INSTANCE.disposeMods();
|
||||||
|
|
||||||
@@ -962,6 +1038,9 @@ public class App implements ApplicationListener {
|
|||||||
* Init stuffs which needs GL context
|
* Init stuffs which needs GL context
|
||||||
*/
|
*/
|
||||||
private void postInit() {
|
private void postInit() {
|
||||||
|
long t1 = System.nanoTime();
|
||||||
|
|
||||||
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("blockmarkings_common", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16, 0, 0, 0, 0, false, false, false));
|
CommonResourcePool.INSTANCE.addToLoadingList("blockmarkings_common", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16, 0, 0, 0, 0, false, false, false));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("blockmarking_actor", () -> new BlockMarkerActor());
|
CommonResourcePool.INSTANCE.addToLoadingList("blockmarking_actor", () -> new BlockMarkerActor());
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("loading_circle_64", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/loading_circle_64.tga"), 64, 64, 0, 0, 0, 0, false, false, false));
|
CommonResourcePool.INSTANCE.addToLoadingList("loading_circle_64", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/loading_circle_64.tga"), 64, 64, 0, 0, 0, 0, false, false, false));
|
||||||
@@ -969,7 +1048,7 @@ public class App implements ApplicationListener {
|
|||||||
CommonResourcePool.INSTANCE.addToLoadingList("inventory_category", () -> new TextureRegionPack("./assets/graphics/gui/inventory/category.tga", 20, 20, 0, 0, 0, 0, false, false, false));
|
CommonResourcePool.INSTANCE.addToLoadingList("inventory_category", () -> new TextureRegionPack("./assets/graphics/gui/inventory/category.tga", 20, 20, 0, 0, 0, 0, false, false, false));
|
||||||
CommonResourcePool.INSTANCE.loadAll();
|
CommonResourcePool.INSTANCE.loadAll();
|
||||||
|
|
||||||
shaderHicolour = loadShaderFromClasspath("shaders/default.vert", "shaders/hicolour.frag");
|
// shaderHicolour = loadShaderFromClasspath("shaders/default.vert", "shaders/hicolour.frag");
|
||||||
shaderDebugDiff = loadShaderFromClasspath("shaders/default.vert", "shaders/diff.frag");
|
shaderDebugDiff = loadShaderFromClasspath("shaders/default.vert", "shaders/diff.frag");
|
||||||
shaderColLUT = loadShaderFromClasspath("shaders/default.vert", "shaders/rgbonly.frag");
|
shaderColLUT = loadShaderFromClasspath("shaders/default.vert", "shaders/rgbonly.frag");
|
||||||
shaderGhastlyWhite = loadShaderFromClasspath("shaders/default.vert", "shaders/ghastlywhite.frag");
|
shaderGhastlyWhite = loadShaderFromClasspath("shaders/default.vert", "shaders/ghastlywhite.frag");
|
||||||
@@ -1106,6 +1185,10 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AudioManager.INSTANCE.getMasterVolume();
|
||||||
|
audioManagerThread = new Thread(new AudioManagerRunnable(), "TerrarumAudioManager");
|
||||||
|
audioManagerThread.start();
|
||||||
|
|
||||||
Terrarum.initialise();
|
Terrarum.initialise();
|
||||||
|
|
||||||
|
|
||||||
@@ -1122,7 +1205,9 @@ public class App implements ApplicationListener {
|
|||||||
printdbg(this, "Has update: " + hasUpdate);
|
printdbg(this, "Has update: " + hasUpdate);
|
||||||
|
|
||||||
|
|
||||||
printdbg(this, "PostInit done");
|
long t2 = System.nanoTime();
|
||||||
|
double tms = (t2 - t1) / 1000000000.0;
|
||||||
|
printdbg(this, "PostInit done; took "+tms+" seconds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1245,6 +1330,10 @@ public class App implements ApplicationListener {
|
|||||||
public static String recycledPlayersDir;
|
public static String recycledPlayersDir;
|
||||||
/** defaultDir + "/Recycled/Worlds" */
|
/** defaultDir + "/Recycled/Worlds" */
|
||||||
public static String recycledWorldsDir;
|
public static String recycledWorldsDir;
|
||||||
|
/** defaultDir + "/Custom/" */
|
||||||
|
public static String customDir;
|
||||||
|
/** defaultDir + "/Custom/Music" */
|
||||||
|
public static String customMusicDir;
|
||||||
|
|
||||||
private static void getDefaultDirectory() {
|
private static void getDefaultDirectory() {
|
||||||
String OS = OSName.toUpperCase();
|
String OS = OSName.toUpperCase();
|
||||||
@@ -1278,6 +1367,8 @@ public class App implements ApplicationListener {
|
|||||||
recycledPlayersDir = defaultDir + "/Recycled/Players";
|
recycledPlayersDir = defaultDir + "/Recycled/Players";
|
||||||
recycledWorldsDir = defaultDir + "/Recycled/Worlds";
|
recycledWorldsDir = defaultDir + "/Recycled/Worlds";
|
||||||
importDir = defaultDir + "/Imports";
|
importDir = defaultDir + "/Imports";
|
||||||
|
customDir = defaultDir + "/Custom";
|
||||||
|
customMusicDir = customDir + "/Music";
|
||||||
|
|
||||||
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
||||||
System.out.println(String.format("os.version = %s", OSVersion));
|
System.out.println(String.format("os.version = %s", OSVersion));
|
||||||
@@ -1293,7 +1384,9 @@ public class App implements ApplicationListener {
|
|||||||
new File(worldsDir),
|
new File(worldsDir),
|
||||||
new File(recycledPlayersDir),
|
new File(recycledPlayersDir),
|
||||||
new File(recycledWorldsDir),
|
new File(recycledWorldsDir),
|
||||||
new File(importDir)
|
new File(importDir),
|
||||||
|
new File(customDir),
|
||||||
|
new File(customMusicDir)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (File it : dirs) {
|
for (File it : dirs) {
|
||||||
@@ -1599,7 +1692,7 @@ public class App implements ApplicationListener {
|
|||||||
System.out.println(prompt+"null");
|
System.out.println(prompt+"null");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String indentation = " ".repeat(out.length() + 15);
|
String indentation = " ".repeat(out.length() + 16);
|
||||||
String[] msgLines = message.toString().split("\\n");
|
String[] msgLines = message.toString().split("\\n");
|
||||||
for (int i = 0; i < msgLines.length; i++) {
|
for (int i = 0; i < msgLines.length; i++) {
|
||||||
System.out.println((i == 0 ? prompt : indentation) + msgLines[i]);
|
System.out.println((i == 0 ? prompt : indentation) + msgLines[i]);
|
||||||
@@ -1621,10 +1714,10 @@ public class App implements ApplicationListener {
|
|||||||
System.out.println(prompt+"null"+csi0);
|
System.out.println(prompt+"null"+csi0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String indentation = " ".repeat(out.length() + 11);
|
String indentation = " ".repeat(out.length() + 16);
|
||||||
String[] msgLines = message.toString().split("\\n");
|
String[] msgLines = message.toString().split("\\n");
|
||||||
for (int i = 0; i < msgLines.length; i++) {
|
for (int i = 0; i < msgLines.length; i++) {
|
||||||
System.out.println((i == 0 ? prompt : indentation) + msgLines[i] + csi0);
|
System.out.println((i == 0 ? prompt : indentation) + csiR + msgLines[i] + csi0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
116
src/net/torvald/terrarum/AudioManager.kt
Normal file
116
src/net/torvald/terrarum/AudioManager.kt
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.backends.lwjgl3.audio.Lwjgl3Audio
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.terrarum.modulebasegame.MusicContainer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any audio reference fed into this manager will get lost; you must manually store and dispose of them on your own.
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2023-11-07.
|
||||||
|
*/
|
||||||
|
object AudioManager {
|
||||||
|
const val DEFAULT_FADEOUT_LEN = 2.4f
|
||||||
|
|
||||||
|
/** Returns a master volume */
|
||||||
|
val masterVolume: Float
|
||||||
|
get() = App.getConfigDouble("mastervolume").toFloat()
|
||||||
|
|
||||||
|
/** Returns a (master volume * bgm volume) */
|
||||||
|
val musicVolume: Float
|
||||||
|
get() = (App.getConfigDouble("bgmvolume") * App.getConfigDouble("mastervolume")).toFloat()
|
||||||
|
|
||||||
|
/** Returns a (master volume * sfx volume */
|
||||||
|
val ambientVolume: Float
|
||||||
|
get() = (App.getConfigDouble("sfxvolume") * App.getConfigDouble("mastervolume")).toFloat()
|
||||||
|
|
||||||
|
|
||||||
|
var currentMusic: MusicContainer? = null
|
||||||
|
var currentAmbient: MusicContainer? = null
|
||||||
|
|
||||||
|
private var nextMusic: MusicContainer? = null
|
||||||
|
|
||||||
|
private var fadeAkku = 0f
|
||||||
|
private var fadeLength = DEFAULT_FADEOUT_LEN
|
||||||
|
|
||||||
|
private var fadeoutFired = false
|
||||||
|
private var fadeinFired = false
|
||||||
|
|
||||||
|
fun update(delta: Float) {
|
||||||
|
(Gdx.audio as? Lwjgl3Audio)?.update()
|
||||||
|
|
||||||
|
|
||||||
|
if (fadeoutFired) {
|
||||||
|
fadeAkku += delta
|
||||||
|
currentMusic?.gdxMusic?.volume = (musicVolume * (1f - (fadeAkku / fadeLength))).coerceIn(0f, 1f)
|
||||||
|
|
||||||
|
// printdbg(this, "Fadeout fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}")
|
||||||
|
|
||||||
|
if (fadeAkku >= fadeLength) {
|
||||||
|
fadeoutFired = false
|
||||||
|
currentMusic?.gdxMusic?.volume = 0f
|
||||||
|
// currentMusic?.gdxMusic?.pause()
|
||||||
|
currentMusic = null
|
||||||
|
|
||||||
|
// printdbg(this, "Fadeout end")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// process fadein request
|
||||||
|
else if (fadeinFired) {
|
||||||
|
fadeAkku += delta
|
||||||
|
currentMusic?.gdxMusic?.volume = (musicVolume * (fadeAkku / fadeLength)).coerceIn(0f, 1f)
|
||||||
|
|
||||||
|
// printdbg(this, "Fadein fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}")
|
||||||
|
|
||||||
|
if (currentMusic?.gdxMusic?.isPlaying == false) {
|
||||||
|
currentMusic?.gdxMusic?.play()
|
||||||
|
// printdbg(this, "Fadein starting music ${currentMusic?.name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fadeAkku >= fadeLength) {
|
||||||
|
currentMusic?.gdxMusic?.volume = musicVolume
|
||||||
|
fadeinFired = false
|
||||||
|
|
||||||
|
// printdbg(this, "Fadein end")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (currentMusic?.gdxMusic?.isPlaying != true && nextMusic != null) {
|
||||||
|
// printdbg(this, "Playing next music: ${nextMusic!!.name}")
|
||||||
|
currentMusic = nextMusic
|
||||||
|
nextMusic = null
|
||||||
|
currentMusic!!.gdxMusic.volume = musicVolume
|
||||||
|
currentMusic!!.gdxMusic.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startMusic(song: MusicContainer) {
|
||||||
|
if (currentMusic?.gdxMusic?.isPlaying == true) {
|
||||||
|
requestFadeOut(DEFAULT_FADEOUT_LEN)
|
||||||
|
}
|
||||||
|
nextMusic = song
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopMusic() {
|
||||||
|
requestFadeOut(DEFAULT_FADEOUT_LEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestFadeOut(length: Float) {
|
||||||
|
if (!fadeoutFired) {
|
||||||
|
fadeLength = length.coerceAtLeast(1f/1024f)
|
||||||
|
fadeAkku = 0f
|
||||||
|
fadeoutFired = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestFadeIn(length: Float) {
|
||||||
|
if (!fadeinFired) {
|
||||||
|
fadeLength = length.coerceAtLeast(1f/1024f)
|
||||||
|
fadeAkku = 0f
|
||||||
|
fadeinFired = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
29
src/net/torvald/terrarum/AudioManagerRunnable.kt
Normal file
29
src/net/torvald/terrarum/AudioManagerRunnable.kt
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import net.torvald.terrarum.gamecontroller.InputStrober
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-08.
|
||||||
|
*/
|
||||||
|
class AudioManagerRunnable : Runnable {
|
||||||
|
|
||||||
|
var oldT = System.nanoTime()
|
||||||
|
var dT = 0f
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
while (!Thread.interrupted()) {
|
||||||
|
try {
|
||||||
|
val T = System.nanoTime()
|
||||||
|
dT = (T - oldT) / 1000000000f
|
||||||
|
oldT = T;
|
||||||
|
AudioManager.update(dT)
|
||||||
|
// println("AudioManagerRunnable dT = ${dT * 1000f} ms")
|
||||||
|
Thread.sleep(30L)
|
||||||
|
}
|
||||||
|
catch (e: InterruptedException) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ import java.net.http.HttpResponse
|
|||||||
*/
|
*/
|
||||||
object CheckUpdate {
|
object CheckUpdate {
|
||||||
|
|
||||||
private val versionNumFull = App.getVERSION_STRING()
|
private val versionNumFull = App.getVERSION_STRING_WITHOUT_SNAPSHOT()
|
||||||
private val versionNumOnly = String.format(
|
private val versionNumOnly = String.format(
|
||||||
"%d.%d.%d",
|
"%d.%d.%d",
|
||||||
App.VERSION_RAW ushr 48,
|
App.VERSION_RAW ushr 48,
|
||||||
|
|||||||
@@ -128,6 +128,10 @@ object DefaultConfig {
|
|||||||
"bgmvolume" to 1.0,
|
"bgmvolume" to 1.0,
|
||||||
"sfxvolume" to 1.0,
|
"sfxvolume" to 1.0,
|
||||||
|
|
||||||
|
"lightpasses" to 3,
|
||||||
|
|
||||||
|
"enablescriptmods" to false,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// settings regarding debugger
|
// settings regarding debugger
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import net.torvald.terrarum.langpack.Lang
|
|||||||
|
|
||||||
object ErrorDisp : Screen {
|
object ErrorDisp : Screen {
|
||||||
|
|
||||||
private val logoTex = App.logo
|
private val logoTex = App.splashScreenLogo
|
||||||
private val font = App.fontGame
|
private val font = App.fontGame
|
||||||
|
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ object ErrorDisp : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(delta: Float) {
|
override fun render(delta: Float) {
|
||||||
gdxClearAndEnableBlend(.094f, .094f, .094f, 0f)
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package net.torvald.terrarum
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
@@ -22,6 +22,7 @@ import net.torvald.terrarum.modulebasegame.ui.UITooltip
|
|||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.savegame.VirtualDisk
|
import net.torvald.terrarum.savegame.VirtualDisk
|
||||||
import net.torvald.terrarum.ui.ConsoleWindow
|
import net.torvald.terrarum.ui.ConsoleWindow
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
import net.torvald.util.SortedArrayList
|
import net.torvald.util.SortedArrayList
|
||||||
import org.khelekore.prtree.*
|
import org.khelekore.prtree.*
|
||||||
@@ -90,7 +91,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
init {
|
init {
|
||||||
consoleHandler.setPosition(0, 0)
|
consoleHandler.setPosition(0, 0)
|
||||||
notifier.setPosition(
|
notifier.setPosition(
|
||||||
(App.scr.width - notifier.width) / 2,
|
(Toolkit.drawWidth - notifier.width) / 2,
|
||||||
App.scr.height - notifier.height - App.scr.tvSafeGraphicsHeight
|
App.scr.height - notifier.height - App.scr.tvSafeGraphicsHeight
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -186,6 +187,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(updateRate: Float) {
|
override fun render(updateRate: Float) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pause() {
|
override fun pause() {
|
||||||
@@ -333,10 +335,10 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
|
|
||||||
protected open fun forceRemoveActor(actor: Actor, caller: Throwable = StackTraceRecorder()) {
|
protected open fun forceRemoveActor(actor: Actor, caller: Throwable = StackTraceRecorder()) {
|
||||||
arrayOf(actorContainerActive, actorContainerInactive).forEach { actorContainer ->
|
arrayOf(actorContainerActive, actorContainerInactive).forEach { actorContainer ->
|
||||||
val indexToDelete = actorContainer.searchFor(actor.referenceID) { it.referenceID }
|
val indexToDelete = actorContainer.searchForIndex(actor.referenceID) { it.referenceID }
|
||||||
if (indexToDelete != null) {
|
if (indexToDelete != null) {
|
||||||
actor.dispose()
|
actor.dispose()
|
||||||
actorContainer.remove(indexToDelete)
|
actorContainer.removeAt(indexToDelete)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,7 +350,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
throw ReferencedActorAlreadyExistsException(actor, caller)
|
throw ReferencedActorAlreadyExistsException(actor, caller)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
actorAdditionQueue.add(actor to StackTraceRecorder())
|
actorContainerActive.add(actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,6 +547,8 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
|
|
||||||
fun onConfigChange() {
|
fun onConfigChange() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open val musicGovernor: MusicGovernor = MusicGovernor()
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun Lock.lock(body: () -> Unit) {
|
inline fun Lock.lock(body: () -> Unit) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
|||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
|
|
||||||
open class LoadScreenBase : ScreenAdapter(), Disposable, TerrarumGamescreen {
|
open class LoadScreenBase : ScreenAdapter(), Disposable, TerrarumGamescreen {
|
||||||
|
|
||||||
@@ -26,6 +27,9 @@ open class LoadScreenBase : ScreenAdapter(), Disposable, TerrarumGamescreen {
|
|||||||
|
|
||||||
var camera = OrthographicCamera(App.scr.wf, App.scr.hf)
|
var camera = OrthographicCamera(App.scr.wf, App.scr.hf)
|
||||||
|
|
||||||
|
var progress = AtomicLong(0L) // generic variable, interpretation will vary by the screen
|
||||||
|
var stageValue = 0
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
messages.clear()
|
messages.clear()
|
||||||
doContextChange = false
|
doContextChange = false
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.badlogic.gdx.utils.JsonValue
|
|||||||
import net.torvald.terrarum.App.*
|
import net.torvald.terrarum.App.*
|
||||||
import net.torvald.terrarum.App.setToGameConfig
|
import net.torvald.terrarum.App.setToGameConfig
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
|
import net.torvald.terrarum.blockproperties.OreCodex
|
||||||
import net.torvald.terrarum.blockproperties.WireCodex
|
import net.torvald.terrarum.blockproperties.WireCodex
|
||||||
import net.torvald.terrarum.gamecontroller.IME
|
import net.torvald.terrarum.gamecontroller.IME
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
@@ -14,6 +15,9 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||||
import net.torvald.terrarum.itemproperties.MaterialCodex
|
import net.torvald.terrarum.itemproperties.MaterialCodex
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.modulebasegame.worldgenerator.OregenParams
|
||||||
|
import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen
|
||||||
|
import net.torvald.terrarum.serialise.Common
|
||||||
import net.torvald.terrarum.utils.CSVFetcher
|
import net.torvald.terrarum.utils.CSVFetcher
|
||||||
import net.torvald.terrarum.utils.JsonFetcher
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
import net.torvald.terrarum.utils.forEachSiblings
|
import net.torvald.terrarum.utils.forEachSiblings
|
||||||
@@ -66,8 +70,10 @@ object ModMgr {
|
|||||||
val version: String,
|
val version: String,
|
||||||
val jar: String,
|
val jar: String,
|
||||||
val dependencies: Array<String>,
|
val dependencies: Array<String>,
|
||||||
val isInternal: Boolean
|
val isInternal: Boolean,
|
||||||
|
val configPlan: List<String>
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
"\tModule #$order -- $properName | $version | $author\n" +
|
"\tModule #$order -- $properName | $version | $author\n" +
|
||||||
"\t$description | $releaseDate\n" +
|
"\t$description | $releaseDate\n" +
|
||||||
@@ -120,7 +126,7 @@ object ModMgr {
|
|||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val loadOrderFile = FileSystems.getDefault().getPath("${App.defaultDir}/LoadOrder.txt").toFile()
|
val loadOrderFile = File(App.loadOrderDir)
|
||||||
if (loadOrderFile.exists()) {
|
if (loadOrderFile.exists()) {
|
||||||
|
|
||||||
// load modules
|
// load modules
|
||||||
@@ -134,6 +140,10 @@ object ModMgr {
|
|||||||
|
|
||||||
|
|
||||||
loadOrder.forEachIndexed { index, it ->
|
loadOrder.forEachIndexed { index, it ->
|
||||||
|
|
||||||
|
val loadScriptMod = if (App.getConfigBoolean("enablescriptmods")) true else (index == 0)
|
||||||
|
|
||||||
|
|
||||||
val moduleName = it[0]
|
val moduleName = it[0]
|
||||||
this.loadOrder.add(moduleName)
|
this.loadOrder.add(moduleName)
|
||||||
printmsg(this, "Loading module $moduleName")
|
printmsg(this, "Loading module $moduleName")
|
||||||
@@ -191,7 +201,14 @@ object ModMgr {
|
|||||||
val dependency = modMetadata.getProperty("dependency").split(Regex(""";[ ]*""")).filter { it.isNotEmpty() }.toTypedArray()
|
val dependency = modMetadata.getProperty("dependency").split(Regex(""";[ ]*""")).filter { it.isNotEmpty() }.toTypedArray()
|
||||||
val isDir = FileSystems.getDefault().getPath("$modDir/$moduleName").toFile().isDirectory
|
val isDir = FileSystems.getDefault().getPath("$modDir/$moduleName").toFile().isDirectory
|
||||||
|
|
||||||
module = ModuleMetadata(index, isDir, getGdxFile("$modDir/$moduleName/icon.png"), properName, description, descTranslations, author, packageName, entryPoint, releaseDate, version, jar, dependency, isInternal)
|
val configPlan = ArrayList<String>()
|
||||||
|
File("$modDir/$moduleName/configplan.csv").let {
|
||||||
|
if (it.exists() && it.isFile) {
|
||||||
|
configPlan.addAll(it.readLines(Common.CHARSET).filter { it.isNotBlank() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module = ModuleMetadata(index, isDir, getGdxFile("$modDir/$moduleName/icon.png"), properName, description, descTranslations, author, packageName, entryPoint, releaseDate, version, jar, dependency, isInternal, configPlan)
|
||||||
|
|
||||||
val versionNumeral = version.split('.')
|
val versionNumeral = version.split('.')
|
||||||
val versionNumber = versionNumeral.toVersionNumber()
|
val versionNumber = versionNumeral.toVersionNumber()
|
||||||
@@ -237,6 +254,11 @@ object ModMgr {
|
|||||||
|
|
||||||
// run entry script in entry point
|
// run entry script in entry point
|
||||||
if (entryPoint.isNotBlank()) {
|
if (entryPoint.isNotBlank()) {
|
||||||
|
if (!loadScriptMod) {
|
||||||
|
throw ScriptModDisallowedException()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var newClass: Class<*>? = null
|
var newClass: Class<*>? = null
|
||||||
try {
|
try {
|
||||||
// for modules that has JAR defined
|
// for modules that has JAR defined
|
||||||
@@ -316,6 +338,14 @@ object ModMgr {
|
|||||||
moduleInfo.remove(moduleName)
|
moduleInfo.remove(moduleName)
|
||||||
if (module != null) moduleInfoErrored[moduleName] = module
|
if (module != null) moduleInfoErrored[moduleName] = module
|
||||||
}
|
}
|
||||||
|
catch (noScriptModule: ScriptModDisallowedException) {
|
||||||
|
printmsgerr(this, noScriptModule.message)
|
||||||
|
|
||||||
|
logError(LoadErrorType.MY_FAULT, moduleName, noScriptModule)
|
||||||
|
|
||||||
|
moduleInfo.remove(moduleName)
|
||||||
|
if (module != null) moduleInfoErrored[moduleName] = module
|
||||||
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
// TODO: Instead of skipping module with error, just display the error message onto the face?
|
// TODO: Instead of skipping module with error, just display the error message onto the face?
|
||||||
|
|
||||||
@@ -339,6 +369,8 @@ object ModMgr {
|
|||||||
private class ModuleDependencyNotSatisfied(want: String, have: String) :
|
private class ModuleDependencyNotSatisfied(want: String, have: String) :
|
||||||
RuntimeException("Required: $want, Installed: $have")
|
RuntimeException("Required: $want, Installed: $have")
|
||||||
|
|
||||||
|
private class ScriptModDisallowedException : RuntimeException("Script Mods disabled")
|
||||||
|
|
||||||
operator fun invoke() { }
|
operator fun invoke() { }
|
||||||
|
|
||||||
/*fun reloadModules() {
|
/*fun reloadModules() {
|
||||||
@@ -475,7 +507,7 @@ object ModMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getLoadOrderTextForSavegame(): String {
|
fun getLoadOrderTextForSavegame(): String {
|
||||||
return loadOrder.map { "$it ${moduleInfo[it]!!.version}" }.joinToString("\n")
|
return loadOrder.filter { moduleInfo[it] != null }.map { "$it ${moduleInfo[it]!!.version}" }.joinToString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -491,6 +523,34 @@ object ModMgr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object GameOreLoader {
|
||||||
|
init {
|
||||||
|
Terrarum.oreCodex = OreCodex()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic operator fun invoke(module: String) {
|
||||||
|
// register ore codex
|
||||||
|
Terrarum.oreCodex.fromModule(module, "ores/ores.csv")
|
||||||
|
|
||||||
|
// register to worldgen
|
||||||
|
try {
|
||||||
|
CSVFetcher.readFromModule(module, "ores/worldgen.csv").forEach { rec ->
|
||||||
|
val tile = "ores@$module:${rec.get("id")}"
|
||||||
|
val freq = rec.get("freq").toDouble()
|
||||||
|
val power = rec.get("power").toDouble()
|
||||||
|
val scale = rec.get("scale").toDouble()
|
||||||
|
val ratio = rec.get("ratio").toDouble()
|
||||||
|
val tiling = rec.get("tiling")
|
||||||
|
|
||||||
|
Worldgen.registerOre(OregenParams(tile, freq, power, scale, ratio, tiling))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object GameItemLoader {
|
object GameItemLoader {
|
||||||
const val itemPath = "items/"
|
const val itemPath = "items/"
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
package net.torvald.terrarum
|
package net.torvald.terrarum
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.modulebasegame.ui.ControlPanelCommon
|
||||||
|
import net.torvald.terrarum.modulebasegame.ui.ControlPanelOptions
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
|
import net.torvald.terrarum.ui.UIItemTextSelector
|
||||||
|
import net.torvald.unicode.TIMES
|
||||||
|
|
||||||
class ModOptionsHost(val remoCon: UIRemoCon) : UICanvas() {
|
class ModOptionsHost(val remoCon: UIRemoCon) : UICanvas() {
|
||||||
init {
|
init {
|
||||||
@@ -14,13 +22,80 @@ class ModOptionsHost(val remoCon: UIRemoCon) : UICanvas() {
|
|||||||
private val moduleAreaHMargin = 48
|
private val moduleAreaHMargin = 48
|
||||||
private val moduleAreaBorder = 8
|
private val moduleAreaBorder = 8
|
||||||
|
|
||||||
override var width = App.scr.width - UIRemoCon.remoConWidth - moduleAreaHMargin
|
override var width = 560
|
||||||
override var height = App.scr.height - moduleAreaHMargin * 2
|
override var height = App.scr.height - moduleAreaHMargin * 2
|
||||||
|
|
||||||
|
private val drawX = (Toolkit.drawWidth - width) / 2
|
||||||
|
private val drawY = (App.scr.height - height) / 2
|
||||||
|
|
||||||
|
private var currentlySelectedModule = "basegame"
|
||||||
|
|
||||||
|
// List<Pair<proper name, mod key>>
|
||||||
|
val configurableMods = ModMgr.moduleInfo.filter { it.value.configPlan.isNotEmpty() }.map { it.value.properName to it.key }.toList().sortedBy { it.second }
|
||||||
|
|
||||||
|
private val modSelectorWidth = 360
|
||||||
|
private val modSelector = UIItemTextSelector(this, drawX + (width - modSelectorWidth) / 2, drawY,
|
||||||
|
configurableMods.map { { it.first } }, 0, modSelectorWidth, false
|
||||||
|
).also { item ->
|
||||||
|
item.selectionChangeListener = {
|
||||||
|
currentlySelectedModule = configurableMods[it].second
|
||||||
|
|
||||||
|
defer {
|
||||||
|
uiItems.clear()
|
||||||
|
makeConfig(currentlySelectedModule)
|
||||||
|
addUIitem(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
printdbg(this, "configurableMods = ${configurableMods.map { it.second }}")
|
||||||
|
|
||||||
|
addUIitem(modSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
super.show()
|
||||||
|
|
||||||
|
makeConfig(currentlySelectedModule)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var deferred = {}
|
||||||
|
private fun defer(what: () -> Unit) {
|
||||||
|
deferred = what
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun makeConfig(modname: String) {
|
||||||
|
val mod = ModMgr.moduleInfo[modname]!!
|
||||||
|
if (mod.configPlan.isEmpty()) return
|
||||||
|
|
||||||
|
val modOptions: ControlPanelOptions = mod.configPlan.map {
|
||||||
|
val options = it.split("->")
|
||||||
|
val labelfun = if (options[1].startsWith("Lang:")) {
|
||||||
|
{ Lang[options[1].substringAfter(":")] }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
{ options[1] }
|
||||||
|
}
|
||||||
|
if (options[0].isBlank())
|
||||||
|
arrayOf("", labelfun, options[2])
|
||||||
|
else
|
||||||
|
arrayOf("$modname:${options[0]}", labelfun, options[2])
|
||||||
|
}.toTypedArray()
|
||||||
|
|
||||||
|
ControlPanelCommon.register(this, width, "basegame.modcontrolpanel.$modname", modOptions)
|
||||||
|
}
|
||||||
|
|
||||||
override fun updateUI(delta: Float) {
|
override fun updateUI(delta: Float) {
|
||||||
|
uiItems.forEach { it.update(delta) }
|
||||||
|
deferred(); deferred = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) {
|
override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) {
|
||||||
|
// the actual control panel
|
||||||
|
ControlPanelCommon.render("basegame.modcontrolpanel.$currentlySelectedModule", width, batch)
|
||||||
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
|||||||
19
src/net/torvald/terrarum/MusicGovernor.kt
Normal file
19
src/net/torvald/terrarum/MusicGovernor.kt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
open class MusicGovernor {
|
||||||
|
|
||||||
|
open fun update(ingameInstance: IngameInstance, delta: Float) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected var state = 0 // 0: disabled, 1: playing, 2: waiting
|
||||||
|
protected var intermissionAkku = 0f
|
||||||
|
protected var intermissionLength = 1f
|
||||||
|
protected var musicFired = false
|
||||||
|
|
||||||
|
|
||||||
|
open fun dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -58,6 +58,8 @@ class NoModuleDefaultTitlescreen(batch: FlippingSpriteBatch) : IngameInstance(ba
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(updateRate: Float) {
|
override fun render(updateRate: Float) {
|
||||||
|
super.render(updateRate)
|
||||||
|
|
||||||
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
||||||
|
|
||||||
if (!init) {
|
if (!init) {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ object SanicLoadScreen : LoadScreenBase() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
gdxClearAndEnableBlend(.094f, .094f, .094f, 0f)
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
||||||
|
|
||||||
textFbo.inAction(null, null) {
|
textFbo.inAction(null, null) {
|
||||||
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
|
||||||
@@ -127,9 +127,9 @@ object SanicLoadScreen : LoadScreenBase() {
|
|||||||
// draw colour overlay, flipped
|
// draw colour overlay, flipped
|
||||||
it.draw(textOverlayTex,
|
it.draw(textOverlayTex,
|
||||||
(textFbo.width - textWidth) / 2f,
|
(textFbo.width - textWidth) / 2f,
|
||||||
App.fontGame.lineHeight,
|
0f,
|
||||||
textWidth,
|
textWidth,
|
||||||
-App.fontGame.lineHeight
|
App.fontGame.lineHeight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,7 @@ object SanicLoadScreen : LoadScreenBase() {
|
|||||||
// --> original text
|
// --> original text
|
||||||
if (genuineSonic) {
|
if (genuineSonic) {
|
||||||
it.color = Color.WHITE
|
it.color = Color.WHITE
|
||||||
it.draw(textTex, textX, glideDispY - 2f)
|
it.draw(textTex, textX, glideDispY - 2f + textTex.height, textTex.width.toFloat(), -textTex.height.toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
// --> ghost
|
// --> ghost
|
||||||
@@ -167,9 +167,9 @@ object SanicLoadScreen : LoadScreenBase() {
|
|||||||
val drawHeight = getPulseEffWidthMul() * textTex.height
|
val drawHeight = getPulseEffWidthMul() * textTex.height
|
||||||
it.draw(textTex,
|
it.draw(textTex,
|
||||||
textX - (drawWidth - textTex.width) / 2f,
|
textX - (drawWidth - textTex.width) / 2f,
|
||||||
glideDispY - 2f - (drawHeight - textTex.height) / 2f,
|
glideDispY - 2f - (drawHeight - textTex.height) / 2f + drawHeight,
|
||||||
drawWidth,
|
drawWidth,
|
||||||
drawHeight
|
-drawHeight
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class SavegameCollection(files0: List<DiskSkimmer>, prefiltered: Boolean) {
|
|||||||
val manualSaves = files.filter { !it.diskFile.extension.matches(Regex("[a-z]")) }
|
val manualSaves = files.filter { !it.diskFile.extension.matches(Regex("[a-z]")) }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
printdbg(this, "Rebuilding skimmers (${files.size})")
|
// printdbg(this, "Rebuilding skimmers (${files.size})")
|
||||||
// files.forEach { it.rebuild() }
|
// files.forEach { it.rebuild() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import net.torvald.terrarum.App.*
|
|||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
|
import net.torvald.terrarum.blockproperties.FluidCodex
|
||||||
|
import net.torvald.terrarum.blockproperties.OreCodex
|
||||||
import net.torvald.terrarum.blockproperties.WireCodex
|
import net.torvald.terrarum.blockproperties.WireCodex
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameactors.ActorID
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
@@ -76,6 +78,8 @@ object Terrarum : Disposable {
|
|||||||
var factionCodex = FactionCodex(); internal set
|
var factionCodex = FactionCodex(); internal set
|
||||||
var craftingCodex = CraftingCodex(); internal set
|
var craftingCodex = CraftingCodex(); internal set
|
||||||
var apocryphas = HashMap<String, Any>(); internal set
|
var apocryphas = HashMap<String, Any>(); internal set
|
||||||
|
var fluidCodex = FluidCodex(); internal set
|
||||||
|
var oreCodex = OreCodex(); internal set
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -258,6 +262,8 @@ object Terrarum : Disposable {
|
|||||||
get() = 1.0 / Gdx.graphics.deltaTime
|
get() = 1.0 / Gdx.graphics.deltaTime
|
||||||
val mouseDown: Boolean
|
val mouseDown: Boolean
|
||||||
get() = Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))
|
get() = Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))
|
||||||
|
val mouseJustDown: Boolean
|
||||||
|
get() = Gdx.input.isButtonJustPressed(App.getConfigInt("config_mouseprimary"))
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -761,6 +767,10 @@ val CraftingRecipeCodex: CraftingCodex
|
|||||||
get() = Terrarum.craftingCodex
|
get() = Terrarum.craftingCodex
|
||||||
val Apocryphas: HashMap<String, Any>
|
val Apocryphas: HashMap<String, Any>
|
||||||
get() = Terrarum.apocryphas
|
get() = Terrarum.apocryphas
|
||||||
|
val FluidCodex: FluidCodex
|
||||||
|
get() = Terrarum.fluidCodex
|
||||||
|
val OreCodex: OreCodex
|
||||||
|
get() = Terrarum.oreCodex
|
||||||
|
|
||||||
class Codex : KVHashMap() {
|
class Codex : KVHashMap() {
|
||||||
|
|
||||||
@@ -784,7 +794,7 @@ fun AppUpdateListOfSavegames() {
|
|||||||
|
|
||||||
|
|
||||||
// create list of worlds
|
// create list of worlds
|
||||||
printdbg("ListSavegames", "Listing saved worlds...")
|
// printdbg("ListSavegames", "Listing saved worlds...")
|
||||||
val worldsDirLs = File(worldsDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
val worldsDirLs = File(worldsDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
||||||
try {
|
try {
|
||||||
DiskSkimmer(file, true)
|
DiskSkimmer(file, true)
|
||||||
@@ -810,16 +820,16 @@ fun AppUpdateListOfSavegames() {
|
|||||||
}
|
}
|
||||||
filteringResults.forEachIndexed { index, list ->
|
filteringResults.forEachIndexed { index, list ->
|
||||||
val it = list.first()
|
val it = list.first()
|
||||||
printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
|
// printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
|
||||||
|
|
||||||
printdbg("ListSavegames", " collecting...")
|
// printdbg("ListSavegames", " collecting...")
|
||||||
val collection = SavegameCollection.collectFromBaseFilename(list, it.diskFile.name)
|
val collection = SavegameCollection.collectFromBaseFilename(list, it.diskFile.name)
|
||||||
printdbg("ListSavegames", " disk rebuilding...")
|
// printdbg("ListSavegames", " disk rebuilding...")
|
||||||
collection.rebuildLoadable()
|
collection.rebuildLoadable()
|
||||||
printdbg("ListSavegames", " get UUID...")
|
// printdbg("ListSavegames", " get UUID...")
|
||||||
val worldUUID = collection.getUUID()
|
val worldUUID = collection.getUUID()
|
||||||
|
|
||||||
printdbg("ListSavegames", " registration...")
|
// printdbg("ListSavegames", " registration...")
|
||||||
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
||||||
if (!App.savegameWorlds.contains(worldUUID)) {
|
if (!App.savegameWorlds.contains(worldUUID)) {
|
||||||
App.savegameWorlds[worldUUID] = collection
|
App.savegameWorlds[worldUUID] = collection
|
||||||
@@ -830,7 +840,7 @@ fun AppUpdateListOfSavegames() {
|
|||||||
|
|
||||||
|
|
||||||
// create list of players
|
// create list of players
|
||||||
printdbg("ListSavegames", "Listing saved players...")
|
// printdbg("ListSavegames", "Listing saved players...")
|
||||||
val playersDirLs = File(playersDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
val playersDirLs = File(playersDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
||||||
try {
|
try {
|
||||||
DiskSkimmer(file, true)
|
DiskSkimmer(file, true)
|
||||||
@@ -856,16 +866,16 @@ fun AppUpdateListOfSavegames() {
|
|||||||
}
|
}
|
||||||
filteringResults2.forEachIndexed { index, list ->
|
filteringResults2.forEachIndexed { index, list ->
|
||||||
val it = list.first()
|
val it = list.first()
|
||||||
printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
|
// printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
|
||||||
|
|
||||||
printdbg("ListSavegames", " collecting...")
|
// printdbg("ListSavegames", " collecting...")
|
||||||
val collection = SavegameCollection.collectFromBaseFilename(list, it.diskFile.name)
|
val collection = SavegameCollection.collectFromBaseFilename(list, it.diskFile.name)
|
||||||
printdbg("ListSavegames", " disk rebuilding...")
|
// printdbg("ListSavegames", " disk rebuilding...")
|
||||||
collection.rebuildLoadable()
|
collection.rebuildLoadable()
|
||||||
printdbg("ListSavegames", " get UUID...")
|
// printdbg("ListSavegames", " get UUID...")
|
||||||
val playerUUID = collection.getUUID()
|
val playerUUID = collection.getUUID()
|
||||||
|
|
||||||
printdbg("ListSavegames", " registration...")
|
// printdbg("ListSavegames", " registration...")
|
||||||
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
||||||
if (!App.savegamePlayers.contains(playerUUID)) {
|
if (!App.savegamePlayers.contains(playerUUID)) {
|
||||||
App.savegamePlayers[playerUUID] = collection
|
App.savegamePlayers[playerUUID] = collection
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ basegame
|
|||||||
* e.g. 0x02010034 will be translated as 2.1.52
|
* e.g. 0x02010034 will be translated as 2.1.52
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const val VERSION_RAW: Long = 0x0000_000003_000003
|
const val VERSION_RAW: Long = 0x0000_000004_000000
|
||||||
// Commit counts up to the Release 0.3.0: 2259
|
// Commit counts up to the Release 0.3.0: 2259
|
||||||
// Commit counts up to the Release 0.3.1: 2278
|
// Commit counts up to the Release 0.3.1: 2278
|
||||||
// Commit counts up to the Release 0.3.2: 2732
|
// Commit counts up to the Release 0.3.2: 2732
|
||||||
// Commit counts up to the Release 0.3.3: ????
|
// Commit counts up to the Release 0.3.3: 3020
|
||||||
|
|
||||||
val VERSION_SNAPSHOT = if (App.IS_DEVELOPMENT_BUILD) Snapshot(0) else null
|
val VERSION_SNAPSHOT = if (App.IS_DEVELOPMENT_BUILD) Snapshot(0) else null
|
||||||
|
|
||||||
@@ -100,6 +100,9 @@ data class Snapshot(var revision: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
if (revision !in 0..7) {
|
||||||
|
throw IllegalArgumentException("Revision out of range -- expected 0..7 (a..h), got $revision")
|
||||||
|
}
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,4 +115,8 @@ data class Snapshot(var revision: Int) {
|
|||||||
revision = (b[0].toUint() ushr 7 shl 2) or b[1].toUint().and(3)
|
revision = (b[0].toUint() ushr 7 shl 2) or b[1].toUint().and(3)
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return year.shl(24) or week.shl(16) or revision
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
outFBO.inAction(camera, batch) {
|
outFBO.inAction(camera, batch) {
|
||||||
App.measureDebugTime("Renderer.PostProcessor") {
|
App.measureDebugTime("Renderer.PostProcessor") {
|
||||||
|
|
||||||
gdxClearAndEnableBlend(.094f, .094f, .094f, 0f)
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
||||||
|
|
||||||
fbo.colorBufferTexture.setFilter(
|
fbo.colorBufferTexture.setFilter(
|
||||||
Texture.TextureFilter.Linear,
|
Texture.TextureFilter.Linear,
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import net.torvald.gdx.graphics.Cvec
|
|||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.ReferencingRanges.PREFIX_VIRTUALTILE
|
import net.torvald.terrarum.ReferencingRanges.PREFIX_VIRTUALTILE
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.FluidType
|
import net.torvald.terrarum.gameitems.isWall
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import net.torvald.terrarum.utils.CSVFetcher
|
import net.torvald.terrarum.utils.CSVFetcher
|
||||||
import net.torvald.util.SortedArrayList
|
import net.torvald.util.SortedArrayList
|
||||||
import org.apache.commons.csv.CSVRecord
|
import org.apache.commons.csv.CSVRecord
|
||||||
@@ -65,7 +64,7 @@ class BlockCodex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun fromCSV(module: String, csvString: String) {
|
fun fromCSV(module: String, csvString: String) {
|
||||||
printdbg(this, "Building wire properties table for module $module")
|
printdbg(this, "Building block properties table for module $module")
|
||||||
|
|
||||||
val csvParser = org.apache.commons.csv.CSVParser.parse(
|
val csvParser = org.apache.commons.csv.CSVParser.parse(
|
||||||
csvString,
|
csvString,
|
||||||
@@ -146,7 +145,7 @@ class BlockCodex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return if (blockID.startsWith("wall@"))
|
return if (blockID.isWall())
|
||||||
blockProps[blockID.substring(5)]!!
|
blockProps[blockID.substring(5)]!!
|
||||||
else
|
else
|
||||||
blockProps[blockID]!!
|
blockProps[blockID]!!
|
||||||
@@ -156,10 +155,10 @@ class BlockCodex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun get(fluidType: FluidType?): BlockProp {
|
/*operator fun get(fluidType: FluidType?): BlockProp {
|
||||||
// TODO fluid from other mods
|
// TODO fluid from other mods
|
||||||
|
|
||||||
if (fluidType == null || fluidType.value == 0) {
|
if (fluidType == null || fluidType == Fluid.NULL) {
|
||||||
return blockProps[Block.AIR]!!
|
return blockProps[Block.AIR]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +168,7 @@ class BlockCodex {
|
|||||||
catch (e: NullPointerException) {
|
catch (e: NullPointerException) {
|
||||||
throw NullPointerException("Blockprop with id $fluidType does not exist.")
|
throw NullPointerException("Blockprop with id $fluidType does not exist.")
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
fun getOrNull(blockID: ItemID?): BlockProp? {//<O>
|
fun getOrNull(blockID: ItemID?): BlockProp? {//<O>
|
||||||
return blockProps[blockID]
|
return blockProps[blockID]
|
||||||
|
|||||||
@@ -1,20 +1,16 @@
|
|||||||
package net.torvald.terrarum.blockproperties
|
package net.torvald.terrarum.blockproperties
|
||||||
|
|
||||||
import net.torvald.terrarum.gameworld.FluidType
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-08-06.
|
* Created by minjaesong on 2016-08-06.
|
||||||
*/
|
*/
|
||||||
object Fluid {
|
object Fluid {
|
||||||
|
|
||||||
val NULL = FluidType(0)
|
val NULL = "fluid@basegame:0"
|
||||||
|
val WATER = "fluid@basegame:1"
|
||||||
val WATER = FluidType(1)
|
val LAVA = "fluid@basegame:2"
|
||||||
val STATIC_WATER = FluidType(-1)
|
|
||||||
|
|
||||||
val LAVA = FluidType(2)
|
|
||||||
val STATIC_LAVA = FluidType(-2)
|
|
||||||
|
|
||||||
|
|
||||||
val fluidRange = 1..2 // TODO MANUAL UPDATE
|
|
||||||
}
|
}
|
||||||
41
src/net/torvald/terrarum/blockproperties/FluidCodex.kt
Normal file
41
src/net/torvald/terrarum/blockproperties/FluidCodex.kt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package net.torvald.terrarum.blockproperties
|
||||||
|
|
||||||
|
import net.torvald.gdx.graphics.Cvec
|
||||||
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-10-09.
|
||||||
|
*/
|
||||||
|
class FluidCodex {
|
||||||
|
|
||||||
|
@Transient val blockProps = HashMap<ItemID, FluidProp>()
|
||||||
|
|
||||||
|
@Transient private val nullProp = FluidProp()
|
||||||
|
|
||||||
|
|
||||||
|
operator fun get(fluidID: ItemID?): FluidProp {
|
||||||
|
if (fluidID == null || fluidID == Fluid.NULL) {
|
||||||
|
return nullProp
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return if (fluidID.startsWith("fluid@"))
|
||||||
|
blockProps[fluidID.substring(6)]!!
|
||||||
|
else
|
||||||
|
blockProps[fluidID]!!
|
||||||
|
}
|
||||||
|
catch (e: NullPointerException) {
|
||||||
|
throw NullPointerException("Fluidprop with id $fluidID does not exist.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FluidProp {
|
||||||
|
val opacity: Cvec = Cvec()
|
||||||
|
val lumCol: Cvec = Cvec()
|
||||||
|
var id: ItemID = ""
|
||||||
|
var nameKey: String = ""
|
||||||
|
}
|
||||||
84
src/net/torvald/terrarum/blockproperties/OreCodex.kt
Normal file
84
src/net/torvald/terrarum/blockproperties/OreCodex.kt
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package net.torvald.terrarum.blockproperties
|
||||||
|
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
import net.torvald.terrarum.utils.CSVFetcher
|
||||||
|
import org.apache.commons.csv.CSVRecord
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-10-11.
|
||||||
|
*/
|
||||||
|
class OreCodex {
|
||||||
|
|
||||||
|
@Transient val oreProps = HashMap<ItemID, OreProp>()
|
||||||
|
@Transient private val nullProp = OreProp()
|
||||||
|
|
||||||
|
internal constructor()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Later entry (possible from other modules) will replace older ones
|
||||||
|
*/
|
||||||
|
fun fromModule(module: String, path: String) {
|
||||||
|
App.printdbg(this, "Building ore properties table")
|
||||||
|
try {
|
||||||
|
register(module, CSVFetcher.readFromModule(module, path))
|
||||||
|
}
|
||||||
|
catch (e: IOException) { e.printStackTrace() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromCSV(module: String, csvString: String) {
|
||||||
|
App.printdbg(this, "Building ore properties table for module $module")
|
||||||
|
|
||||||
|
val csvParser = org.apache.commons.csv.CSVParser.parse(
|
||||||
|
csvString,
|
||||||
|
CSVFetcher.terrarumCSVFormat
|
||||||
|
)
|
||||||
|
val csvRecordList = csvParser.records
|
||||||
|
csvParser.close()
|
||||||
|
|
||||||
|
register(module, csvRecordList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun register(module: String, records: List<CSVRecord>) {
|
||||||
|
records.forEach {
|
||||||
|
setProp(module, it.intVal("id"), it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.item = record.get("item").let { if (it == null) "" else if (it.contains(':')) it else "$modname:$it" }
|
||||||
|
|
||||||
|
oreProps[prop.id] = prop
|
||||||
|
|
||||||
|
App.printdbg(this, "Setting prop ${prop.id}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAll() = oreProps.values
|
||||||
|
|
||||||
|
operator fun get(oreID: ItemID?): OreProp {
|
||||||
|
if (oreID == null || oreID == Block.NULL) {
|
||||||
|
return nullProp
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return oreProps[oreID]!!
|
||||||
|
}
|
||||||
|
catch (e: NullPointerException) {
|
||||||
|
throw NullPointerException("Oreprop with id $oreID does not exist.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class OreProp {
|
||||||
|
var id: String = ""
|
||||||
|
var item: ItemID = ""
|
||||||
|
var tags = HashSet<String>()
|
||||||
|
|
||||||
|
fun hasTag(s: String) = tags.contains(s)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIM
|
|||||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
|
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
|
||||||
import net.torvald.terrarum.sqr
|
import net.torvald.terrarum.sqr
|
||||||
import net.torvald.terrarum.toInt
|
import net.torvald.terrarum.toInt
|
||||||
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
@@ -150,7 +151,7 @@ object MinimapComposer : Disposable {
|
|||||||
val tileTerr = world.getTileFromTerrain(x, y)
|
val tileTerr = world.getTileFromTerrain(x, y)
|
||||||
val wallTerr = world.getTileFromWall(x, y)
|
val wallTerr = world.getTileFromWall(x, y)
|
||||||
val colTerr = App.tileMaker.terrainTileColourMap.get(tileTerr)!!.toGdxColor()
|
val colTerr = App.tileMaker.terrainTileColourMap.get(tileTerr)!!.toGdxColor()
|
||||||
val colWall = App.tileMaker.terrainTileColourMap.get(wallTerr)!!.toGdxColor().mul(App.tileMaker.wallOverlayColour)
|
val colWall = App.tileMaker.terrainTileColourMap.get(wallTerr)!!.toGdxColor().mul(WALL_OVERLAY_COLOUR)
|
||||||
|
|
||||||
var outCol = if (y < 0)
|
var outCol = if (y < 0)
|
||||||
oobColTop
|
oobColTop
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ internal object Authenticator : ConsoleCommand {
|
|||||||
val pwd = args[1]
|
val pwd = args[1]
|
||||||
val hashedPwd = DigestUtils.sha256Hex(pwd)
|
val hashedPwd = DigestUtils.sha256Hex(pwd)
|
||||||
|
|
||||||
println("auth passwd: '$pwd'")
|
// println("auth passwd: '$pwd'")
|
||||||
println("hash: $hashedPwd")
|
// println("hash: $hashedPwd")
|
||||||
|
|
||||||
if ("2d962f949f55906ac47f16095ded190c9e44d95920259b8f36c2e54bd75df173".equals(hashedPwd, ignoreCase = true)) {
|
if ("c40232ae7b8020da3ab1449a015e7cc23f249a790856b63b1b69c6a5de019fed".equals(hashedPwd, ignoreCase = true)) {
|
||||||
// beedle
|
// beedle
|
||||||
val msg = if (a) "Locked" else "Authenticated"
|
val msg = if (a) "Locked" else "Authenticated"
|
||||||
Echo(msg)
|
Echo(msg)
|
||||||
println("[Authenticator] " + msg)
|
println("[Authenticator] $msg")
|
||||||
a = !a
|
a = !a
|
||||||
INGAME.consoleHandler.reset()
|
INGAME.consoleHandler.reset()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,4 +158,11 @@ object AVKey {
|
|||||||
* This value is only used for IngamePlayers
|
* This value is only used for IngamePlayers
|
||||||
*/
|
*/
|
||||||
const val GAMEMODE = "gamemode"
|
const val GAMEMODE = "gamemode"
|
||||||
|
|
||||||
|
/** String
|
||||||
|
* Comma-separated ItemIDs for the item the ore drops (`item@basegame:128` instead of `ores@basegame:1`)
|
||||||
|
*
|
||||||
|
* When the player gets the ore item, its itemID is appended to this actorvalue.
|
||||||
|
*/
|
||||||
|
const val ORE_DICT = "oredict"
|
||||||
}
|
}
|
||||||
@@ -15,20 +15,20 @@ import net.torvald.terrarum.blockproperties.Block
|
|||||||
import net.torvald.terrarum.blockproperties.BlockProp
|
import net.torvald.terrarum.blockproperties.BlockProp
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
import net.torvald.terrarum.gameparticles.createRandomBlockParticle
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.*
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.pow
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -564,17 +564,36 @@ open class ActorWithBody : Actor {
|
|||||||
// Codes that (SHOULD) displaces hitbox directly //
|
// Codes that (SHOULD) displaces hitbox directly //
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
|
|
||||||
|
val vecSum = (externalV + (controllerV ?: Vector2(0.0, 0.0)))
|
||||||
/**
|
/**
|
||||||
* solveCollision()?
|
* solveCollision()?
|
||||||
* If and only if:
|
* If and only if:
|
||||||
* This body is NON-STATIC and the other body is STATIC
|
* This body is NON-STATIC and the other body is STATIC
|
||||||
*/
|
*/
|
||||||
if (!isNoCollideWorld) {
|
if (!isNoCollideWorld) {
|
||||||
displaceHitbox()
|
val (collisionStatus, collisionDamage) = displaceHitbox()
|
||||||
|
|
||||||
|
|
||||||
|
if (collisionStatus != 0 && collisionDamage >= 1.0) {
|
||||||
|
val terrainDamage = collisionDamage / 1000.0
|
||||||
|
getWalledTiles(hitbox, collisionStatus).let {
|
||||||
|
if (it.isNotEmpty()) {
|
||||||
|
// printdbg(this, "Dmg to terrain: $terrainDamage, affected: ${it.size}")
|
||||||
|
// printdbg(this, it)
|
||||||
|
val dmgPerTile = terrainDamage / it.size
|
||||||
|
it.forEach { (x, y) ->
|
||||||
|
world?.inflictTerrainDamage(x, y, dmgPerTile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make dusts
|
||||||
|
if (collisionStatus != 0)
|
||||||
|
makeDust(collisionDamage, vecSum)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
stairPenaltyCounter = 999
|
stairPenaltyCounter = 999
|
||||||
val vecSum = externalV + (controllerV ?: Vector2(0.0, 0.0))
|
|
||||||
hitbox.translate(vecSum)
|
hitbox.translate(vecSum)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,6 +618,9 @@ open class ActorWithBody : Actor {
|
|||||||
clampHitbox()
|
clampHitbox()
|
||||||
|
|
||||||
if (stairPenaltyCounter < 999) stairPenaltyCounter += 1
|
if (stairPenaltyCounter < 999) stairPenaltyCounter += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -703,7 +725,11 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun displaceHitbox() {
|
/**
|
||||||
|
* @return Collision Status, Collision damage in Newtons
|
||||||
|
*/
|
||||||
|
private fun displaceHitbox(): Pair<Int, Double> {
|
||||||
|
var collisionDamage = 0.0
|
||||||
val printdbg1 = false && App.IS_DEVELOPMENT_BUILD
|
val printdbg1 = false && App.IS_DEVELOPMENT_BUILD
|
||||||
// // HOW IT SHOULD WORK // //
|
// // HOW IT SHOULD WORK // //
|
||||||
// ////////////////////////
|
// ////////////////////////
|
||||||
@@ -1072,10 +1098,21 @@ open class ActorWithBody : Actor {
|
|||||||
debug1("resulting hitbox: $newHitbox")
|
debug1("resulting hitbox: $newHitbox")
|
||||||
|
|
||||||
|
|
||||||
|
// var feetTileCount = 0
|
||||||
|
// var feetTileStregthSum = 0
|
||||||
|
// forEachFeetTile { it?.let {
|
||||||
|
// feetTileCount += 1
|
||||||
|
// feetTileStregthSum += it.strength
|
||||||
|
// }}
|
||||||
|
// val avrFeetTileStrength = feetTileStregthSum.toDouble() / feetTileCount
|
||||||
|
// val adjustedTileStr = avrFeetTileStrength / 1176
|
||||||
|
// val fallDamageDampenMult = (adjustedTileStr / (adjustedTileStr + 1)).sqr()
|
||||||
|
val fallDamageDampenMult = (32.0 / 1176.0).sqr()
|
||||||
// slam-into-whatever damage (such dirty; much hack; wow)
|
// slam-into-whatever damage (such dirty; much hack; wow)
|
||||||
// vvvv hack (supposed to be 1.0) vvv 50% hack
|
// vvvv hack (supposed to be 1.0) vvv 50% hack
|
||||||
val collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.PHYS_TIME_FRAME).sqr()) / fallDamageDampening.sqr() * GAME_TO_SI_ACC
|
collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.PHYS_TIME_FRAME).sqr()) * fallDamageDampenMult * GAME_TO_SI_ACC
|
||||||
// kg * m / s^2 (mass * acceleration), acceleration -> (vectorMagn / (0.01)^2).gameToSI()
|
// kg * m / s^2 (mass * acceleration), acceleration -> (vectorMagn / (0.01)^2).gameToSI()
|
||||||
|
// take material softness(?) into account
|
||||||
if (collisionDamage != 0.0) debug1("Collision damage: $collisionDamage N")
|
if (collisionDamage != 0.0) debug1("Collision damage: $collisionDamage N")
|
||||||
// FIXME instead of 0.5mv^2, we can model after "change of velocity (aka accel)", just as in real-life; big change of accel on given unit time is what kills
|
// FIXME instead of 0.5mv^2, we can model after "change of velocity (aka accel)", just as in real-life; big change of accel on given unit time is what kills
|
||||||
|
|
||||||
@@ -1091,13 +1128,14 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
return
|
return selfCollisionStatus to collisionDamage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if collision not detected, just don't care; it's not your job to apply moveDelta
|
// if collision not detected, just don't care; it's not your job to apply moveDelta
|
||||||
|
|
||||||
} // end of (world != null)
|
} // end of (world != null)
|
||||||
|
return 0 to collisionDamage
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1202,6 +1240,68 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getWalledTiles(hitbox: Hitbox, option: Int): List<Point2i> {
|
||||||
|
/*
|
||||||
|
The structure:
|
||||||
|
|
||||||
|
####### // TOP
|
||||||
|
=+-----+=
|
||||||
|
=| |=
|
||||||
|
=+-----+=
|
||||||
|
####### // BOTTOM
|
||||||
|
|
||||||
|
IMPORTANT AF NOTE: things are ASYMMETRIC!
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (option.popcnt() == 1) {
|
||||||
|
val (x1, x2, y1, y2) = hitbox.getWallDetection(option)
|
||||||
|
|
||||||
|
val txStart = x1.floorToInt().div(TILE_SIZED).floorToInt() // round down toward negative infinity
|
||||||
|
val txEnd = x2.floorToInt().div(TILE_SIZED).floorToInt() // round down toward negative infinity
|
||||||
|
val tyStart = y1.floorToInt().div(TILE_SIZED).floorToInt() // round down toward negative infinity
|
||||||
|
val tyEnd = y2.floorToInt().div(TILE_SIZED).floorToInt() // round down toward negative infinity
|
||||||
|
|
||||||
|
return getWalledTiles0(txStart, tyStart, txEnd, tyEnd, option == COLLIDING_BOTTOM)
|
||||||
|
}
|
||||||
|
else if (option == 0) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return intArrayOf(1, 2, 4, 8).flatMap {
|
||||||
|
getWalledTiles(hitbox, option and it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getWalledTiles0(pxStart: Int, pyStart: Int, pxEnd: Int, pyEnd: Int, feet: Boolean): List<Point2i> {
|
||||||
|
val ret = ArrayList<Point2i>()
|
||||||
|
if (world == null) return emptyList()
|
||||||
|
val ys = pyStart..pyEnd
|
||||||
|
val xs = pxStart..pxEnd
|
||||||
|
val feetY = pyEnd // round down toward negative infinity // TODO reverse gravity adaptation?
|
||||||
|
|
||||||
|
for (ty in ys) {
|
||||||
|
val isFeetTileHeight = (ty == feetY)
|
||||||
|
|
||||||
|
for (tx in xs) {
|
||||||
|
val tile = world!!.getTileFromTerrain(tx, ty)
|
||||||
|
|
||||||
|
if (feet && isFeetTileHeight) {
|
||||||
|
if (shouldICollideWithThisFeet(tile)) {
|
||||||
|
ret.add(Point2i(tx, ty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (shouldICollideWithThis(tile)) {
|
||||||
|
ret.add(Point2i(tx, ty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// printdbg(this, "ys=$ys, xs=$xs, ret=$ret")
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return First int: 0 - no collision, 1 - staircasing, 2 - "bonk" to the wall; Second int: stair height
|
* @return First int: 0 - no collision, 1 - staircasing, 2 - "bonk" to the wall; Second int: stair height
|
||||||
*/
|
*/
|
||||||
@@ -1289,10 +1389,9 @@ open class ActorWithBody : Actor {
|
|||||||
(pxStart + sub)..(pxEnd - sub)
|
(pxStart + sub)..(pxEnd - sub)
|
||||||
}
|
}
|
||||||
else*/
|
else*/
|
||||||
pxStart..pxEnd
|
(pxStart / TILE_SIZED).floorToInt()..(pxEnd / TILE_SIZED).floorToInt()
|
||||||
|
|
||||||
for (x in xs) {
|
for (tx in xs) {
|
||||||
val tx = (x / TILE_SIZED).floorToInt() // round down toward negative infinity
|
|
||||||
val tile = world!!.getTileFromTerrain(tx, ty)
|
val tile = world!!.getTileFromTerrain(tx, ty)
|
||||||
|
|
||||||
if (feet && isFeetTileHeight) {
|
if (feet && isFeetTileHeight) {
|
||||||
@@ -1917,6 +2016,82 @@ open class ActorWithBody : Actor {
|
|||||||
return tileProps.forEach(consumer)
|
return tileProps.forEach(consumer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getFeetTiles(): List<Pair<Point2i, ItemID>> {
|
||||||
|
val y = intTilewiseHitbox.height.toInt() + 1
|
||||||
|
return (0..intTilewiseHitbox.width.toInt()).map { x ->
|
||||||
|
val px = x + intTilewiseHitbox.startX.toInt()
|
||||||
|
val py = y + intTilewiseHitbox.startY.toInt()
|
||||||
|
Point2i(px, py) to world!!.getTileFromTerrain(px, py)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun makeDust(collisionDamage: Double, vecSum: Vector2) {
|
||||||
|
val particleCount = (collisionDamage / 24.0).pow(0.75)
|
||||||
|
val trueParticleCount = particleCount.toInt() + (Math.random() < (particleCount % 1.0)).toInt()
|
||||||
|
|
||||||
|
if (collisionDamage > 1.0 / 1024.0) {
|
||||||
|
// printdbg(this, "Collision damage: $collisionDamage N, count: $particleCount, velocity: $vecSum, mass: ${this.mass}")
|
||||||
|
|
||||||
|
val feetTiles = getFeetTiles()
|
||||||
|
val feetTileIndices = feetTiles.indices.toList().toIntArray()
|
||||||
|
|
||||||
|
for (i in 0 until trueParticleCount) {
|
||||||
|
if (i % feetTiles.size == 0) feetTileIndices.shuffle()
|
||||||
|
|
||||||
|
feetTiles[feetTileIndices[i % feetTiles.size]].second.let { tile ->
|
||||||
|
val px = hitbox.startX + Math.random() * hitbox.width
|
||||||
|
val py = hitbox.endY
|
||||||
|
makeDust0(tile, px, py, particleCount, collisionDamage, vecSum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val pixelOffs = intArrayOf(2, 7, 12) // hard-coded assuming TILE_SIZE=16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wx World-X position
|
||||||
|
*/
|
||||||
|
private fun makeDust0(tile: ItemID, wx: Double, wy: Double, count: Double, fallDamage: Double, vecSum: Vector2) {
|
||||||
|
val pw = 3
|
||||||
|
val ph = 3
|
||||||
|
|
||||||
|
val renderTag = App.tileMaker.getRenderTag(tile)
|
||||||
|
val baseTilenum = renderTag.tileNumber
|
||||||
|
val representativeTilenum = when (renderTag.maskType) {
|
||||||
|
CreateTileAtlas.RenderTag.MASK_47 -> 17
|
||||||
|
CreateTileAtlas.RenderTag.MASK_PLATFORM -> 7
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
val tileNum = baseTilenum + representativeTilenum // the particle won't match the visible tile anyway because of the seasons stuff
|
||||||
|
|
||||||
|
val vi = if (vecSum.y > PHYS_EPSILON_VELO) 0 else if (vecSum.y < -PHYS_EPSILON_VELO) 2 else (Math.random() * 3).toInt()
|
||||||
|
val u = (wx.toInt() % TILE_SIZE).coerceIn(0..TILE_SIZE - pw)
|
||||||
|
val v = pixelOffs[vi]
|
||||||
|
val pos = Vector2(
|
||||||
|
wx,
|
||||||
|
wy,
|
||||||
|
)
|
||||||
|
val veloXvar = (Math.random() + Math.random()) * (if (Math.random() < 0.5) -1 else 1) * 0.5 // avr at 0.5
|
||||||
|
val veloYvar = brownianRand()
|
||||||
|
val veloMult = Vector2(
|
||||||
|
vecSum.x * 0.8 + veloXvar,
|
||||||
|
(count.pow(0.5) + veloYvar) * vecSum.y.sign
|
||||||
|
)
|
||||||
|
createRandomBlockParticle(tileNum, pos, veloMult, u, v, pw, ph).let {
|
||||||
|
it.despawnUponCollision = true
|
||||||
|
it.drawColour.set(Color.WHITE)
|
||||||
|
(Terrarum.ingame as TerrarumIngame).addParticle(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return random number between 0-1, of which 0 is the most likely and 1 is the least
|
||||||
|
*/
|
||||||
|
private fun brownianRand(): Double {
|
||||||
|
return Math.abs(Math.random() + Math.random() - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -198,6 +198,8 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
|||||||
).let { drop ->
|
).let { drop ->
|
||||||
INGAME.queueActorAddition(drop)
|
INGAME.queueActorAddition(drop)
|
||||||
}
|
}
|
||||||
|
// apply item effect
|
||||||
|
ItemCodex[item]!!.effectOnThrow(player)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ object InputStrober {
|
|||||||
val keymap = IME.getLowLayerByName(App.getConfigString("basekeyboardlayout"))
|
val keymap = IME.getLowLayerByName(App.getConfigString("basekeyboardlayout"))
|
||||||
|
|
||||||
if (stroboStatus % 2 == 0 && keybuf[0] != 0) {
|
if (stroboStatus % 2 == 0 && keybuf[0] != 0) {
|
||||||
// println("Key strobed: ${keybuf.joinToString()}; ${oldKeys.joinToString()}; changed = $keyChanged")
|
// println("Key strobed: ${keybuf.joinToString()}; old: ${oldKeys.joinToString()}; changed = $keyChanged")
|
||||||
|
|
||||||
stroboStatus += 1
|
stroboStatus += 1
|
||||||
stroboTime = System.nanoTime()
|
stroboTime = System.nanoTime()
|
||||||
@@ -82,11 +82,11 @@ object InputStrober {
|
|||||||
val headKeyCode = if (keyDiff.size < 1) keybuf[0] else keyDiff[0]
|
val headKeyCode = if (keyDiff.size < 1) keybuf[0] else keyDiff[0]
|
||||||
|
|
||||||
if (!keyChanged) {
|
if (!keyChanged) {
|
||||||
// println("KEY_DOWN '$keysym' ($headKeyCode) $repeatCount; ${keys.joinToString()}")
|
// println("KEY_DOWN '$keysym' ($headKeyCode) $repeatCount")
|
||||||
App.inputStrobed(TerrarumKeyboardEvent(KEY_DOWN, keysym, headKeyCode, repeatCount, keybuf))
|
App.inputStrobed(TerrarumKeyboardEvent(KEY_DOWN, keysym, headKeyCode, repeatCount, keybuf))
|
||||||
}
|
}
|
||||||
else if (newKeysym != null) {
|
else if (newKeysym != null) {
|
||||||
// println("KEY_DOWC '$newKeysym' ($headKeyCode) $repeatCount; ${keys.joinToString()}")
|
// println("KEY_DOWC '$newKeysym' ($headKeyCode) $repeatCount")
|
||||||
App.inputStrobed(TerrarumKeyboardEvent(KEY_DOWN, newKeysym, headKeyCode, repeatCount, keybuf))
|
App.inputStrobed(TerrarumKeyboardEvent(KEY_DOWN, newKeysym, headKeyCode, repeatCount, keybuf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
|||||||
/**
|
/**
|
||||||
* Effects applied immediately only once when picked up
|
* Effects applied immediately only once when picked up
|
||||||
*/
|
*/
|
||||||
open fun effectOnPickup(actor: ActorWithBody, delta: Float) { }
|
open fun effectOnPickup(actor: ActorWithBody) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply effects (continuously or not) while primary button is down.
|
* Apply effects (continuously or not) while primary button is down.
|
||||||
@@ -249,7 +249,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
|||||||
/**
|
/**
|
||||||
* Effects applied immediately only once when thrown (discarded) from pocket
|
* Effects applied immediately only once when thrown (discarded) from pocket
|
||||||
*/
|
*/
|
||||||
open fun effectOnThrow(actor: ActorWithBody, delta: Float) { }
|
open fun effectOnThrow(actor: ActorWithBody) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Effects applied (continuously or not) while being equipped (drawn/pulled out)
|
* Effects applied (continuously or not) while being equipped (drawn/pulled out)
|
||||||
@@ -259,7 +259,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
|||||||
/**
|
/**
|
||||||
* Effects applied only once when unequipped
|
* Effects applied only once when unequipped
|
||||||
*/
|
*/
|
||||||
open fun effectOnUnequip(actor: ActorWithBody, delta: Float) { }
|
open fun effectOnUnequip(actor: ActorWithBody) { }
|
||||||
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@@ -417,8 +417,10 @@ fun mouseInInteractableRangeTools(actor: ActorWithBody, item: GameItem?, reachMu
|
|||||||
|
|
||||||
fun ItemID.isItem() = this.startsWith("item@")
|
fun ItemID.isItem() = this.startsWith("item@")
|
||||||
fun ItemID.isWire() = this.startsWith("wire@")
|
fun ItemID.isWire() = this.startsWith("wire@")
|
||||||
fun ItemID.isDynamic() = this.startsWith("$PREFIX_DYNAMICITEM:")
|
fun ItemID.isDynamic() = this.startsWith("$PREFIX_DYNAMICITEM:") // aka module name 'dyn'
|
||||||
fun ItemID.isActor() = this.startsWith("$PREFIX_ACTORITEM@")
|
fun ItemID.isActor() = this.startsWith("$PREFIX_ACTORITEM@")
|
||||||
fun ItemID.isVirtual() = this.startsWith("$PREFIX_VIRTUALTILE@")
|
fun ItemID.isVirtual() = this.startsWith("$PREFIX_VIRTUALTILE@")
|
||||||
fun ItemID.isBlock() = !this.contains('@') && !this.isDynamic()
|
fun ItemID.isBlock() = !this.contains('@') && !this.isDynamic()
|
||||||
fun ItemID.isWall() = this.startsWith("wall@")
|
fun ItemID.isWall() = this.startsWith("wall@")
|
||||||
|
fun ItemID.isFluid() = this.startsWith("fluid@")
|
||||||
|
fun ItemID.isOre() = this.startsWith("ores@")
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.dyn4j.geometry.Vector2
|
|||||||
*
|
*
|
||||||
* Created by minjaesong on 2017-01-20.
|
* Created by minjaesong on 2017-01-20.
|
||||||
*/
|
*/
|
||||||
open class ParticleBase(renderOrder: Actor.RenderOrder, val despawnUponCollision: Boolean, val noCollision: Boolean = true, maxLifeTime: Second? = null) : Runnable {
|
open class ParticleBase(renderOrder: Actor.RenderOrder, var despawnUponCollision: Boolean, var noCollision: Boolean = true, maxLifeTime: Second? = null) : Runnable {
|
||||||
|
|
||||||
/** Will NOT actually delete from the CircularArray */
|
/** Will NOT actually delete from the CircularArray */
|
||||||
@Volatile var flagDespawn = false
|
@Volatile var flagDespawn = false
|
||||||
@@ -22,7 +22,7 @@ open class ParticleBase(renderOrder: Actor.RenderOrder, val despawnUponCollision
|
|||||||
override fun run() = update(App.UPDATE_RATE)
|
override fun run() = update(App.UPDATE_RATE)
|
||||||
|
|
||||||
var isNoSubjectToGrav = false
|
var isNoSubjectToGrav = false
|
||||||
var dragCoefficient = 3.0
|
var dragCoefficient = 40.0
|
||||||
|
|
||||||
val lifetimeMax = maxLifeTime ?: 5f
|
val lifetimeMax = maxLifeTime ?: 5f
|
||||||
var lifetimeCounter = 0f
|
var lifetimeCounter = 0f
|
||||||
@@ -55,8 +55,8 @@ open class ParticleBase(renderOrder: Actor.RenderOrder, val despawnUponCollision
|
|||||||
)].isSolid) {
|
)].isSolid) {
|
||||||
|
|
||||||
|
|
||||||
if (despawnUponCollision) flagDespawn = true
|
if (despawnUponCollision && lifetimeCounter >= 0.1f) flagDespawn = true
|
||||||
if (!noCollision) velocity.y = 0.0
|
if (!noCollision && lifetimeCounter >= 0.1f) velocity.y = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lifetimeCounter >= lifetimeMax) {
|
if (lifetimeCounter >= lifetimeMax) {
|
||||||
|
|||||||
@@ -2,12 +2,20 @@ package net.torvald.terrarum.gameparticles
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameactors.drawBodyInGoodPosition
|
import net.torvald.terrarum.gameactors.drawBodyInGoodPosition
|
||||||
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||||
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.RenderTag
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import org.dyn4j.geometry.Vector2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The texture must be manually discarded.
|
||||||
|
*
|
||||||
* @param tex image
|
* @param tex image
|
||||||
* @param x x-coord of the particle's initial spawn position, bottom-centre
|
* @param x x-coord of the particle's initial spawn position, bottom-centre
|
||||||
* @param y y-coord of the particle's initial spawn position, bottom-centre
|
* @param y y-coord of the particle's initial spawn position, bottom-centre
|
||||||
@@ -29,6 +37,31 @@ open class ParticleVanishingTexture(val tex: TextureRegion, x: Double, y: Double
|
|||||||
|
|
||||||
drawColour.a = (lifetimeMax - lifetimeCounter) / lifetimeMax
|
drawColour.a = (lifetimeMax - lifetimeCounter) / lifetimeMax
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// pickaxe sparks must use different create- function
|
||||||
|
fun createRandomBlockParticle(tileNum: Int, position: Vector2, velocityMult: Vector2, tx: Int, ty: Int, tw: Int, th: Int): ParticleBase {
|
||||||
|
val velocity = Vector2(
|
||||||
|
(Math.random() + Math.random()) * velocityMult.x,
|
||||||
|
-velocityMult.y
|
||||||
|
) // triangular distribution with mean of 1.0 * velocityMult
|
||||||
|
|
||||||
|
val atlasX = tileNum % BlocksDrawer.weatherTerrains[1].horizontalCount
|
||||||
|
val atlasY = tileNum / BlocksDrawer.weatherTerrains[1].horizontalCount
|
||||||
|
// take base texture
|
||||||
|
val texBody = BlocksDrawer.weatherTerrains[1].get(atlasX, atlasY)
|
||||||
|
val texGlow = BlocksDrawer.tilesGlow.get(atlasX, atlasY)
|
||||||
|
|
||||||
|
// take random square part
|
||||||
|
val texRegionBody = TextureRegion(texBody.texture, texBody.regionX + tx, texBody.regionY + ty, tw, th)
|
||||||
|
val texRegionGlow = TextureRegion(texGlow.texture, texGlow.regionX + tx, texGlow.regionY + ty, tw, th)
|
||||||
|
|
||||||
|
return ParticleVanishingTexture(texRegionBody, position.x, position.y).also {
|
||||||
|
it.glow = texRegionGlow
|
||||||
|
it.velocity.set(velocity)
|
||||||
|
it.isNoSubjectToGrav = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,110 +1,15 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import net.torvald.terrarum.App.printdbg
|
|
||||||
import net.torvald.terrarum.serialise.toUint
|
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
|
||||||
import net.torvald.unsafe.UnsafePtr
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory layout:
|
* Created by minjaesong on 2023-10-10.
|
||||||
* ```
|
|
||||||
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 ||
|
|
||||||
* ```
|
|
||||||
* where a_n is a tile number
|
|
||||||
*
|
|
||||||
* Original version Created by minjaesong on 2016-01-17.
|
|
||||||
* Unsafe version Created by minjaesong on 2019-06-08.
|
|
||||||
*
|
|
||||||
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
|
||||||
*/
|
*/
|
||||||
open class BlockLayer(val width: Int, val height: Int) : Disposable {
|
interface BlockLayer : Disposable {
|
||||||
// for some reason, all the efforts of saving the memory space were futile.
|
|
||||||
|
|
||||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
val bytesPerBlock: Long
|
||||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * BYTES_PER_BLOCK)
|
fun unsafeToBytes(x: Int, y: Int): ByteArray
|
||||||
|
fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray)
|
||||||
|
fun unsafeGetTile(x: Int, y: Int): Int
|
||||||
|
|
||||||
val ptrDestroyed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
init {
|
|
||||||
ptr.fillWith(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param data Byte array representation of the layer
|
|
||||||
*/
|
|
||||||
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
|
||||||
TODO()
|
|
||||||
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over stored bytes.
|
|
||||||
*
|
|
||||||
* @return an Iterator.
|
|
||||||
*/
|
|
||||||
fun bytesIterator(): Iterator<Byte> {
|
|
||||||
return object : Iterator<Byte> {
|
|
||||||
private var iteratorCount = 0L
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return iteratorCount < width * height * BYTES_PER_BLOCK
|
|
||||||
}
|
|
||||||
override fun next(): Byte {
|
|
||||||
iteratorCount += 1
|
|
||||||
return ptr[iteratorCount - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun unsafeGetTile(x: Int, y: Int): Int {
|
|
||||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
|
|
||||||
return lsb.toUint() + msb.toUint().shl(8)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
|
||||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
|
|
||||||
// try {
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
// }
|
|
||||||
// catch (e: IndexOutOfBoundsException) {
|
|
||||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
|
||||||
// throw e
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
|
||||||
*/
|
|
||||||
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
|
||||||
val offset = BYTES_PER_BLOCK * blockOffset
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
unsafe.putByte(layerPtr + offset, lsb)
|
|
||||||
unsafe.putByte(layerPtr + offset + 1, msb)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
ptr.destroy()
|
|
||||||
printdbg(this, "BlockLayer with ptr ($ptr) successfully freed")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Transient val BYTES_PER_BLOCK = 2L
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
123
src/net/torvald/terrarum/gameworld/BlockLayerI16.kt
Normal file
123
src/net/torvald/terrarum/gameworld/BlockLayerI16.kt
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.terrarum.serialise.toUint
|
||||||
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
|
import net.torvald.unsafe.UnsafePtr
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory layout:
|
||||||
|
* ```
|
||||||
|
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 ||
|
||||||
|
* ```
|
||||||
|
* where a_n is a tile number
|
||||||
|
*
|
||||||
|
* Original version Created by minjaesong on 2016-01-17.
|
||||||
|
* Unsafe version Created by minjaesong on 2019-06-08.
|
||||||
|
*
|
||||||
|
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
||||||
|
*/
|
||||||
|
open class BlockLayerI16(val width: Int, val height: Int) : BlockLayer {
|
||||||
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
|
// for some reason, all the efforts of saving the memory space were futile.
|
||||||
|
|
||||||
|
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||||
|
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * BYTES_PER_BLOCK)
|
||||||
|
|
||||||
|
val ptrDestroyed: Boolean
|
||||||
|
get() = ptr.destroyed
|
||||||
|
|
||||||
|
init {
|
||||||
|
ptr.fillWith(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data Byte array representation of the layer
|
||||||
|
*/
|
||||||
|
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||||
|
TODO()
|
||||||
|
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over stored bytes.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun bytesIterator(): Iterator<Byte> {
|
||||||
|
return object : Iterator<Byte> {
|
||||||
|
private var iteratorCount = 0L
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height * BYTES_PER_BLOCK
|
||||||
|
}
|
||||||
|
override fun next(): Byte {
|
||||||
|
iteratorCount += 1
|
||||||
|
return ptr[iteratorCount - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
|
||||||
|
return lsb.toUint() + msb.toUint().shl(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
|
||||||
|
// try {
|
||||||
|
ptr[offset] = lsb
|
||||||
|
ptr[offset + 1] = msb
|
||||||
|
// }
|
||||||
|
// catch (e: IndexOutOfBoundsException) {
|
||||||
|
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
||||||
|
// throw e
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
ptr[offset] = bytes[1]
|
||||||
|
ptr[offset + 1] = bytes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
||||||
|
*/
|
||||||
|
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
||||||
|
val offset = BYTES_PER_BLOCK * blockOffset
|
||||||
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
unsafe.putByte(layerPtr + offset, lsb)
|
||||||
|
unsafe.putByte(layerPtr + offset + 1, msb)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
ptr.destroy()
|
||||||
|
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = ptr.toString("BlockLayerI16")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Transient val BYTES_PER_BLOCK = 2L
|
||||||
|
}
|
||||||
|
}
|
||||||
137
src/net/torvald/terrarum/gameworld/BlockLayerI16F16.kt
Normal file
137
src/net/torvald/terrarum/gameworld/BlockLayerI16F16.kt
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.gameworld.WorldSimulator.FLUID_MIN_MASS
|
||||||
|
import net.torvald.terrarum.serialise.toUint
|
||||||
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
|
import net.torvald.unsafe.UnsafePtr
|
||||||
|
import net.torvald.util.Float16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * Memory layout:
|
||||||
|
* * ```
|
||||||
|
* * a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | f7 f6 f5 f4 f3 f2 f1 f0 | fF fE fD fC fB fA f9 f8 ||
|
||||||
|
* * ```
|
||||||
|
* * where a_n is a fluid number, f_n is a fluid fill
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2023-10-10.
|
||||||
|
*/
|
||||||
|
class BlockLayerI16F16(val width: Int, val height: Int) : BlockLayer {
|
||||||
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
|
// for some reason, all the efforts of saving the memory space were futile.
|
||||||
|
|
||||||
|
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||||
|
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * BYTES_PER_BLOCK)
|
||||||
|
|
||||||
|
val ptrDestroyed: Boolean
|
||||||
|
get() = ptr.destroyed
|
||||||
|
|
||||||
|
init {
|
||||||
|
ptr.fillWith(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data Byte array representation of the layer
|
||||||
|
*/
|
||||||
|
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||||
|
TODO()
|
||||||
|
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over stored bytes.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun bytesIterator(): Iterator<Byte> {
|
||||||
|
return object : Iterator<Byte> {
|
||||||
|
private var iteratorCount = 0L
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height * BYTES_PER_BLOCK
|
||||||
|
}
|
||||||
|
override fun next(): Byte {
|
||||||
|
iteratorCount += 1
|
||||||
|
return ptr[iteratorCount - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
|
||||||
|
val fill = Float16.toFloat(hbits)
|
||||||
|
|
||||||
|
return lsb.toUint() + msb.toUint().shl(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
|
||||||
|
val fill = Float16.toFloat(hbits)
|
||||||
|
|
||||||
|
return lsb.toUint() + msb.toUint().shl(8) to fill
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
|
||||||
|
|
||||||
|
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
|
||||||
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
val hlsb = hbits.and(0xff).toByte()
|
||||||
|
val hmsb = hbits.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
ptr[offset] = lsb
|
||||||
|
ptr[offset + 1] = msb
|
||||||
|
ptr[offset + 2] = hlsb
|
||||||
|
ptr[offset + 3] = hmsb
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
ptr[offset] = bytes[1]
|
||||||
|
ptr[offset + 1] = bytes[0]
|
||||||
|
ptr[offset + 2] = bytes[3]
|
||||||
|
ptr[offset + 3] = bytes[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
||||||
|
*/
|
||||||
|
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
||||||
|
val offset = BYTES_PER_BLOCK * blockOffset
|
||||||
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
unsafe.putByte(layerPtr + offset, lsb)
|
||||||
|
unsafe.putByte(layerPtr + offset + 1, msb)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
ptr.destroy()
|
||||||
|
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = ptr.toString("BlockLayerI16F16")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Transient val BYTES_PER_BLOCK = 4L
|
||||||
|
}
|
||||||
|
}
|
||||||
140
src/net/torvald/terrarum/gameworld/BlockLayerI16I8.kt
Normal file
140
src/net/torvald/terrarum/gameworld/BlockLayerI16I8.kt
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.serialise.toUint
|
||||||
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
|
import net.torvald.unsafe.UnsafePtr
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory layout:
|
||||||
|
* ```
|
||||||
|
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
|
||||||
|
* ```
|
||||||
|
* where a_n is a tile number, p_n is a placement index
|
||||||
|
* Created by minjaesong on 2023-10-10.
|
||||||
|
*/
|
||||||
|
class BlockLayerI16I8 (val width: Int, val height: Int) : BlockLayer {
|
||||||
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
|
// for some reason, all the efforts of saving the memory space were futile.
|
||||||
|
|
||||||
|
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||||
|
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * BYTES_PER_BLOCK)
|
||||||
|
|
||||||
|
val ptrDestroyed: Boolean
|
||||||
|
get() = ptr.destroyed
|
||||||
|
|
||||||
|
init {
|
||||||
|
ptr.fillWith(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data Byte array representation of the layer
|
||||||
|
*/
|
||||||
|
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||||
|
TODO()
|
||||||
|
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over stored bytes.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun bytesIterator(): Iterator<Byte> {
|
||||||
|
return object : Iterator<Byte> {
|
||||||
|
private var iteratorCount = 0L
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height * BYTES_PER_BLOCK
|
||||||
|
}
|
||||||
|
override fun next(): Byte {
|
||||||
|
iteratorCount += 1
|
||||||
|
return ptr[iteratorCount - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
val placement = ptr[offset + 2]
|
||||||
|
|
||||||
|
return lsb.toUint() + msb.toUint().shl(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
val placement = ptr[offset + 2]
|
||||||
|
|
||||||
|
return lsb.toUint() + msb.toUint().shl(8) to placement.toUint()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
|
||||||
|
// try {
|
||||||
|
ptr[offset] = lsb
|
||||||
|
ptr[offset + 1] = msb
|
||||||
|
ptr[offset + 2] = placement.toByte()
|
||||||
|
// }
|
||||||
|
// catch (e: IndexOutOfBoundsException) {
|
||||||
|
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
||||||
|
// throw e
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
ptr[offset] = bytes[1]
|
||||||
|
ptr[offset + 1] = bytes[0]
|
||||||
|
ptr[offset + 2] = bytes[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeSetTileKeepPlacement(x: Int, y: Int, tile: Int) {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
ptr[offset] = lsb
|
||||||
|
ptr[offset + 1] = msb
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
||||||
|
*/
|
||||||
|
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
||||||
|
val offset = BYTES_PER_BLOCK * blockOffset
|
||||||
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
unsafe.putByte(layerPtr + offset, lsb)
|
||||||
|
unsafe.putByte(layerPtr + offset + 1, msb)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
ptr.destroy()
|
||||||
|
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = ptr.toString("BlockLayerI16I8")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Transient val BYTES_PER_BLOCK = 3L
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,21 +7,20 @@ import net.torvald.terrarum.*
|
|||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockproperties.Fluid
|
import net.torvald.terrarum.blockproperties.Fluid
|
||||||
import net.torvald.terrarum.concurrent.ThreadExecutor
|
|
||||||
import net.torvald.terrarum.gameactors.ActorID
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
import net.torvald.terrarum.gameitems.isFluid
|
||||||
import net.torvald.terrarum.itemproperties.ItemRemapTable
|
import net.torvald.terrarum.itemproperties.ItemRemapTable
|
||||||
import net.torvald.terrarum.itemproperties.ItemTable
|
import net.torvald.terrarum.itemproperties.ItemTable
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.utils.*
|
import net.torvald.terrarum.utils.*
|
||||||
import net.torvald.terrarum.weather.WeatherMixer
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
import net.torvald.terrarum.weather.WeatherSchedule
|
|
||||||
import net.torvald.terrarum.weather.Weatherbox
|
import net.torvald.terrarum.weather.Weatherbox
|
||||||
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
import net.torvald.util.SortedArrayList
|
import net.torvald.util.SortedArrayList
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.absoluteValue
|
|
||||||
|
|
||||||
typealias BlockAddress = Long
|
typealias BlockAddress = Long
|
||||||
|
|
||||||
@@ -39,8 +38,8 @@ class PhysicalStatus() {
|
|||||||
* Special version of GameWorld where everything, including layer data, are saved in a single JSON file (i.e. not chunked)
|
* Special version of GameWorld where everything, including layer data, are saved in a single JSON file (i.e. not chunked)
|
||||||
*/
|
*/
|
||||||
class SimpleGameWorld(width: Int, height: Int) : GameWorld(width, height) {
|
class SimpleGameWorld(width: Int, height: Int) : GameWorld(width, height) {
|
||||||
override lateinit var layerWall: BlockLayer
|
override lateinit var layerWall: BlockLayerI16
|
||||||
override lateinit var layerTerrain: BlockLayer
|
override lateinit var layerTerrain: BlockLayerI16
|
||||||
constructor() : this(0, 0)
|
constructor() : this(0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +81,14 @@ open class GameWorld(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//layers
|
//layers
|
||||||
@Transient lateinit open var layerWall: BlockLayer
|
@Transient lateinit open var layerWall: BlockLayerI16
|
||||||
@Transient lateinit open var layerTerrain: BlockLayer
|
@Transient lateinit open var layerTerrain: BlockLayerI16
|
||||||
|
@Transient lateinit open var layerOres: BlockLayerI16I8 // damage to the block follows `terrainDamages`
|
||||||
|
@Transient lateinit open var layerFluids: BlockLayerI16F16
|
||||||
|
val wallDamages = HashArray<Float>()
|
||||||
|
val terrainDamages = HashArray<Float>()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//val layerThermal: MapLayerHalfFloat // in Kelvins
|
//val layerThermal: MapLayerHalfFloat // in Kelvins
|
||||||
//val layerFluidPressure: MapLayerHalfFloat // (milibar - 1000)
|
//val layerFluidPressure: MapLayerHalfFloat // (milibar - 1000)
|
||||||
@@ -101,10 +106,7 @@ open class GameWorld(
|
|||||||
}
|
}
|
||||||
var portalPoint: Point2i? = null
|
var portalPoint: Point2i? = null
|
||||||
|
|
||||||
val wallDamages = HashArray<Float>()
|
|
||||||
val terrainDamages = HashArray<Float>()
|
|
||||||
val fluidTypes = HashedFluidType()
|
|
||||||
val fluidFills = HashArray<Float>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Single block can have multiple conduits, different types of conduits are stored separately.
|
* Single block can have multiple conduits, different types of conduits are stored separately.
|
||||||
@@ -140,10 +142,27 @@ open class GameWorld(
|
|||||||
30L * WorldTime.MINUTE_SEC
|
30L * WorldTime.MINUTE_SEC
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Transient private val forcedTileNumberToNames = hashSetOf(
|
||||||
val tileNumberToNameMap = HashArray<ItemID>()
|
Block.AIR, Block.UPDATE
|
||||||
|
)
|
||||||
|
@Transient private val forcedFluidNumberToTiles = hashSetOf(
|
||||||
|
Fluid.NULL
|
||||||
|
)
|
||||||
|
val tileNumberToNameMap = HashArray<ItemID>().also {
|
||||||
|
it[0] = Block.AIR
|
||||||
|
it[2] = Block.UPDATE
|
||||||
|
}
|
||||||
|
val fluidNumberToNameMap = HashArray<ItemID>().also {
|
||||||
|
it[0] = Fluid.NULL
|
||||||
|
}
|
||||||
// does not go to the savefile
|
// does not go to the savefile
|
||||||
@Transient val tileNameToNumberMap = HashMap<ItemID, Int>()
|
@Transient val tileNameToNumberMap = HashMap<ItemID, Int>().also {
|
||||||
|
it[Block.AIR] = 0
|
||||||
|
it[Block.UPDATE] = 2
|
||||||
|
}
|
||||||
|
@Transient val fluidNameToNumberMap = HashMap<ItemID, Int>().also {
|
||||||
|
it[Fluid.NULL] = 0
|
||||||
|
}
|
||||||
|
|
||||||
val extraFields = HashMap<String, Any?>()
|
val extraFields = HashMap<String, Any?>()
|
||||||
|
|
||||||
@@ -197,8 +216,10 @@ open class GameWorld(
|
|||||||
this.spawnX = width / 2
|
this.spawnX = width / 2
|
||||||
this.spawnY = 150
|
this.spawnY = 150
|
||||||
|
|
||||||
layerTerrain = BlockLayer(width, height)
|
layerTerrain = BlockLayerI16(width, height)
|
||||||
layerWall = BlockLayer(width, height)
|
layerWall = BlockLayerI16(width, height)
|
||||||
|
layerOres = BlockLayerI16I8(width, height)
|
||||||
|
layerFluids = BlockLayerI16F16(width, height)
|
||||||
|
|
||||||
// temperature layer: 2x2 is one cell
|
// temperature layer: 2x2 is one cell
|
||||||
//layerThermal = MapLayerHalfFloat(width, height, averageTemperature)
|
//layerThermal = MapLayerHalfFloat(width, height, averageTemperature)
|
||||||
@@ -214,26 +235,15 @@ open class GameWorld(
|
|||||||
if (App.tileMaker != null) {
|
if (App.tileMaker != null) {
|
||||||
App.tileMaker.tags.forEach {
|
App.tileMaker.tags.forEach {
|
||||||
if (!forcedTileNumberToNames.contains(it.key)) {
|
if (!forcedTileNumberToNames.contains(it.key)) {
|
||||||
printdbg(this, "tileNumber ${it.value.tileNumber} <-> tileName ${it.key}")
|
printdbg(this, "newworld tileNumber ${it.value.tileNumber} <-> tileName ${it.key}")
|
||||||
|
|
||||||
tileNumberToNameMap[it.value.tileNumber.toLong()] = it.key
|
tileNumberToNameMap[it.value.tileNumber.toLong()] = it.key
|
||||||
tileNameToNumberMap[it.key] = it.value.tileNumber
|
tileNameToNumberMap[it.key] = it.value.tileNumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AN EXCEPTIONAL TERM: tilenum 0 is always redirected to Air tile, even if the tilenum for actual Air tile is not zero
|
|
||||||
tileNumberToNameMap[0] = Block.AIR
|
|
||||||
tileNameToNumberMap[Block.AIR] = 0
|
|
||||||
|
|
||||||
tileNumberToNameMap[2] = Block.UPDATE
|
|
||||||
tileNameToNumberMap[Block.UPDATE] = 2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient private val forcedTileNumberToNames = hashSetOf(
|
|
||||||
Block.AIR, Block.UPDATE
|
|
||||||
)
|
|
||||||
|
|
||||||
fun coordInWorld(x: Int, y: Int) = y in 0 until height // ROUNDWORLD implementation
|
fun coordInWorld(x: Int, y: Int) = y in 0 until height // ROUNDWORLD implementation
|
||||||
fun coordInWorldStrict(x: Int, y: Int) = x in 0 until width && y in 0 until height // ROUNDWORLD implementation
|
fun coordInWorldStrict(x: Int, y: Int) = x in 0 until width && y in 0 until height // ROUNDWORLD implementation
|
||||||
|
|
||||||
@@ -243,6 +253,8 @@ open class GameWorld(
|
|||||||
tileNumberToNameMap.clear()
|
tileNumberToNameMap.clear()
|
||||||
tileNameToNumberMap.clear()
|
tileNameToNumberMap.clear()
|
||||||
App.tileMaker.tags.forEach {
|
App.tileMaker.tags.forEach {
|
||||||
|
printdbg(this, "afterload tileNumber ${it.value.tileNumber} <-> tileName ${it.key}")
|
||||||
|
|
||||||
tileNumberToNameMap[it.value.tileNumber.toLong()] = it.key
|
tileNumberToNameMap[it.value.tileNumber.toLong()] = it.key
|
||||||
tileNameToNumberMap[it.key] = it.value.tileNumber
|
tileNameToNumberMap[it.key] = it.value.tileNumber
|
||||||
}
|
}
|
||||||
@@ -252,15 +264,20 @@ open class GameWorld(
|
|||||||
for (x in 0 until layerTerrain.width) {
|
for (x in 0 until layerTerrain.width) {
|
||||||
layerTerrain.unsafeSetTile(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerTerrain.unsafeGetTile(x, y).toLong()]]!!)
|
layerTerrain.unsafeSetTile(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerTerrain.unsafeGetTile(x, y).toLong()]]!!)
|
||||||
layerWall.unsafeSetTile(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerWall.unsafeGetTile(x, y).toLong()]]!!)
|
layerWall.unsafeSetTile(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerWall.unsafeGetTile(x, y).toLong()]]!!)
|
||||||
|
layerOres.unsafeSetTileKeepPlacement(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerOres.unsafeGetTile(x, y).toLong()]]!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AN EXCEPTIONAL TERM: tilenum 0 is always redirected to Air tile, even if the tilenum for actual Air tile is not zero
|
// force this rule to the old saves
|
||||||
tileNumberToNameMap[0] = Block.AIR
|
tileNumberToNameMap[0] = Block.AIR
|
||||||
tileNameToNumberMap[Block.AIR] = 0
|
|
||||||
|
|
||||||
tileNumberToNameMap[2] = Block.UPDATE
|
tileNumberToNameMap[2] = Block.UPDATE
|
||||||
|
tileNameToNumberMap[Block.AIR] = 0
|
||||||
tileNameToNumberMap[Block.UPDATE] = 2
|
tileNameToNumberMap[Block.UPDATE] = 2
|
||||||
|
fluidNumberToNameMap[0] = Fluid.NULL
|
||||||
|
fluidNameToNumberMap[Fluid.NULL] = 0
|
||||||
|
|
||||||
|
|
||||||
|
BlocksDrawer.rebuildInternalPrecalculations()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,8 +288,9 @@ open class GameWorld(
|
|||||||
// get() = layerWire.data
|
// get() = layerWire.data
|
||||||
|
|
||||||
fun getLayer(index: Int) = when(index) {
|
fun getLayer(index: Int) = when(index) {
|
||||||
0 -> layerTerrain
|
TERRAIN -> layerTerrain
|
||||||
1 -> layerWall
|
WALL -> layerWall
|
||||||
|
ORES -> layerOres
|
||||||
else -> null//throw IllegalArgumentException("Unknown layer index: $index")
|
else -> null//throw IllegalArgumentException("Unknown layer index: $index")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,14 +375,25 @@ open class GameWorld(
|
|||||||
terrainDamages.remove(blockAddr)
|
terrainDamages.remove(blockAddr)
|
||||||
|
|
||||||
if (BlockCodex[itemID].isSolid) {
|
if (BlockCodex[itemID].isSolid) {
|
||||||
fluidFills.remove(blockAddr)
|
layerFluids.unsafeSetTile(x, y, fluidNameToNumberMap[Fluid.NULL]!!, 0f)
|
||||||
fluidTypes.remove(blockAddr)
|
// Terrarum.ingame?.modified(LandUtil.LAYER_FLUID, x, y)
|
||||||
}
|
}
|
||||||
// fluid tiles-item should be modified so that they will also place fluid onto their respective map
|
// fluid tiles-item should be modified so that they will also place fluid onto their respective map
|
||||||
|
|
||||||
|
val oldOre = layerOres.unsafeGetTile(x, y)
|
||||||
|
val deleteOldOre = (oldOre != 0 && !BlockCodex[itemID].isSolid)
|
||||||
|
|
||||||
|
if (deleteOldOre) {
|
||||||
|
layerOres.unsafeSetTile(x, y, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
if (!bypassEvent && oldTerrain != itemID) {
|
if (!bypassEvent && oldTerrain != itemID) {
|
||||||
Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, itemID, x, y)
|
Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, itemID, x, y)
|
||||||
Terrarum.ingame?.modified(LandUtil.LAYER_TERR, x, y)
|
Terrarum.ingame?.modified(LandUtil.LAYER_TERR, x, y)
|
||||||
|
|
||||||
|
if (deleteOldOre) {
|
||||||
|
Terrarum.ingame?.modified(LandUtil.LAYER_ORES, x, y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +410,7 @@ open class GameWorld(
|
|||||||
|
|
||||||
if (!bypassEvent) {
|
if (!bypassEvent) {
|
||||||
Terrarum.ingame?.queueWireChangedEvent(tile, false, x, y)
|
Terrarum.ingame?.queueWireChangedEvent(tile, false, x, y)
|
||||||
Terrarum.ingame?.modified(LandUtil.LAYER_WIRE, x, y)
|
// Terrarum.ingame?.modified(LandUtil.LAYER_WIRE, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -405,6 +434,13 @@ open class GameWorld(
|
|||||||
setWireGraphOfUnsafe(blockAddr, tile, connection)
|
setWireGraphOfUnsafe(blockAddr, tile, connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setTileOnLayerUnsafe(layer: Int, x: Int, y: Int, tile: Int) {
|
||||||
|
(getLayer(layer) ?: throw IllegalArgumentException("Unknown layer index: $layer")).let {
|
||||||
|
if (it !is BlockLayerI16) throw IllegalArgumentException("Block layers other than BlockLayer16 is not supported yet)")
|
||||||
|
it.unsafeSetTile(x, y, tile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun removeTileWire(x: Int, y: Int, tile: ItemID, bypassEvent: Boolean) {
|
fun removeTileWire(x: Int, y: Int, tile: ItemID, bypassEvent: Boolean) {
|
||||||
val (x, y) = coerceXY(x, y)
|
val (x, y) = coerceXY(x, y)
|
||||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||||
@@ -413,7 +449,7 @@ open class GameWorld(
|
|||||||
if (wireNode != null) {
|
if (wireNode != null) {
|
||||||
if (!bypassEvent) {
|
if (!bypassEvent) {
|
||||||
Terrarum.ingame?.queueWireChangedEvent(tile, true, x, y)
|
Terrarum.ingame?.queueWireChangedEvent(tile, true, x, y)
|
||||||
Terrarum.ingame?.modified(LandUtil.LAYER_WIRE, x, y)
|
// Terrarum.ingame?.modified(LandUtil.LAYER_WIRE, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// disconnect neighbouring nodes
|
// disconnect neighbouring nodes
|
||||||
@@ -543,11 +579,26 @@ open class GameWorld(
|
|||||||
return getTileFromWall(x, y)
|
return getTileFromWall(x, y)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw IllegalArgumentException("illegal mode input: " + mode.toString())
|
throw IllegalArgumentException("illegal mode input: $mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun terrainIterator(): Iterator<ItemID> {
|
/**
|
||||||
return object : Iterator<ItemID> {
|
* Will return (Block.AIR, 0) if there is no ore
|
||||||
|
*/
|
||||||
|
fun getTileFromOre(rawX: Int, rawY: Int): OrePlacement {
|
||||||
|
val (x, y) = coerceXY(rawX, rawY)
|
||||||
|
val (tileNum, placement) = layerOres.unsafeGetTile1(x, y)
|
||||||
|
val tileName = tileNumberToNameMap[tileNum.toLong()]
|
||||||
|
return OrePlacement(tileName ?: Block.UPDATE, placement)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTileOre(rawX: Int, rawY: Int, ore: ItemID, placement: Int) {
|
||||||
|
val (x, y) = coerceXY(rawX, rawY)
|
||||||
|
layerOres.unsafeSetTile(x, y, tileNameToNumberMap[ore]!!, placement)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun terrainIterator(): Iterator<List<ItemID>> {
|
||||||
|
return object : Iterator<List<ItemID>> {
|
||||||
|
|
||||||
private var iteratorCount = 0
|
private var iteratorCount = 0
|
||||||
|
|
||||||
@@ -555,13 +606,13 @@ open class GameWorld(
|
|||||||
return iteratorCount < width * height
|
return iteratorCount < width * height
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun next(): ItemID {
|
override fun next(): List<ItemID> {
|
||||||
val y = iteratorCount / width
|
val y = iteratorCount / width
|
||||||
val x = iteratorCount % width
|
val x = iteratorCount % width
|
||||||
// advance counter
|
// advance counter
|
||||||
iteratorCount += 1
|
iteratorCount += 1
|
||||||
|
|
||||||
return getTileFromTerrain(x, y)
|
return listOf(getTileFromTerrain(x, y), getTileFromWall(x, y), getTileFromOre(x, y).item)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -609,7 +660,7 @@ open class GameWorld(
|
|||||||
//println("[GameWorld] accumulated damage: ${terrainDamages[addr]}")
|
//println("[GameWorld] accumulated damage: ${terrainDamages[addr]}")
|
||||||
|
|
||||||
// remove tile from the world
|
// remove tile from the world
|
||||||
if (terrainDamages[addr] ?: 0f >= BlockCodex[getTileFromTerrain(x, y)].strength) {
|
if ((terrainDamages[addr] ?: 0f) >= BlockCodex[getTileFromTerrain(x, y)].strength) {
|
||||||
val tileBroke = getTileFromTerrain(x, y)
|
val tileBroke = getTileFromTerrain(x, y)
|
||||||
setTileTerrain(x, y, Block.AIR, false)
|
setTileTerrain(x, y, Block.AIR, false)
|
||||||
terrainDamages.remove(addr)
|
terrainDamages.remove(addr)
|
||||||
@@ -651,7 +702,9 @@ open class GameWorld(
|
|||||||
fun getWallDamage(x: Int, y: Int): Float =
|
fun getWallDamage(x: Int, y: Int): Float =
|
||||||
wallDamages[LandUtil.getBlockAddr(this, x, y)] ?: 0f
|
wallDamages[LandUtil.getBlockAddr(this, x, y)] ?: 0f
|
||||||
|
|
||||||
fun setFluid(x: Int, y: Int, fluidType: FluidType, fill: Float) {
|
fun setFluid(x: Int, y: Int, fluidType: ItemID, fill: Float) {
|
||||||
|
if (!fluidType.isFluid()) throw IllegalArgumentException("Fluid type is not actually fluid: $fluidType")
|
||||||
|
|
||||||
/*if (x == 60 && y == 256) {
|
/*if (x == 60 && y == 256) {
|
||||||
printdbg(this, "Setting fluid $fill at ($x,$y)")
|
printdbg(this, "Setting fluid $fill at ($x,$y)")
|
||||||
}*/
|
}*/
|
||||||
@@ -664,15 +717,14 @@ open class GameWorld(
|
|||||||
|
|
||||||
val addr = LandUtil.getBlockAddr(this, x, y)
|
val addr = LandUtil.getBlockAddr(this, x, y)
|
||||||
|
|
||||||
|
val fluidNumber = fluidNameToNumberMap[fluidType]!!
|
||||||
|
|
||||||
if (fill > WorldSimulator.FLUID_MIN_MASS) {
|
if (fill > WorldSimulator.FLUID_MIN_MASS) {
|
||||||
//setTileTerrain(x, y, fluidTypeToBlock(fluidType))
|
//setTileTerrain(x, y, fluidTypeToBlock(fluidType))
|
||||||
fluidFills[addr] = fill
|
layerFluids.unsafeSetTile(x, y, fluidNumber, fill)
|
||||||
fluidTypes[addr] = fluidType
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fluidFills.remove(addr)
|
layerFluids.unsafeSetTile(x, y, fluidNumber, 0f)
|
||||||
fluidTypes.remove(addr)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -684,23 +736,24 @@ open class GameWorld(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getFluid(x: Int, y: Int): FluidInfo {
|
fun getFluid(x: Int, y: Int): FluidInfo {
|
||||||
val addr = LandUtil.getBlockAddr(this, x, y)
|
val (x, y) = coerceXY(x, y)
|
||||||
val fill = fluidFills[addr]
|
val (type, fill) = layerFluids.unsafeGetTile1(x, y)
|
||||||
val type = fluidTypes[addr]
|
val fluidID = fluidNumberToNameMap[type.toLong()] ?: throw NullPointerException("No such fluid: $type")
|
||||||
return if (type == null) FluidInfo(Fluid.NULL, 0f) else FluidInfo(type, fill!!)
|
|
||||||
|
return FluidInfo(fluidID, fill)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fluidTypeToBlock(type: FluidType) = when (type.abs()) {
|
/*private fun fluidTypeToBlock(type: FluidType) = when (type.abs()) {
|
||||||
Fluid.NULL.value -> Block.AIR
|
Fluid.NULL.value -> Block.AIR
|
||||||
in Fluid.fluidRange -> GameWorld.TILES_SUPPORTED - type.abs()
|
in Fluid.fluidRange -> GameWorld.TILES_SUPPORTED - type.abs()
|
||||||
else -> throw IllegalArgumentException("Unsupported fluid type: $type")
|
else -> throw IllegalArgumentException("Unsupported fluid type: $type")
|
||||||
}
|
}*/
|
||||||
|
|
||||||
data class FluidInfo(val type: FluidType = Fluid.NULL, val amount: Float = 0f) {
|
data class FluidInfo(val type: ItemID = Fluid.NULL, val amount: Float = 0f) {
|
||||||
/** test if this fluid should be considered as one */
|
/** test if this fluid should be considered as one */
|
||||||
fun isFluid() = type != Fluid.NULL && amount >= WorldSimulator.FLUID_MIN_MASS
|
fun isFluid() = type != Fluid.NULL && amount >= WorldSimulator.FLUID_MIN_MASS
|
||||||
fun getProp() = BlockCodex[type]
|
fun getProp(): Nothing = TODO()
|
||||||
override fun toString() = "Fluid type: ${type.value}, amount: $amount"
|
override fun toString() = "Fluid type: ${type}, amount: $amount"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -747,9 +800,9 @@ open class GameWorld(
|
|||||||
override fun equals(other: Any?) = layerTerrain.ptr == (other as GameWorld).layerTerrain.ptr
|
override fun equals(other: Any?) = layerTerrain.ptr == (other as GameWorld).layerTerrain.ptr
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient const val WALL = 0
|
@Transient const val TERRAIN = 0
|
||||||
@Transient const val TERRAIN = 1
|
@Transient const val WALL = 1
|
||||||
@Transient const val WIRE = 2
|
@Transient const val ORES = 2
|
||||||
|
|
||||||
@Transient val TILES_SUPPORTED = ReferencingRanges.TILES.last + 1
|
@Transient val TILES_SUPPORTED = ReferencingRanges.TILES.last + 1
|
||||||
//@Transient val SIZEOF: Byte = 2
|
//@Transient val SIZEOF: Byte = 2
|
||||||
@@ -776,10 +829,3 @@ infix fun Int.fmod(other: Int) = Math.floorMod(this, other)
|
|||||||
infix fun Long.fmod(other: Long) = Math.floorMod(this, other)
|
infix fun Long.fmod(other: Long) = Math.floorMod(this, other)
|
||||||
infix fun Float.fmod(other: Float) = if (this >= 0f) this % other else (this % other) + other
|
infix fun Float.fmod(other: Float) = if (this >= 0f) this % other else (this % other) + other
|
||||||
infix fun Double.fmod(other: Double) = if (this >= 0.0) this % other else (this % other) + other
|
infix fun Double.fmod(other: Double) = if (this >= 0.0) this % other else (this % other) + other
|
||||||
|
|
||||||
@JvmInline
|
|
||||||
value class FluidType(val value: Int) {
|
|
||||||
infix fun sameAs(other: FluidType) = this.value.absoluteValue == other.value.absoluteValue
|
|
||||||
fun abs() = this.value.absoluteValue
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ object WorldSimulator {
|
|||||||
|
|
||||||
const val FLUID_MAX_MASS = 1f // The normal, un-pressurized mass of a full water cell
|
const val FLUID_MAX_MASS = 1f // The normal, un-pressurized mass of a full water cell
|
||||||
const val FLUID_MAX_COMP = 0.02f // How much excess water a cell can store, compared to the cell above it. A tile of fluid can contain more than MaxMass water.
|
const val FLUID_MAX_COMP = 0.02f // How much excess water a cell can store, compared to the cell above it. A tile of fluid can contain more than MaxMass water.
|
||||||
const val FLUID_MIN_MASS = 0.0001f //Ignore cells that are almost dry
|
const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smaller than epsilon of float16)
|
||||||
const val WIRE_MIN_FLOW = 0.0001f
|
const val WIRE_MIN_FLOW = 0.0001f
|
||||||
const val minFlow = 0.01f
|
const val minFlow = 0.01f
|
||||||
const val maxSpeed = 1f // max units of water moved out of one block to another, per timestamp
|
const val maxSpeed = 1f // max units of water moved out of one block to another, per timestamp
|
||||||
@@ -151,6 +151,7 @@ object WorldSimulator {
|
|||||||
if (result.distance < pickupDistSqr) {
|
if (result.distance < pickupDistSqr) {
|
||||||
droppedItem.flagDespawn = true
|
droppedItem.flagDespawn = true
|
||||||
(actor as Pocketed).inventory.add(droppedItem.itemID, droppedItem.itemCount)
|
(actor as Pocketed).inventory.add(droppedItem.itemID, droppedItem.itemCount)
|
||||||
|
ItemCodex[droppedItem.itemID]!!.effectOnPickup(actor)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,12 +179,12 @@ object WorldSimulator {
|
|||||||
fluidmapToWorld()
|
fluidmapToWorld()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFlowable(type: FluidType, worldX: Int, worldY: Int): Boolean {
|
fun isFlowable(type: ItemID, worldX: Int, worldY: Int): Boolean {
|
||||||
val fluid = world.getFluid(worldX, worldY)
|
val fluid = world.getFluid(worldX, worldY)
|
||||||
val tile = world.getTileFromTerrain(worldX, worldY)
|
val tile = world.getTileFromTerrain(worldX, worldY)
|
||||||
|
|
||||||
// true if target's type is the same as mine, or it's NULL (air)
|
// true if target's type is the same as mine, or it's NULL (air)
|
||||||
return ((fluid.type sameAs type || fluid.type sameAs Fluid.NULL) && !BlockCodex[tile].isSolid)
|
return ((fluid.type == type || fluid.type == Fluid.NULL) && !BlockCodex[tile].isSolid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ class Material {
|
|||||||
|
|
||||||
var toolReach: Int = 6
|
var toolReach: Int = 6
|
||||||
|
|
||||||
|
var rcs: Int = 10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mainly intended to be used by third-party modules
|
* Mainly intended to be used by third-party modules
|
||||||
*/
|
*/
|
||||||
@@ -70,6 +72,7 @@ class MaterialCodex {
|
|||||||
prop.thermalConductivity = it.floatVal("tcond")
|
prop.thermalConductivity = it.floatVal("tcond")
|
||||||
prop.identifier = it.get("idst").toUpperCase()
|
prop.identifier = it.get("idst").toUpperCase()
|
||||||
prop.toolReach = it.intVal("reach")
|
prop.toolReach = it.intVal("reach")
|
||||||
|
prop.rcs = it.intVal("rcs")
|
||||||
|
|
||||||
materialProps[prop.identifier] = prop
|
materialProps[prop.identifier] = prop
|
||||||
|
|
||||||
@@ -86,6 +89,6 @@ class MaterialCodex {
|
|||||||
throw NullPointerException("Material with id $identifier does not exist.")
|
throw NullPointerException("Material with id $identifier does not exist.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrDefault(identifier: String) = materialProps[identifier.toUpperCase()] ?: nullMaterial
|
fun getOrDefault(identifier: String?) = materialProps[identifier?.toUpperCase()] ?: nullMaterial
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,6 @@ import com.badlogic.gdx.InputAdapter
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import net.torvald.gdx.graphics.Cvec
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
@@ -14,16 +13,26 @@ import net.torvald.terrarum.gameactors.*
|
|||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
|
import net.torvald.terrarum.gameworld.BlockLayerI16
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.gameworld.WorldTime
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
||||||
|
import net.torvald.terrarum.modulebasegame.ui.UIScreenZoom
|
||||||
|
import net.torvald.terrarum.serialise.Common
|
||||||
|
import net.torvald.terrarum.serialise.PointOfInterest
|
||||||
|
import net.torvald.terrarum.serialise.POILayer
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarum.weather.WeatherMixer
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
import net.torvald.terrarum.ui.UINSMenu
|
import net.torvald.terrarum.ui.UINSMenu
|
||||||
|
import net.torvald.terrarum.utils.OrePlacement
|
||||||
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2018-07-06.
|
* Created by minjaesong on 2018-07-06.
|
||||||
@@ -32,72 +41,37 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
private val menuYaml = Yaml("""
|
private val menuYaml = Yaml("""
|
||||||
- File
|
- File
|
||||||
- New flat ter.
|
- New Flat ter. : net.torvald.terrarum.modulebasegame.YamlCommandNewFlatTerrain
|
||||||
- New rand. ter.
|
- New Rand. ter.
|
||||||
- Export…
|
- Export… : net.torvald.terrarum.modulebasegame.YamlCommandToolExportTest
|
||||||
- Export sel…
|
- Import… : net.torvald.terrarum.modulebasegame.YamlCommandToolImportTest
|
||||||
- Import…
|
|
||||||
- Save terrain…
|
|
||||||
- Load terrain…
|
|
||||||
-
|
|
||||||
- Exit to Title : net.torvald.terrarum.modulebasegame.YamlCommandExit
|
- Exit to Title : net.torvald.terrarum.modulebasegame.YamlCommandExit
|
||||||
- Tool
|
- Edit
|
||||||
- Pencil : net.torvald.terrarum.modulebasegame.YamlCommandToolPencil
|
- Clear Selections : net.torvald.terrarum.modulebasegame.YamlCommandClearSelection
|
||||||
- Eraser : net.torvald.terrarum.modulebasegame.YamlCommandToolPencilErase
|
|
||||||
- Wall Hammer : net.torvald.terrarum.modulebasegame.YamlCommandToolPencilEraseWall
|
|
||||||
- Eyedropper : net.torvald.terrarum.modulebasegame.YamlCommandToolEyedropper
|
|
||||||
- Add Selection : net.torvald.terrarum.modulebasegame.YamlCommandToolMarquee
|
|
||||||
- Remove Sel. : net.torvald.terrarum.modulebasegame.YamlCommandToolMarqueeErase
|
|
||||||
- Clear Sel. : net.torvald.terrarum.modulebasegame.YamlCommandToolMarqueeClear
|
|
||||||
- Move Selected
|
|
||||||
-
|
|
||||||
- Hide/Show Sel. : net.torvald.terrarum.modulebasegame.YamlCommandToolToggleMarqueeOverlay
|
|
||||||
-
|
|
||||||
- Undo
|
|
||||||
- Redo
|
|
||||||
- Time
|
- Time
|
||||||
|
- Dawn : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeDawn
|
||||||
|
- Sunrise : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeSunrise
|
||||||
- Morning : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeMorning
|
- Morning : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeMorning
|
||||||
- Noon : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNoon
|
- Noon : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNoon
|
||||||
- Dusk : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeDusk
|
- Dusk : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeDusk
|
||||||
|
- Sunset : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeSunset
|
||||||
- Night : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNight
|
- Night : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeNight
|
||||||
|
- Midnight : net.torvald.terrarum.modulebasegame.YamlCommandSetTimeMidnight
|
||||||
- Set…
|
- Set…
|
||||||
- Weather
|
|
||||||
- Sunny
|
|
||||||
- Raining
|
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
private val timeNow = System.currentTimeMillis() / 1000
|
lateinit var gameWorld: GameWorld
|
||||||
|
|
||||||
val gameWorld = GameWorld(90*12, 90*4, timeNow, timeNow)
|
override val musicGovernor = TerrarumMusicGovernor()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// ghetto world for building
|
gameUpdateGovernor = ConsistentUpdateRate
|
||||||
|
YamlCommandNewFlatTerrain().invoke(arrayOf(this))
|
||||||
|
}
|
||||||
|
|
||||||
println("[BuildingMaker] Generating builder world...")
|
internal fun reset() {
|
||||||
|
gameUpdateGovernor.reset()
|
||||||
for (y in 0 until gameWorld.height) {
|
WeatherMixer.forceSolarElev = 5.0
|
||||||
gameWorld.setTileWall(0, y, Block.ILLUMINATOR_RED, true)
|
|
||||||
gameWorld.setTileWall(gameWorld.width - 1, y, Block.ILLUMINATOR_RED, true)
|
|
||||||
gameWorld.setTileTerrain(0, y, Block.ILLUMINATOR_RED_OFF, true)
|
|
||||||
gameWorld.setTileTerrain(gameWorld.width - 1, y, Block.ILLUMINATOR_RED_OFF, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (y in 150 until gameWorld.height) {
|
|
||||||
for (x in 1 until gameWorld.width - 1) {
|
|
||||||
// wall layer
|
|
||||||
gameWorld.setTileWall(x, y, Block.DIRT, true)
|
|
||||||
|
|
||||||
// terrain layer
|
|
||||||
gameWorld.setTileTerrain(x, y, if (y == 150) Block.GRASS else Block.DIRT, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set time to summer
|
|
||||||
gameWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
|
||||||
|
|
||||||
world = gameWorld
|
|
||||||
|
|
||||||
gameUpdateGovernor = ConsistentUpdateRate.also { it.reset() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -108,9 +82,13 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
val uiPalette = UIBuildingMakerBlockChooser(this)
|
val uiPalette = UIBuildingMakerBlockChooser(this)
|
||||||
val uiPenMenu = UIBuildingMakerPenMenu(this)
|
val uiPenMenu = UIBuildingMakerPenMenu(this)
|
||||||
|
|
||||||
|
val uiGetPoiName = UIBuildingMakerGetFilename() // used for both import and export
|
||||||
|
|
||||||
val uiContainer = UIContainer()
|
val uiContainer = UIContainer()
|
||||||
|
|
||||||
|
val keyboardUsedByTextInput: Boolean
|
||||||
|
get() = uiGetPoiName.textInput.isEnabled
|
||||||
|
|
||||||
private val pensMustShowSelection = arrayOf(
|
private val pensMustShowSelection = arrayOf(
|
||||||
PENMODE_MARQUEE, PENMODE_MARQUEE_ERASE
|
PENMODE_MARQUEE, PENMODE_MARQUEE_ERASE
|
||||||
)
|
)
|
||||||
@@ -124,7 +102,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
var currentPenTarget = PENTARGET_TERRAIN
|
var currentPenTarget = PENTARGET_TERRAIN
|
||||||
|
|
||||||
val selection = ArrayList<Point2i>()
|
val selection = ArrayList<Long>()
|
||||||
|
|
||||||
val blockMarkings = CommonResourcePool.getAsTextureRegionPack("blockmarkings_common")
|
val blockMarkings = CommonResourcePool.getAsTextureRegionPack("blockmarkings_common")
|
||||||
internal var showSelection = true
|
internal var showSelection = true
|
||||||
@@ -227,41 +205,52 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
internal fun addBlockMarker(x: Int, y: Int) {
|
internal fun addBlockMarker(x: Int, y: Int) {
|
||||||
try {
|
try {
|
||||||
val a = generateNewBlockMarkerVisible(x, y)
|
val a = generateNewBlockMarkerVisible(x, y)
|
||||||
queueActorAddition(a)
|
if (!theGameHasActor(a.referenceID)) {
|
||||||
actorsRenderOverlay.add(a)
|
selection.add(toAddr(x, y))
|
||||||
selection.add(Point2i(x, y))
|
actorsRenderOverlay.add(a)
|
||||||
|
queueActorAddition(a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (e: Error) { }
|
catch (e: Error) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun removeBlockMarker(x: Int, y: Int) {
|
internal fun removeBlockMarker(x: Int, y: Int) {
|
||||||
try {
|
try {
|
||||||
|
selection.remove(toAddr(x, y))
|
||||||
val a = getActorByID(blockPosToRefID(x, y))
|
val a = getActorByID(blockPosToRefID(x, y))
|
||||||
queueActorAddition(a)
|
|
||||||
actorsRenderOverlay.remove(a)
|
actorsRenderOverlay.remove(a)
|
||||||
selection.remove(Point2i(x, y))
|
queueActorRemoval(a)
|
||||||
}
|
}
|
||||||
catch (e: IllegalArgumentException) {
|
catch (e: Throwable) {
|
||||||
// no actor to erase, do nothing
|
// no actor to erase, do nothing
|
||||||
|
// e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal var imported: PointOfInterest? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val PENMODE_PENCIL = 0
|
const val PENMODE_PENCIL = 0
|
||||||
const val PENMODE_PENCIL_ERASE = 1
|
const val PENMODE_PENCIL_ERASE = 1
|
||||||
const val PENMODE_MARQUEE = 2
|
const val PENMODE_MARQUEE = 2
|
||||||
const val PENMODE_MARQUEE_ERASE = 3
|
const val PENMODE_MARQUEE_ERASE = 3
|
||||||
const val PENMODE_EYEDROPPER = 4
|
const val PENMODE_EYEDROPPER = 4
|
||||||
|
const val PENMODE_IMPORT = 8
|
||||||
|
|
||||||
const val PENTARGET_TERRAIN = 1
|
const val PENTARGET_TERRAIN = 1
|
||||||
const val PENTARGET_WALL = 2
|
const val PENTARGET_WALL = 2
|
||||||
|
const val PENTARGET_ORE = 4
|
||||||
|
|
||||||
val toolCursorColour = arrayOf(
|
val toolCursorColour = arrayOf(
|
||||||
Color.YELLOW,
|
Color.YELLOW,
|
||||||
Color.YELLOW,
|
Color.YELLOW,
|
||||||
Color.MAGENTA,
|
Color.MAGENTA,
|
||||||
Color.MAGENTA,
|
Color.MAGENTA,
|
||||||
Color.WHITE
|
Color.WHITE,
|
||||||
|
Color.WHITE,
|
||||||
|
Color.WHITE,
|
||||||
|
Color.WHITE,
|
||||||
|
Color.MAGENTA,
|
||||||
)
|
)
|
||||||
|
|
||||||
const val DEFAULT_POI_NAME = "The Yucky Panopticon"
|
const val DEFAULT_POI_NAME = "The Yucky Panopticon"
|
||||||
@@ -271,16 +260,17 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
private val essentialOverlays = ArrayList<ActorWithBody>()
|
private val essentialOverlays = ArrayList<ActorWithBody>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
gameWorld.worldTime.setTimeOfToday(WorldTime.HOUR_SEC * 10)
|
|
||||||
gameWorld.globalLight = Cvec(.8f, .8f, .8f, .8f)
|
|
||||||
|
|
||||||
essentialOverlays.add(blockPointingCursor)
|
essentialOverlays.add(blockPointingCursor)
|
||||||
|
|
||||||
uiContainer.add(uiToolbox)
|
uiContainer.add(
|
||||||
uiContainer.add(uiPaletteSelector)
|
uiToolbox,
|
||||||
uiContainer.add(notifier)
|
uiPaletteSelector,
|
||||||
uiContainer.add(uiPalette)
|
notifier,
|
||||||
uiContainer.add(uiPenMenu)
|
uiPalette,
|
||||||
|
uiPenMenu,
|
||||||
|
uiGetPoiName,
|
||||||
|
UIScreenZoom(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -288,11 +278,13 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
uiToolbox.isVisible = true
|
uiToolbox.isVisible = true
|
||||||
uiToolbox.invocationArgument = arrayOf(this)
|
uiToolbox.invocationArgument = arrayOf(this)
|
||||||
|
|
||||||
uiPaletteSelector.setPosition(App.scr.width - uiPaletteSelector.width, 0)
|
uiPaletteSelector.setPosition(0, App.scr.height - uiPaletteSelector.height)
|
||||||
uiPaletteSelector.isVisible = true
|
uiPaletteSelector.isVisible = true
|
||||||
|
|
||||||
notifier.setPosition(
|
notifier.setPosition(
|
||||||
(App.scr.width - notifier.width) / 2, App.scr.height - notifier.height)
|
(Toolkit.drawWidth - notifier.width) / 2,
|
||||||
|
App.scr.height - notifier.height - App.scr.tvSafeGraphicsHeight
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
actorNowPlaying?.setPosition(512 * 16.0, 149 * 16.0)
|
actorNowPlaying?.setPosition(512 * 16.0, 149 * 16.0)
|
||||||
@@ -311,7 +303,14 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private var disableMouseClick = false
|
||||||
|
var mousePrimaryJustDown = false; private set
|
||||||
|
|
||||||
override fun render(updateRate: Float) {
|
override fun render(updateRate: Float) {
|
||||||
|
super.render(updateRate)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Gdx.graphics.setTitle(TerrarumIngame.getCanonicalTitle())
|
Gdx.graphics.setTitle(TerrarumIngame.getCanonicalTitle())
|
||||||
|
|
||||||
|
|
||||||
@@ -329,6 +328,11 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))) {
|
||||||
|
disableMouseClick = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mouseOnUI = false
|
private var mouseOnUI = false
|
||||||
@@ -337,9 +341,12 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
private val updateGame = { delta: Float ->
|
private val updateGame = { delta: Float ->
|
||||||
|
|
||||||
WeatherMixer.update(delta, actorNowPlaying, gameWorld)
|
|
||||||
blockPointingCursor.update(delta)
|
blockPointingCursor.update(delta)
|
||||||
actorNowPlaying?.update(delta)
|
|
||||||
|
if (!keyboardUsedByTextInput) {
|
||||||
|
actorNowPlaying?.update(delta)
|
||||||
|
}
|
||||||
|
|
||||||
var overwriteMouseOnUI = false
|
var overwriteMouseOnUI = false
|
||||||
uiContainer.forEach {
|
uiContainer.forEach {
|
||||||
it?.update(delta)
|
it?.update(delta)
|
||||||
@@ -348,7 +355,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseOnUI = (overwriteMouseOnUI || uiPenMenu.isVisible)
|
mouseOnUI = (overwriteMouseOnUI || uiPenMenu.isVisible /*|| uiPalette.isVisible*/ || uiGetPoiName.isVisible)
|
||||||
|
|
||||||
|
|
||||||
WorldCamera.update(world, actorNowPlaying)
|
WorldCamera.update(world, actorNowPlaying)
|
||||||
@@ -374,7 +381,74 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
uiPenMenu.setAsOpen()
|
uiPenMenu.setAsOpen()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
actorAdditionQueue.forEach { forceAddActor(it.first, it.second) }
|
||||||
|
actorAdditionQueue.clear()
|
||||||
|
actorRemovalQueue.forEach { forceRemoveActor(it.first, it.second) }
|
||||||
|
actorRemovalQueue.clear()
|
||||||
|
|
||||||
|
|
||||||
BlockPropUtil.dynamicLumFuncTickClock()
|
BlockPropUtil.dynamicLumFuncTickClock()
|
||||||
|
WeatherMixer.update(delta, actorNowPlaying, gameWorld)
|
||||||
|
if (WORLD_UPDATE_TIMER % 2 == 1) {
|
||||||
|
fillUpWiresBuffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
musicGovernor.update(this, delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val maxRenderableWires = ReferencingRanges.ACTORS_WIRES.last - ReferencingRanges.ACTORS_WIRES.first + 1
|
||||||
|
private val wireActorsContainer = Array(maxRenderableWires) { WireActor(ReferencingRanges.ACTORS_WIRES.first + it).let {
|
||||||
|
forceAddActor(it)
|
||||||
|
/*^let*/ it
|
||||||
|
} }
|
||||||
|
var selectedWireRenderClass = ""
|
||||||
|
private var oldSelectedWireRenderClass = ""
|
||||||
|
|
||||||
|
|
||||||
|
private fun fillUpWiresBuffer() {
|
||||||
|
val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorToInt() - LightmapRenderer.LIGHTMAP_OVERRENDER
|
||||||
|
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical + 2* LightmapRenderer.LIGHTMAP_OVERRENDER
|
||||||
|
|
||||||
|
val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorToInt() - LightmapRenderer.LIGHTMAP_OVERRENDER
|
||||||
|
val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal + 2* LightmapRenderer.LIGHTMAP_OVERRENDER
|
||||||
|
|
||||||
|
var wiringCounter = 0
|
||||||
|
for (y in for_y_start..for_y_end) {
|
||||||
|
for (x in for_x_start..for_x_end) {
|
||||||
|
if (wiringCounter >= maxRenderableWires) break
|
||||||
|
|
||||||
|
val (wires, nodes) = world.getAllWiresFrom(x, y)
|
||||||
|
|
||||||
|
wires?.forEach {
|
||||||
|
val wireActor = wireActorsContainer[wiringCounter]
|
||||||
|
|
||||||
|
wireActor.setWire(it, x, y, nodes!![it]!!.cnx)
|
||||||
|
|
||||||
|
if (WireCodex[it].renderClass == selectedWireRenderClass || selectedWireRenderClass == "wire_render_all") {
|
||||||
|
wireActor.renderOrder = Actor.RenderOrder.OVERLAY
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wireActor.renderOrder = Actor.RenderOrder.BEHIND
|
||||||
|
}
|
||||||
|
|
||||||
|
wireActor.isUpdate = true
|
||||||
|
wireActor.isVisible = true
|
||||||
|
wireActor.forceDormant = false
|
||||||
|
|
||||||
|
wiringCounter += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in wiringCounter until maxRenderableWires) {
|
||||||
|
wireActorsContainer[i].isUpdate = false
|
||||||
|
wireActorsContainer[i].isVisible = false
|
||||||
|
wireActorsContainer[i].forceDormant = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val particles = CircularArray<ParticleBase>(16, true)
|
private val particles = CircularArray<ParticleBase>(16, true)
|
||||||
@@ -383,7 +457,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
_testMarkerDrawCalls = 0L
|
_testMarkerDrawCalls = 0L
|
||||||
|
|
||||||
IngameRenderer.invoke(false,
|
IngameRenderer.invoke(false,
|
||||||
1f,
|
screenZoom,
|
||||||
listOf(),
|
listOf(),
|
||||||
listOf(),
|
listOf(),
|
||||||
listOf(),
|
listOf(),
|
||||||
@@ -398,9 +472,13 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
override fun resize(width: Int, height: Int) {
|
override fun resize(width: Int, height: Int) {
|
||||||
IngameRenderer.resize(App.scr.width, App.scr.height)
|
IngameRenderer.resize(App.scr.width, App.scr.height)
|
||||||
|
val drawWidth = Toolkit.drawWidth
|
||||||
|
|
||||||
uiToolbox.setPosition(0, 0)
|
uiToolbox.setPosition(0, 0)
|
||||||
notifier.setPosition(
|
notifier.setPosition(
|
||||||
(App.scr.width - notifier.width) / 2, App.scr.height - notifier.height)
|
(Toolkit.drawWidth - notifier.width) / 2,
|
||||||
|
App.scr.height - notifier.height - App.scr.tvSafeGraphicsHeight
|
||||||
|
)
|
||||||
|
|
||||||
println("[BuildingMaker] Resize event")
|
println("[BuildingMaker] Resize event")
|
||||||
}
|
}
|
||||||
@@ -412,95 +490,136 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
blockMarkings.dispose()
|
// blockMarkings.dispose()
|
||||||
uiPenMenu.dispose()
|
uiPenMenu.dispose()
|
||||||
|
uiGetPoiName.dispose()
|
||||||
|
musicGovernor.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inputStrobed(e: TerrarumKeyboardEvent) {
|
fun getPoiNameForExport(w: Int, h: Int, callback: (String) -> Unit) {
|
||||||
|
uiGetPoiName.let {
|
||||||
|
it.title = "Export"
|
||||||
|
it.labelDo = "Export"
|
||||||
|
it.text = listOf("WH: $w\u00D7$h", "Name of the POI:")
|
||||||
|
it.confirmCallback = { s ->
|
||||||
|
callback(s)
|
||||||
|
disableMouseClick = true
|
||||||
|
}
|
||||||
|
it.cancelCallback = {
|
||||||
|
disableMouseClick = true
|
||||||
|
}
|
||||||
|
it.setPosition(
|
||||||
|
240,
|
||||||
|
32
|
||||||
|
)
|
||||||
|
it.reset()
|
||||||
|
it.setAsOpen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPoiNameForImport(callback: (String) -> Unit) {
|
||||||
|
uiGetPoiName.let {
|
||||||
|
it.title = "Import"
|
||||||
|
it.labelDo = "Import"
|
||||||
|
it.text = listOf("Name of the POI:")
|
||||||
|
it.confirmCallback = { s ->
|
||||||
|
callback(s)
|
||||||
|
disableMouseClick = true
|
||||||
|
}
|
||||||
|
it.cancelCallback = {
|
||||||
|
disableMouseClick = true
|
||||||
|
}
|
||||||
|
it.setPosition(
|
||||||
|
240,
|
||||||
|
32
|
||||||
|
)
|
||||||
|
it.reset()
|
||||||
|
it.setAsOpen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getNearbyTilesPos8(x: Int, y: Int): Array<Point2i> {
|
||||||
|
return arrayOf(
|
||||||
|
Point2i(x + 1, y),
|
||||||
|
Point2i(x + 1, y + 1),
|
||||||
|
Point2i(x, y + 1),
|
||||||
|
Point2i(x - 1, y + 1),
|
||||||
|
Point2i(x - 1, y),
|
||||||
|
Point2i(x - 1, y - 1),
|
||||||
|
Point2i(x, y - 1),
|
||||||
|
Point2i(x + 1, y - 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
private fun getNearbyOres8(x: Int, y: Int): List<OrePlacement> {
|
||||||
|
return getNearbyTilesPos8(x, y).map { world.getTileFromOre(it.x, it.y) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makePenWork(x: Int, y: Int) {
|
private fun makePenWork(x: Int, y: Int) {
|
||||||
val world = gameWorld
|
val world = gameWorld
|
||||||
val palSelection = uiPaletteSelector.fore
|
val palSelection = uiPaletteSelector.fore
|
||||||
|
|
||||||
when (currentPenMode) {
|
if (!disableMouseClick) {
|
||||||
// test paint terrain layer
|
when (currentPenMode) {
|
||||||
PENMODE_PENCIL -> {
|
// test paint terrain layer
|
||||||
if (palSelection.startsWith("wall@"))
|
PENMODE_PENCIL -> {
|
||||||
world.setTileWall(x, y, palSelection.substring(5), true)
|
if (palSelection.startsWith("wall@"))
|
||||||
else
|
world.setTileWall(x, y, palSelection.substring(5), true)
|
||||||
world.setTileTerrain(x, y, palSelection, true)
|
else if (palSelection.startsWith("ore@")) {
|
||||||
}
|
// get autotiling placement
|
||||||
PENMODE_PENCIL_ERASE -> {
|
val autotiled = getNearbyOres8(x, y).foldIndexed(0) { index, acc, placement ->
|
||||||
if (currentPenTarget and PENTARGET_WALL != 0)
|
acc or (placement.item == palSelection).toInt(index)
|
||||||
world.setTileWall(x, y, Block.AIR, true)
|
}
|
||||||
else
|
val placement = BlocksDrawer.connectLut16[autotiled]
|
||||||
world.setTileTerrain(x, y, Block.AIR, true)
|
|
||||||
}
|
world.setTileOre(x, y, palSelection, placement)
|
||||||
PENMODE_EYEDROPPER -> {
|
}
|
||||||
uiPaletteSelector.fore = if (world.getTileFromTerrain(x, y) == Block.AIR)
|
else
|
||||||
"wall@"+world.getTileFromWall(x, y)
|
world.setTileTerrain(x, y, palSelection, true)
|
||||||
else
|
}
|
||||||
world.getTileFromTerrain(x, y)
|
|
||||||
}
|
PENMODE_PENCIL_ERASE -> {
|
||||||
PENMODE_MARQUEE -> {
|
if (currentPenTarget and PENTARGET_TERRAIN != 0)
|
||||||
addBlockMarker(x, y)
|
world.setTileTerrain(x, y, Block.AIR, true)
|
||||||
}
|
if (currentPenTarget and PENTARGET_WALL != 0)
|
||||||
PENMODE_MARQUEE_ERASE -> {
|
world.setTileWall(x, y, Block.AIR, true)
|
||||||
removeBlockMarker(x, y)
|
if (currentPenTarget and PENTARGET_ORE != 0)
|
||||||
|
world.setTileOre(x, y, Block.NULL, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
PENMODE_EYEDROPPER -> {
|
||||||
|
uiPaletteSelector.fore = if (world.getTileFromTerrain(x, y) == Block.AIR)
|
||||||
|
"wall@" + world.getTileFromWall(x, y)
|
||||||
|
else
|
||||||
|
world.getTileFromTerrain(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
PENMODE_MARQUEE -> {
|
||||||
|
addBlockMarker(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
PENMODE_MARQUEE_ERASE -> {
|
||||||
|
removeBlockMarker(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
PENMODE_IMPORT -> {
|
||||||
|
importPoi(x, y)
|
||||||
|
disableMouseClick = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSelectionTotalDimension(): Point2i {
|
private fun importPoi(x: Int, y: Int) {
|
||||||
selection.sortBy { it.y * world.width + it.x }
|
imported?.let {
|
||||||
return selection.last() - selection.first()
|
it.placeOnWorld(listOf(it.layers.first().name), world, x, y) // TODO show layer list and ticker using right click?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*private fun serialiseSelection(outfile: File) {
|
override fun inputStrobed(e: TerrarumKeyboardEvent) {
|
||||||
// save format: sparse list encoded in following binary format:
|
uiContainer.forEach {
|
||||||
/*
|
it?.inputStrobed(e)
|
||||||
Header: TEaT0bLD -- magic: Terrarum Attachment
|
|
||||||
Int8 version number -- always 1
|
|
||||||
Int8 number of layers -- always 2 or 3
|
|
||||||
Int8 number of payloads -- always 2 or 3
|
|
||||||
int8 compression algorithm -- always 1 (DEFLATE)
|
|
||||||
Int16 width
|
|
||||||
|
|
||||||
The rest: payloads defined in the map data format
|
|
||||||
Payloads: array of (Int48 tileAddress, UInt16 blockID)
|
|
||||||
Payload names: TerL, WalL, WirL for Terrain, Wall and Wire respectively
|
|
||||||
|
|
||||||
Footer: EndTEM \xFF\xFE -- magic: end of attachment with BOM
|
|
||||||
|
|
||||||
Endian: LITTLE
|
|
||||||
*/
|
|
||||||
// proc:
|
|
||||||
// translate boxes so that leftmost point is (0,0)
|
|
||||||
// write to the list using translated coords
|
|
||||||
|
|
||||||
val payloads = arrayOf("WalL", "TerL", "WirL")
|
|
||||||
|
|
||||||
val selectionDim = getSelectionTotalDimension()
|
|
||||||
val fos = FileOutputStream(outfile)
|
|
||||||
// write header
|
|
||||||
fos.write("TEaT0bLD".toByteArray())
|
|
||||||
fos.write(byteArrayOf(1,3,3,1))
|
|
||||||
fos.write(selectionDim.x.toLittleShort())
|
|
||||||
// write wall -> terrain -> wire (order defined in GameWorld.TERRAIN/WALL/WIRE)
|
|
||||||
payloads.forEachIndexed { index, it ->
|
|
||||||
fos.write(PAYLOAD_HEADER); fos.write(it.toByteArray())
|
|
||||||
selection.forEach {
|
|
||||||
val tile = world.getTileFrom(index, it.x, it.y)!!
|
|
||||||
val addr = LandUtil.getBlockAddr(world, it.x - selectionDim.x, it.y - selectionDim.y)
|
|
||||||
fos.write(addr.toULittle48())
|
|
||||||
fos.write(tile.toLittle())
|
|
||||||
}
|
|
||||||
fos.write(PAYLOAD_FOOTER)
|
|
||||||
}
|
}
|
||||||
fos.write(FILE_FOOTER)
|
}
|
||||||
fos.close()
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
|
class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
|
||||||
@@ -592,27 +711,59 @@ class YamlCommandExit : YamlInvokable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class YamlCommandSetTimeDawn : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("6h00"))
|
||||||
|
WeatherMixer.forceSolarElev = -3.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class YamlCommandSetTimeSunrise : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("6h00"))
|
||||||
|
WeatherMixer.forceSolarElev = 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class YamlCommandSetTimeMorning : YamlInvokable {
|
class YamlCommandSetTimeMorning : YamlInvokable {
|
||||||
override fun invoke(args: Array<Any>) {
|
override fun invoke(args: Array<Any>) {
|
||||||
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("7h00"))
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("6h00"))
|
||||||
|
WeatherMixer.forceSolarElev = 5.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class YamlCommandSetTimeNoon : YamlInvokable {
|
class YamlCommandSetTimeNoon : YamlInvokable {
|
||||||
override fun invoke(args: Array<Any>) {
|
override fun invoke(args: Array<Any>) {
|
||||||
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("12h30"))
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("12h00"))
|
||||||
|
WeatherMixer.forceSolarElev = 30.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class YamlCommandSetTimeDusk : YamlInvokable {
|
class YamlCommandSetTimeDusk : YamlInvokable {
|
||||||
override fun invoke(args: Array<Any>) {
|
override fun invoke(args: Array<Any>) {
|
||||||
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("18h40"))
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("18h00"))
|
||||||
|
WeatherMixer.forceSolarElev = 3.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class YamlCommandSetTimeSunset : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("18h00"))
|
||||||
|
WeatherMixer.forceSolarElev = 0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class YamlCommandSetTimeNight : YamlInvokable {
|
class YamlCommandSetTimeNight : YamlInvokable {
|
||||||
override fun invoke(args: Array<Any>) {
|
override fun invoke(args: Array<Any>) {
|
||||||
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("0h30"))
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("18h00"))
|
||||||
|
WeatherMixer.forceSolarElev = -8.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class YamlCommandSetTimeMidnight : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
(args[0] as BuildingMaker).gameWorld.worldTime.setTimeOfToday(WorldTime.parseTime("0h00"))
|
||||||
|
WeatherMixer.forceSolarElev = -30.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,7 +810,8 @@ class YamlCommandToolMarqueeErase : YamlInvokable {
|
|||||||
class YamlCommandToolMarqueeClear : YamlInvokable {
|
class YamlCommandToolMarqueeClear : YamlInvokable {
|
||||||
override fun invoke(args: Array<Any>) {
|
override fun invoke(args: Array<Any>) {
|
||||||
(args[0] as BuildingMaker).selection.toList().forEach {
|
(args[0] as BuildingMaker).selection.toList().forEach {
|
||||||
(args[0] as BuildingMaker).removeBlockMarker(it.x, it.y)
|
val (x, y) = (it % 4294967296).toInt() to (it / 4294967296).toInt()
|
||||||
|
(args[0] as BuildingMaker).removeBlockMarker(x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -669,3 +821,146 @@ class YamlCommandToolToggleMarqueeOverlay : YamlInvokable {
|
|||||||
(args[0] as BuildingMaker).showSelection = !(args[0] as BuildingMaker).showSelection
|
(args[0] as BuildingMaker).showSelection = !(args[0] as BuildingMaker).showSelection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class YamlCommandToolExportTest : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
val ui = (args[0] as BuildingMaker)
|
||||||
|
if (ui.selection.isEmpty()) return
|
||||||
|
|
||||||
|
val marked = HashSet<Long>()
|
||||||
|
fun isMarked(x: Int, y: Int) = marked.contains(toAddr(x, y))
|
||||||
|
|
||||||
|
|
||||||
|
// get the bounding box
|
||||||
|
var minX = 2147483647
|
||||||
|
var minY = 2147483647
|
||||||
|
var maxX = -1
|
||||||
|
var maxY = -1
|
||||||
|
ui.selection.forEach {
|
||||||
|
val (x, y) = (it % 4294967296).toInt() to (it / 4294967296).toInt()
|
||||||
|
|
||||||
|
if (x < minX) minX = x
|
||||||
|
if (y < minY) minY = y
|
||||||
|
if (x > maxX) maxX = x
|
||||||
|
if (y > maxY) maxY = y
|
||||||
|
|
||||||
|
marked.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.getPoiNameForExport(maxX - minX + 1, maxY - minY + 1) { name ->
|
||||||
|
// prepare POI
|
||||||
|
val poi = PointOfInterest(
|
||||||
|
name,
|
||||||
|
maxX - minX + 1,
|
||||||
|
maxY - minY + 1,
|
||||||
|
ui.world.tileNumberToNameMap,
|
||||||
|
ui.world.tileNameToNumberMap
|
||||||
|
)
|
||||||
|
val layer = POILayer(name)
|
||||||
|
val terr = BlockLayerI16(poi.w, poi.h)
|
||||||
|
val wall = BlockLayerI16(poi.w, poi.h)
|
||||||
|
layer.blockLayer = arrayListOf(terr, wall)
|
||||||
|
poi.layers.add(layer)
|
||||||
|
|
||||||
|
for (x in minX..maxX) {
|
||||||
|
for (y in minY..maxY) {
|
||||||
|
if (isMarked(x, y)) {
|
||||||
|
terr.unsafeSetTile(x - minX, y - minY, ui.world.getTileFromTerrainRaw(x, y))
|
||||||
|
wall.unsafeSetTile(x - minX, y - minY, ui.world.getTileFromWallRaw(x, y))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
terr.unsafeSetTile(x - minX, y - minY, -1)
|
||||||
|
wall.unsafeSetTile(x - minX, y - minY, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// process POI for export
|
||||||
|
val json = Common.jsoner
|
||||||
|
val jsonStr = json.toJson(poi)
|
||||||
|
|
||||||
|
|
||||||
|
val dir = App.defaultDir + "/Exports/"
|
||||||
|
val dirAsFile = File(dir)
|
||||||
|
if (!dirAsFile.exists()) {
|
||||||
|
dirAsFile.mkdir()
|
||||||
|
}
|
||||||
|
|
||||||
|
File(dirAsFile, "$name.poi").writeText(jsonStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Point2i.toAddr() = toAddr(this.x, this.y)
|
||||||
|
private fun toAddr(x: Int, y: Int) = (y.toLong().shl(32) or x.toLong().and(0xFFFFFFFFL))
|
||||||
|
|
||||||
|
class YamlCommandClearSelection : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
val ui = (args[0] as BuildingMaker)
|
||||||
|
try {
|
||||||
|
(ui.selection.clone() as ArrayList<Long>).forEach { i ->
|
||||||
|
ui.removeBlockMarker((i % 4294967296).toInt(), (i / 4294967296).toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: NullPointerException) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class YamlCommandNewFlatTerrain : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
YamlCommandClearSelection().invoke(args)
|
||||||
|
val ui = (args[0] as BuildingMaker)
|
||||||
|
|
||||||
|
println("[BuildingMaker] Generating builder world...")
|
||||||
|
|
||||||
|
val timeNow = System.currentTimeMillis() / 1000
|
||||||
|
ui.gameWorld = GameWorld(90*12, 90*4, timeNow, timeNow)
|
||||||
|
|
||||||
|
for (y in 0 until ui.gameWorld.height) {
|
||||||
|
ui.gameWorld.setTileWall(0, y, Block.ILLUMINATOR_RED, true)
|
||||||
|
ui.gameWorld.setTileWall(ui.gameWorld.width - 1, y, Block.ILLUMINATOR_RED, true)
|
||||||
|
ui.gameWorld.setTileTerrain(0, y, Block.ILLUMINATOR_RED_OFF, true)
|
||||||
|
ui.gameWorld.setTileTerrain(ui.gameWorld.width - 1, y, Block.ILLUMINATOR_RED_OFF, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y in 150 until ui.gameWorld.height) {
|
||||||
|
for (x in 1 until ui.gameWorld.width - 1) {
|
||||||
|
// wall layer
|
||||||
|
ui.gameWorld.setTileWall(x, y, Block.DIRT, true)
|
||||||
|
|
||||||
|
// terrain layer
|
||||||
|
ui.gameWorld.setTileTerrain(x, y, if (y == 150) Block.GRASS else Block.DIRT, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui.world = ui.gameWorld
|
||||||
|
|
||||||
|
|
||||||
|
// set time to summer morning
|
||||||
|
ui.gameWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
||||||
|
ui.gameWorld.worldTime.setTimeOfToday(18062)
|
||||||
|
|
||||||
|
ui.reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class YamlCommandToolImportTest : YamlInvokable {
|
||||||
|
override fun invoke(args: Array<Any>) {
|
||||||
|
val ui = (args[0] as BuildingMaker)
|
||||||
|
ui.getPoiNameForImport { name ->
|
||||||
|
YamlCommandClearSelection().invoke(args)
|
||||||
|
|
||||||
|
val jsonFile = File(App.defaultDir, "/Exports/$name.poi")
|
||||||
|
if (jsonFile.exists()) {
|
||||||
|
val json = jsonFile.readText()
|
||||||
|
|
||||||
|
val poi = Common.jsoner.fromJson(PointOfInterest().javaClass, json).also {
|
||||||
|
it.getReadyToBeUsed(ui.world.tileNameToNumberMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.imported = poi
|
||||||
|
ui.currentPenMode = BuildingMaker.PENMODE_IMPORT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,7 @@ class ChunkLoadingLoadScreen(screenToBeLoaded: IngameInstance, private val world
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(delta: Float) {
|
override fun render(delta: Float) {
|
||||||
gdxClearAndEnableBlend(.094f, .094f, .094f, 0f)
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
||||||
|
|
||||||
val drawWidth = Toolkit.drawWidth
|
val drawWidth = Toolkit.drawWidth
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import net.torvald.terrarum.*
|
|||||||
import net.torvald.terrarum.App.IS_DEVELOPMENT_BUILD
|
import net.torvald.terrarum.App.IS_DEVELOPMENT_BUILD
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.blockproperties.BlockProp
|
import net.torvald.terrarum.blockproperties.BlockProp
|
||||||
|
import net.torvald.terrarum.blockproperties.OreProp
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.itemproperties.CraftingCodex
|
import net.torvald.terrarum.itemproperties.CraftingCodex
|
||||||
@@ -39,6 +40,7 @@ class EntryPoint : ModuleEntryPoint() {
|
|||||||
ModMgr.GameMaterialLoader.invoke(moduleName)
|
ModMgr.GameMaterialLoader.invoke(moduleName)
|
||||||
ModMgr.GameItemLoader.invoke(moduleName)
|
ModMgr.GameItemLoader.invoke(moduleName)
|
||||||
ModMgr.GameBlockLoader.invoke(moduleName)
|
ModMgr.GameBlockLoader.invoke(moduleName)
|
||||||
|
ModMgr.GameOreLoader.invoke(moduleName)
|
||||||
ModMgr.GameLanguageLoader.invoke(moduleName)
|
ModMgr.GameLanguageLoader.invoke(moduleName)
|
||||||
ModMgr.GameCraftingRecipeLoader.invoke(moduleName)
|
ModMgr.GameCraftingRecipeLoader.invoke(moduleName)
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ class EntryPoint : ModuleEntryPoint() {
|
|||||||
printdbg(this, "recording item ID ")
|
printdbg(this, "recording item ID ")
|
||||||
|
|
||||||
// blocks.csvs are loaded by ModMgr beforehand
|
// blocks.csvs are loaded by ModMgr beforehand
|
||||||
// block items (blocks and walls are the same thing basically)
|
// register blocks as items
|
||||||
for (tile in BlockCodex.getAll()) {
|
for (tile in BlockCodex.getAll()) {
|
||||||
ItemCodex[tile.id] = makeNewItemObj(tile, false)
|
ItemCodex[tile.id] = makeNewItemObj(tile, false)
|
||||||
|
|
||||||
@@ -93,7 +95,7 @@ class EntryPoint : ModuleEntryPoint() {
|
|||||||
private fun makeNewItemObj(tile: BlockProp, isWall: Boolean) = object : GameItem(
|
private fun makeNewItemObj(tile: BlockProp, isWall: Boolean) = object : GameItem(
|
||||||
if (isWall) "wall@"+tile.id else tile.id
|
if (isWall) "wall@"+tile.id else tile.id
|
||||||
) {
|
) {
|
||||||
override var baseMass: Double = tile.density / 1000.0
|
override var baseMass: Double = tile.density / 100.0
|
||||||
override var baseToolSize: Double? = null
|
override var baseToolSize: Double? = null
|
||||||
override var inventoryCategory = if (isWall) Category.WALL else Category.BLOCK
|
override var inventoryCategory = if (isWall) Category.WALL else Category.BLOCK
|
||||||
override var isDynamic = false
|
override var isDynamic = false
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
||||||
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-10-30.
|
||||||
|
*/
|
||||||
|
open class FancyWorldReadLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidth: Int, private val worldheight: Int, override var preLoadJob: (LoadScreenBase) -> Unit) : LoadScreenBase() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
CommonResourcePool.addToLoadingList("basegame-gui-loadscrlayer01") {
|
||||||
|
Texture(ModMgr.getGdxFile("basegame", "gui/loadscr_layer01.png"))
|
||||||
|
}
|
||||||
|
CommonResourcePool.addToLoadingList("basegame-gui-loadscrlayer02") {
|
||||||
|
Texture(ModMgr.getGdxFile("basegame", "gui/loadscr_layer02.png"))
|
||||||
|
}
|
||||||
|
CommonResourcePool.addToLoadingList("basegame-gui-loadscrlayer03") {
|
||||||
|
Texture(ModMgr.getGdxFile("basegame", "gui/loadscr_layer03.png"))
|
||||||
|
}
|
||||||
|
CommonResourcePool.loadAll()
|
||||||
|
|
||||||
|
App.disposables.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override var screenToLoad: IngameInstance? = screenToBeLoaded
|
||||||
|
|
||||||
|
val ratio = worldwidth * sqrt(2.0 / (worldwidth.sqr() + worldheight.sqr())) // world size is always wider than tall
|
||||||
|
val htilesCount = worldwidth / CHUNK_W
|
||||||
|
val vtilesCount = worldheight / CHUNK_H
|
||||||
|
|
||||||
|
val unitSize = ((540 * ratio) / htilesCount).roundToInt() // (visible tilesize + gapSize)
|
||||||
|
val previewWidth = unitSize * htilesCount
|
||||||
|
val previewHeight = unitSize * vtilesCount
|
||||||
|
|
||||||
|
val xoff = (Math.random() * (1024-764)/2).toInt()
|
||||||
|
|
||||||
|
val baseTileTex = arrayOf(
|
||||||
|
CommonResourcePool.getAsTexture("basegame-gui-loadscrlayer01"),
|
||||||
|
CommonResourcePool.getAsTexture("basegame-gui-loadscrlayer02"),
|
||||||
|
CommonResourcePool.getAsTexture("basegame-gui-loadscrlayer03"),
|
||||||
|
)
|
||||||
|
|
||||||
|
val drawWidth = Toolkit.drawWidth
|
||||||
|
|
||||||
|
val imgYoff = (252 - previewHeight * 0.28f).toInt()
|
||||||
|
|
||||||
|
val tiles = baseTileTex.map {
|
||||||
|
TextureRegionPack(it, 1, imgYoff + previewHeight, 0, 0, xoff, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(delta: Float) {
|
||||||
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
||||||
|
|
||||||
|
App.batch.inUse { val it = it as FlippingSpriteBatch
|
||||||
|
val previewX = (drawWidth - previewWidth).div(2f).roundToFloat()
|
||||||
|
val previewY = (App.scr.height - previewHeight.times(1.5f)).div(2f).roundToFloat()
|
||||||
|
|
||||||
|
it.color = Color.BLACK
|
||||||
|
Toolkit.fillArea(it, previewX, previewY, previewWidth.toFloat(), previewHeight.toFloat())
|
||||||
|
|
||||||
|
// it sets the colour by itself
|
||||||
|
drawTiles(it, getStage(), getProgress(), previewX, previewY - imgYoff)
|
||||||
|
|
||||||
|
|
||||||
|
it.color = Color.WHITE
|
||||||
|
Toolkit.drawBoxBorder(it, previewX.toInt()-1, previewY.toInt()-1, previewWidth+2, previewHeight+2)
|
||||||
|
val text = messages.getHeadElem() ?: ""
|
||||||
|
App.fontGame.draw(it,
|
||||||
|
text,
|
||||||
|
(drawWidth - App.fontGame.getWidth(text)).div(2f).roundToFloat(),
|
||||||
|
previewY + previewHeight + 98 - App.fontGame.lineHeight
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
super.render(delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val totalChunkCount = (worldwidth / CHUNK_W) * (worldheight / CHUNK_H)
|
||||||
|
protected open fun getProgress(): Double {
|
||||||
|
return progress.get().toDouble() / totalChunkCount * previewWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun getStage(): Int {
|
||||||
|
return 3 // fixed value for Read screen
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val batchColour = Color(-1) // create new Color instance just for the progress bar
|
||||||
|
|
||||||
|
protected open fun drawTiles(batch: FlippingSpriteBatch, layerCount: Int, tileCount: Double, x: Float, y: Float) {
|
||||||
|
batch.color = batchColour
|
||||||
|
for (layer in 0 until layerCount) {
|
||||||
|
for (i in 0 until tileCount.ceilToInt()) {
|
||||||
|
batch.color.a = (tileCount - i).toFloat().coerceIn(0f, 1f)
|
||||||
|
batch.draw(tiles[layer].get(i, 0), x + i, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FancyWorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidth: Int, private val worldheight: Int) : FancyWorldReadLoadScreen(screenToBeLoaded, worldwidth, worldheight, {}) {
|
||||||
|
|
||||||
|
override fun getProgress(): Double {
|
||||||
|
return progress.get().toDouble() / worldwidth * previewWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStage(): Int {
|
||||||
|
return stageValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawTiles(batch: FlippingSpriteBatch, layerCount: Int, tileCount: Double, x: Float, y: Float) {
|
||||||
|
batch.color = batchColour
|
||||||
|
for (layer in 0 until layerCount) {
|
||||||
|
val isOldLayer = (layer != layerCount - 1)
|
||||||
|
for (i in 0 until if (!isOldLayer) tileCount.ceilToInt() else previewWidth) {
|
||||||
|
batch.color.a = if (!isOldLayer) (tileCount - i).toFloat().coerceIn(0f, 1f) else 1f
|
||||||
|
batch.draw(tiles[layer].get(i, 0), x + i, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -258,6 +258,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
override var gameFullyLoaded = false
|
override var gameFullyLoaded = false
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
|
override val musicGovernor = TerrarumMusicGovernor()
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
@@ -489,7 +490,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
//WorldGenerator.SEED = worldParams.worldGenSeed
|
//WorldGenerator.SEED = worldParams.worldGenSeed
|
||||||
//WorldGenerator.generateMap()
|
//WorldGenerator.generateMap()
|
||||||
Worldgen.attachMap(world, WorldgenParams(worldParams.worldGenSeed))
|
Worldgen.attachMap(world, WorldgenParams(worldParams.worldGenSeed))
|
||||||
Worldgen.generateMap()
|
Worldgen.generateMap(App.getLoadScreen())
|
||||||
|
|
||||||
|
|
||||||
historicalFigureIDBucket = ArrayList<Int>()
|
historicalFigureIDBucket = ArrayList<Int>()
|
||||||
@@ -731,7 +732,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
internal var autosaveTimer = 0f
|
internal var autosaveTimer = 0f
|
||||||
|
|
||||||
override fun render(`_`: Float) {
|
override fun render(updateRate: Float) {
|
||||||
// Q&D solution for LoadScreen and Ingame, where while LoadScreen is working, Ingame now no longer has GL Context
|
// Q&D solution for LoadScreen and Ingame, where while LoadScreen is working, Ingame now no longer has GL Context
|
||||||
// there's still things to load which needs GL context to be present
|
// there's still things to load which needs GL context to be present
|
||||||
if (!gameFullyLoaded) {
|
if (!gameFullyLoaded) {
|
||||||
@@ -756,6 +757,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
gameFullyLoaded = true
|
gameFullyLoaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.render(updateRate)
|
||||||
|
|
||||||
ingameController.update()
|
ingameController.update()
|
||||||
|
|
||||||
|
|
||||||
@@ -883,12 +886,11 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
oldSelectedWireRenderClass = selectedWireRenderClass
|
oldSelectedWireRenderClass = selectedWireRenderClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
musicGovernor.update(this, delta)
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// ui-related updates //
|
// ui-related updates //
|
||||||
////////////////////////
|
////////////////////////
|
||||||
//uiContainer.forEach { it.update(delta) }
|
|
||||||
//debugWindow.update(delta)
|
|
||||||
//notifier.update(delta)
|
|
||||||
// open/close fake blur UI according to what's opened
|
// open/close fake blur UI according to what's opened
|
||||||
if (uiInventoryPlayer.isVisible ||
|
if (uiInventoryPlayer.isVisible ||
|
||||||
getUIFixture.get()?.isVisible == true || worldTransitionOngoing) {
|
getUIFixture.get()?.isVisible == true || worldTransitionOngoing) {
|
||||||
@@ -1477,7 +1479,9 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
// resize UIs
|
// resize UIs
|
||||||
|
|
||||||
notifier.setPosition(
|
notifier.setPosition(
|
||||||
(drawWidth - notifier.width) / 2, App.scr.height - notifier.height)
|
(Toolkit.drawWidth - notifier.width) / 2,
|
||||||
|
App.scr.height - notifier.height - App.scr.tvSafeGraphicsHeight
|
||||||
|
)
|
||||||
uiQuickBar.setPosition((drawWidth - uiQuickBar.width) / 2, App.scr.tvSafeGraphicsHeight)
|
uiQuickBar.setPosition((drawWidth - uiQuickBar.width) / 2, App.scr.tvSafeGraphicsHeight)
|
||||||
|
|
||||||
// inventory
|
// inventory
|
||||||
@@ -1520,6 +1524,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
catch (e: IllegalArgumentException) {}
|
catch (e: IllegalArgumentException) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
musicGovernor.dispose()
|
||||||
|
|
||||||
super.dispose()
|
super.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
122
src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt
Normal file
122
src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.audio.Music
|
||||||
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.unicode.EMDASH
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
data class MusicContainer(
|
||||||
|
val name: String,
|
||||||
|
val file: File,
|
||||||
|
val gdxMusic: Music
|
||||||
|
) {
|
||||||
|
override fun toString() = if (name.isEmpty()) file.nameWithoutExtension else name
|
||||||
|
}
|
||||||
|
|
||||||
|
class TerrarumMusicGovernor : MusicGovernor() {
|
||||||
|
|
||||||
|
private val songs: List<MusicContainer> =
|
||||||
|
File(App.customMusicDir).listFiles()?.mapNotNull {
|
||||||
|
printdbg(this, "Music: ${it.absolutePath}")
|
||||||
|
try {
|
||||||
|
MusicContainer(
|
||||||
|
it.nameWithoutExtension.replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" "),
|
||||||
|
it,
|
||||||
|
Gdx.audio.newMusic(Gdx.files.absolute(it.absolutePath)).also {
|
||||||
|
it.setOnCompletionListener {
|
||||||
|
stopMusic()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
catch (e: GdxRuntimeException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} ?: emptyList() // TODO test code
|
||||||
|
|
||||||
|
private var musicBin: ArrayList<Int> = ArrayList(songs.indices.toList().shuffled())
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
songs.forEach {
|
||||||
|
App.disposables.add(it.gdxMusic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private var warningPrinted = false
|
||||||
|
|
||||||
|
|
||||||
|
private val STATE_INIT = 0
|
||||||
|
private val STATE_FIREPLAY = 1
|
||||||
|
private val STATE_PLAYING = 2
|
||||||
|
private val STATE_INTERMISSION = 3
|
||||||
|
|
||||||
|
|
||||||
|
private fun stopMusic() {
|
||||||
|
AudioManager.stopMusic()
|
||||||
|
state = STATE_INTERMISSION
|
||||||
|
intermissionAkku = 0f
|
||||||
|
intermissionLength = 30f + 30f * Math.random().toFloat() // 30s-60s
|
||||||
|
musicFired = false
|
||||||
|
printdbg(this, "Intermission: $intermissionLength seconds")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startMusic(song: MusicContainer) {
|
||||||
|
AudioManager.startMusic(song)
|
||||||
|
printdbg(this, "Now playing: $song")
|
||||||
|
INGAME.sendNotification("Now Playing $EMDASH ${song.name}")
|
||||||
|
state = STATE_PLAYING
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun update(ingame: IngameInstance, delta: Float) {
|
||||||
|
if (songs.isEmpty()) {
|
||||||
|
if (!warningPrinted) {
|
||||||
|
warningPrinted = true
|
||||||
|
printdbg(this, "Warning: songs list is empty")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// val ingame = ingame as TerrarumIngame
|
||||||
|
if (state == 0) state = STATE_INTERMISSION
|
||||||
|
|
||||||
|
|
||||||
|
when (state) {
|
||||||
|
STATE_FIREPLAY -> {
|
||||||
|
if (!musicFired) {
|
||||||
|
musicFired = true
|
||||||
|
|
||||||
|
val song = songs[musicBin.removeAt(0)]
|
||||||
|
// prevent same song to play twice
|
||||||
|
if (musicBin.isEmpty()) {
|
||||||
|
musicBin = ArrayList(songs.indices.toList().shuffled())
|
||||||
|
}
|
||||||
|
|
||||||
|
startMusic(song)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STATE_PLAYING -> {
|
||||||
|
// stopMusic() will be called when the music finishes; it's on the setOnCompletionListener
|
||||||
|
}
|
||||||
|
STATE_INTERMISSION -> {
|
||||||
|
intermissionAkku += delta
|
||||||
|
|
||||||
|
if (intermissionAkku >= intermissionLength) {
|
||||||
|
intermissionAkku = 0f
|
||||||
|
state = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
stopMusic()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -175,6 +175,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
printdbg(this, "Demo world not found, using empty world")
|
printdbg(this, "Demo world not found, using empty world")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
demoWorld.renumberTilesAfterLoad()
|
||||||
this.world = demoWorld
|
this.world = demoWorld
|
||||||
|
|
||||||
// set initial time to summer
|
// set initial time to summer
|
||||||
@@ -301,6 +302,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
private var introUncoverDeltaCounter = 0f
|
private var introUncoverDeltaCounter = 0f
|
||||||
|
|
||||||
override fun render(updateRate: Float) {
|
override fun render(updateRate: Float) {
|
||||||
|
super.render(updateRate)
|
||||||
// async update and render
|
// async update and render
|
||||||
gameUpdateGovernor.update(Gdx.graphics.deltaTime, App.UPDATE_RATE, updateScreen, renderScreen)
|
gameUpdateGovernor.update(Gdx.graphics.deltaTime, App.UPDATE_RATE, updateScreen, renderScreen)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame
|
||||||
|
|
||||||
|
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.ui.*
|
||||||
|
import net.torvald.terrarum.ui.UIItemTextButtonList.Companion.DEFAULT_BACKGROUNDCOL
|
||||||
|
import net.torvald.terrarum.ui.UINSMenu.Companion.LINE_HEIGHT
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
class UIBuildingMakerGetFilename : UICanvas() {
|
||||||
|
|
||||||
|
var confirmCallback: (String) -> Unit = {}
|
||||||
|
var cancelCallback: () -> Unit = {}
|
||||||
|
var title = "Export"
|
||||||
|
var text = listOf("")
|
||||||
|
|
||||||
|
var labelDo = "OK"
|
||||||
|
var labelDont = "Cancel"
|
||||||
|
|
||||||
|
override var width = 280
|
||||||
|
override var height = 160
|
||||||
|
|
||||||
|
private val textWidth = width - LINE_HEIGHT
|
||||||
|
private val buttonWidth = 101
|
||||||
|
private val buttonGap = (width - buttonWidth*2) / 3
|
||||||
|
|
||||||
|
override var openCloseTime = OPENCLOSE_GENERIC
|
||||||
|
|
||||||
|
val textInput = UIItemTextLineInput(
|
||||||
|
this,
|
||||||
|
(width - textWidth) / 2,
|
||||||
|
LINE_HEIGHT * (text.size + 2),
|
||||||
|
textWidth,
|
||||||
|
{ "The Yucky Panopticon" },
|
||||||
|
InputLenCap(250, InputLenCap.CharLenUnit.UTF8_BYTES)
|
||||||
|
)
|
||||||
|
|
||||||
|
val buttonOk = UIItemTextButton(
|
||||||
|
this,
|
||||||
|
{ labelDo },
|
||||||
|
buttonGap,
|
||||||
|
height - LINE_HEIGHT - LINE_HEIGHT/2,
|
||||||
|
buttonWidth
|
||||||
|
).also {
|
||||||
|
it.clickOnceListener = { _, _ ->
|
||||||
|
|
||||||
|
textInput.getTextOrPlaceholder().let { name ->
|
||||||
|
if (name.isNotBlank())
|
||||||
|
confirmCallback(name.trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setAsClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val buttonCancel = UIItemTextButton(
|
||||||
|
this,
|
||||||
|
{ labelDont },
|
||||||
|
width - buttonWidth - buttonGap,
|
||||||
|
height - LINE_HEIGHT - LINE_HEIGHT/2,
|
||||||
|
buttonWidth
|
||||||
|
).also {
|
||||||
|
it.clickOnceListener = { _, _ ->
|
||||||
|
reset()
|
||||||
|
cancelCallback()
|
||||||
|
this.setAsClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
textInput.clearText()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
addUIitem(textInput)
|
||||||
|
addUIitem(buttonOk)
|
||||||
|
addUIitem(buttonCancel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
uiItems.forEach { it.update(delta) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) {
|
||||||
|
blendNormalStraightAlpha(batch)
|
||||||
|
|
||||||
|
// draw border
|
||||||
|
batch.color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawBoxBorder(batch, -1, -1 - LINE_HEIGHT, width + 2, height + LINE_HEIGHT + 2)
|
||||||
|
|
||||||
|
// draw title bar
|
||||||
|
batch.color = UINSMenu.DEFAULT_TITLEBACKCOL
|
||||||
|
Toolkit.fillArea(batch, 0, 0 - LINE_HEIGHT, width, LINE_HEIGHT)
|
||||||
|
|
||||||
|
batch.color = UINSMenu.DEFAULT_TITLETEXTCOL
|
||||||
|
App.fontGame.draw(batch, title, UINSMenu.TEXT_OFFSETX + 0, UINSMenu.TEXT_OFFSETY + 0 - LINE_HEIGHT)
|
||||||
|
|
||||||
|
// draw the back
|
||||||
|
batch.color = DEFAULT_BACKGROUNDCOL
|
||||||
|
Toolkit.fillArea(batch, 0, 0, width, height)
|
||||||
|
|
||||||
|
|
||||||
|
// draw the list
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
val textWidth: Int = text.maxOf { App.fontGame.getWidth(it) }
|
||||||
|
|
||||||
|
text.forEachIndexed { index, str ->
|
||||||
|
App.fontGame.draw(batch, str, 0 + LINE_HEIGHT / 2, 0 + LINE_HEIGHT / 2 + LINE_HEIGHT * index)
|
||||||
|
}
|
||||||
|
|
||||||
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var dragOriginX = 0 // relative mousepos
|
||||||
|
private var dragOriginY = 0 // relative mousepos
|
||||||
|
private var dragForReal = false
|
||||||
|
|
||||||
|
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
|
||||||
|
if (mouseInScreen(screenX, screenY)) {
|
||||||
|
if (dragForReal) {
|
||||||
|
handler.setPosition(
|
||||||
|
(screenX / App.scr.magn - dragOriginX).roundToInt(),
|
||||||
|
(screenY / App.scr.magn - dragOriginY).roundToInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uiItems.forEach { it.touchDragged(screenX, screenY, pointer) }
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun mouseOnTitleBar() =
|
||||||
|
relativeMouseX in 0 until width && relativeMouseY in -LINE_HEIGHT until 0
|
||||||
|
|
||||||
|
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
|
if (mouseOnTitleBar()) {
|
||||||
|
dragOriginX = relativeMouseX
|
||||||
|
dragOriginY = relativeMouseY
|
||||||
|
dragForReal = true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dragForReal = false
|
||||||
|
}
|
||||||
|
|
||||||
|
uiItems.forEach { it.touchDown(screenX, screenY, pointer, button) }
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
uiItems.forEach { it.tryDispose() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,7 +57,7 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(delta: Float) {
|
override fun render(delta: Float) {
|
||||||
gdxClearAndEnableBlend(.094f, .094f, .094f, 0f)
|
gdxClearAndEnableBlend(.063f, .070f, .086f, 1f)
|
||||||
|
|
||||||
val drawWidth = Toolkit.drawWidth
|
val drawWidth = Toolkit.drawWidth
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user