mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 16:44:05 +09:00
Compare commits
80 Commits
v0.3.2-tes
...
v0.3.2-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
453459e3b6 | ||
|
|
bad72dd353 | ||
|
|
13185f0565 | ||
|
|
fcaf4c97f1 | ||
|
|
9c396e7b8d | ||
|
|
afb7dff5d2 | ||
|
|
5d0514040c | ||
|
|
7c1806946b | ||
|
|
e5e02681b8 | ||
|
|
6db3baf691 | ||
|
|
07cbcbe79b | ||
|
|
57a9f7febc | ||
|
|
16cfaaea27 | ||
|
|
72c742897e | ||
|
|
23af64deb4 | ||
|
|
bb017fa9b7 | ||
|
|
1745bb16db | ||
|
|
370583d1af | ||
|
|
66b651c627 | ||
|
|
c5874a7f3d | ||
|
|
057905c3b7 | ||
|
|
2b50562002 | ||
|
|
73a8198378 | ||
|
|
1ef479124e | ||
|
|
e5e8028b3f | ||
|
|
739b51af95 | ||
|
|
f9f49ab63c | ||
|
|
a497463349 | ||
|
|
253db56c4f | ||
|
|
3d13941060 | ||
|
|
592e489411 | ||
|
|
49b2011ea0 | ||
|
|
61e6255b52 | ||
|
|
2e956f89f5 | ||
|
|
e8ffd1f844 | ||
|
|
0882145f9c | ||
|
|
28e2179e44 | ||
|
|
48eb1ffd8f | ||
|
|
6daccb2e62 | ||
|
|
8c9d5a26fb | ||
|
|
ee3e5b14cd | ||
|
|
5c39df9080 | ||
|
|
5d77694316 | ||
|
|
cf111d2507 | ||
|
|
724ace3f00 | ||
|
|
1457cbffb3 | ||
|
|
7a42066392 | ||
|
|
528b975350 | ||
|
|
9e9064dd55 | ||
|
|
138c6d22d2 | ||
|
|
a33f0e7ab4 | ||
|
|
93c427473d | ||
|
|
6b8798a19e | ||
|
|
376595d7cd | ||
|
|
4cc52b5585 | ||
|
|
0ff71f39fe | ||
|
|
13f487a562 | ||
|
|
0599ce91b1 | ||
|
|
3d5fd984d7 | ||
|
|
8d0d84fbf8 | ||
|
|
eb2c716691 | ||
|
|
ac53f821e2 | ||
|
|
cd6df71347 | ||
|
|
ac553ed156 | ||
|
|
8c5c986cbf | ||
|
|
a0f597865e | ||
|
|
bafd0d9f7c | ||
|
|
e259fc2f3b | ||
|
|
ebbb121b8c | ||
|
|
331e89b4df | ||
|
|
98a6c9ae70 | ||
|
|
1646871ddf | ||
|
|
76bfc0fde4 | ||
|
|
ef6f39632d | ||
|
|
a3ecd4a4f4 | ||
|
|
065f80224f | ||
|
|
34fb046968 | ||
|
|
43da6cc5d8 | ||
|
|
fccc2162f6 | ||
|
|
c554df9b98 |
24
.idea/artifacts/TerrarumBuild.xml
generated
24
.idea/artifacts/TerrarumBuild.xml
generated
@@ -13,6 +13,10 @@
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-controllers-desktop-2.2.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/GetCpuName.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jxinput-1.0.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk7.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk8.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/commons-csv-1.8.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/prtree.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/Terrarum_Joise.jar" path-in-jar="/" />
|
||||
@@ -72,21 +76,17 @@
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-platform-1.11.0-natives-armeabi-v7a.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-platform-1.11.0-natives-desktop.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-platform-1.11.0-natives-x86_64.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.8.21/kotlin-stdlib-1.8.21.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.21/kotlin-stdlib-common-1.8.21.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test/1.8.21/kotlin-test-1.8.21.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.8.21/kotlin-reflect-1.8.21.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk8.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk7.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/graal-sdk-22.3.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/icu4j-71.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/js-22.3.1-edit.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.8.21/kotlin-stdlib-1.8.21.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.21/kotlin-stdlib-common-1.8.21.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-test/1.8.21/kotlin-test-1.8.21.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/js-scriptengine-22.3.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/regex-22.3.1-edit.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/truffle-api-22.3.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/icu4j-71.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/regex-22.3.1-edit.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/js-22.3.1-edit.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/graal-sdk-22.3.1.jar" path-in-jar="/" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
14
.idea/libraries/io_github_classgraph.xml
generated
Normal file
14
.idea/libraries/io_github_classgraph.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<component name="libraryTable">
|
||||
<library name="io.github.classgraph" type="repository">
|
||||
<properties maven-id="io.github.classgraph:classgraph:4.8.157" />
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/classgraph-4.8.157.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$PROJECT_DIR$/lib/classgraph-4.8.157-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/classgraph-4.8.157-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
19
.idea/runConfigurations/Principii.xml
generated
Normal file
19
.idea/runConfigurations/Principii.xml
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Principii" type="Application" factoryName="Application" nameIsGenerated="true">
|
||||
<option name="MAIN_CLASS_NAME" value="net.torvald.terrarum.Principii" />
|
||||
<module name="TerrarumBuild" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="net.torvald.terrarum.*" />
|
||||
<option name="ENABLED" value="true" />
|
||||
</pattern>
|
||||
</extension>
|
||||
<method v="2">
|
||||
<option name="BuildArtifacts" enabled="true">
|
||||
<artifact name="ModuleComputers" />
|
||||
<artifact name="TerrarumBuild" />
|
||||
</option>
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -16,5 +16,6 @@
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" name="jetbrains.kotlin.reflect" level="project" />
|
||||
<orderEntry type="library" name="jetbrains.kotlin.test" level="project" />
|
||||
<orderEntry type="library" name="io.github.classgraph" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -195,17 +195,10 @@ internal class UIHomeComputer : UICanvas(
|
||||
}
|
||||
|
||||
override fun doOpening(delta: Float) {
|
||||
super.doOpening(delta)
|
||||
fixture.startVM()
|
||||
}
|
||||
|
||||
override fun doClosing(delta: Float) {
|
||||
}
|
||||
|
||||
override fun endOpening(delta: Float) {
|
||||
}
|
||||
|
||||
override fun endClosing(delta: Float) {
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
fbo.dispose()
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
<orderEntry type="library" name="badlogicgames.gdx.backend.lwjgl3" level="project" />
|
||||
<orderEntry type="library" name="jetbrains.kotlin.reflect" level="project" />
|
||||
<orderEntry type="library" name="jetbrains.kotlin.test" level="project" />
|
||||
<orderEntry type="library" name="io.github.classgraph" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
BIN
assets/graphics/gui/apple_rosetta_warning.tga
LFS
Normal file
BIN
assets/graphics/gui/apple_rosetta_warning.tga
LFS
Normal file
Binary file not shown.
BIN
assets/graphics/gui/hrule.tga
LFS
Normal file
BIN
assets/graphics/gui/hrule.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
@@ -7,12 +7,10 @@
|
||||
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
||||
"MENU_MODULES" : "Modules",
|
||||
"MENU_CREDIT_GPL_DNT" : "GPL",
|
||||
"MENU_LABEL_JVM_DNT" : "JVM",
|
||||
"GAME_ACTION_MOVE_VERB" : "Move",
|
||||
"GAME_ACTION_ZOOM" : "Zoom",
|
||||
"MENU_LABEL_RESET" : "Reset",
|
||||
"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_WARNING3": "https://www.java.com/en/download/",
|
||||
"MENU_OPTION_STREAMERS_LAYOUT": "Chat Overlay",
|
||||
"MENU_LABEL_RESTART_REQUIRED": "Restart Required",
|
||||
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
||||
@@ -21,10 +19,19 @@
|
||||
"MENU_OPTIONS_BLUR": "Blur",
|
||||
"MENU_OPTIONS_PARTICLES": "Particles",
|
||||
"MENU_IO_IMPORT": "Import",
|
||||
"APP_NOMODULE_1": "No Module is currently loaded.",
|
||||
"APP_NOMODULE_2": "Please configure your Load Order and restart:",
|
||||
"MENU_LABEL_KEYCONFIG_HELP1": "Click On the Keycap to Assign Actions",
|
||||
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Cliboard",
|
||||
"MENU_OPTIONS_PERFORMANCE": "Performance"
|
||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
||||
"MENU_OPTIONS_PERFORMANCE": "Performance",
|
||||
"MENU_LABEL_DELETE": "Delete",
|
||||
"MENU_OPTIONS_JVM_HEAP_MAX": "Max Heap Memory",
|
||||
"MENU_OPTIONS_AUTOSAVE": "Autosave",
|
||||
"CONTEXT_TIME_MINUTE_PLURAL": "Minutes",
|
||||
"CONTEXT_TIME_SECOND_PLURAL": "Seconds",
|
||||
"MENU_LABEL_SYSTEM_INFO": "System Info",
|
||||
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "Show notification for",
|
||||
"MENU_LABEL_STREAMING": "Livestreaming",
|
||||
"MENU_LABEL_EXTRA_JVM_ARGUMENTS": "Extra Arguments",
|
||||
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
||||
"MENU_IO_AUTOSAVE": "Autosave",
|
||||
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console"
|
||||
}
|
||||
16
assets/locales/en/terrarum_sentences.json
Normal file
16
assets/locales/en/terrarum_sentences.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"GAME_32BIT_WARNING1": "32비트 버전의 Java를 사용중인 것 같습니다.",
|
||||
"GAME_32BIT_WARNING2": "아래 링크에서 최신 64비트 Java를 내려받아 설치해주세요.",
|
||||
"GAME_32BIT_WARNING3": "https://www.java.com/ko/download/",
|
||||
"GAME_APPLE_ROSETTA_WARNING1": "Apple Silicon이 탑재된 Mac을 사용 중이지만 x86 빌드의 게임을 실행 중입니다.",
|
||||
"GAME_APPLE_ROSETTA_WARNING2": "최적의 성능과 게임 경험을 위해 Apple Silicon용 빌드의 게임을 이용해 주십시오.",
|
||||
"APP_NOMODULE_1": "현재 불러와진 모듈이 없습니다.",
|
||||
"APP_NOMODULE_2": "다음의 파일에서 불러오기 순서를 설정하고 게임을 재시작하십시오.",
|
||||
"MENU_LABEL_KEYCONFIG_HELP1": "키캡을 클릭해 컨트롤을 배정하십시오",
|
||||
"GAME_PREV_SAVE_WAS_LOADED1": "가장 최근에 저장된 게임이 손상되었습니다.",
|
||||
"GAME_PREV_SAVE_WAS_LOADED2": "이전에 저장된 게임을 불러왔습니다.",
|
||||
"GAME_MORE_RECENT_AUTOSAVE1": "자동 저장된 게임이 수동으로 저장한 게임보다 더 최신입니다.",
|
||||
"GAME_MORE_RECENT_AUTOSAVE2": "불러올 게임을 선택해 주십시오.",
|
||||
"MENU_LABEL_SAVE_WILL_BE_DELETED": "선택된 세이브가 삭제됩니다.",
|
||||
"MENU_LABEL_UNSAVED_PROGRESSES_WILL_BE_LOST": "저장하지 않은 변동사항을 잃게 됩니다."
|
||||
}
|
||||
@@ -2335,7 +2335,7 @@
|
||||
},
|
||||
{
|
||||
"n": "MENU_OPTIONS",
|
||||
"s": "Stillingar "
|
||||
"s": "Valkostir "
|
||||
},
|
||||
{
|
||||
"n": "MENU_OPTIONS_ADVANCEDGRAPHICS",
|
||||
@@ -2395,11 +2395,11 @@
|
||||
},
|
||||
{
|
||||
"n": "MENU_OPTIONS_GAMEPLAY",
|
||||
"s": "Gameplay Options"
|
||||
"s": "Leikvalkostir"
|
||||
},
|
||||
{
|
||||
"n": "MENU_OPTIONS_GRAPHICS",
|
||||
"s": "Grafíkstillingar"
|
||||
"s": "Grafíkvalkostir"
|
||||
},
|
||||
{
|
||||
"n": "MENU_OPTIONS_HUD",
|
||||
|
||||
@@ -15,5 +15,15 @@
|
||||
"MENU_OPTIONS_DITHER": "Dither",
|
||||
"MENU_OPTIONS_BLUR": "Óskýrt",
|
||||
"MENU_OPTIONS_PARTICLES": "Eind",
|
||||
"MENU_IO_IMPORT": "Flytja inn"
|
||||
"MENU_IO_IMPORT": "Flytja inn",
|
||||
"APP_NOMODULE_1": "Engin eining er hlaðin eins og er.",
|
||||
"APP_NOMODULE_2": "Vinsamlega stilltu hleðslupöntunina þína og endurræstu:",
|
||||
"MENU_LABEL_KEYCONFIG_HELP1": "Smelltu á lyklalokið til að úthluta aðgerðum",
|
||||
"MENU_LABEL_IME_TOGGLE": "Breyttu IME",
|
||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Límdu frá klemmuspjald",
|
||||
"MENU_OPTIONS_PERFORMANCE": "Afköst",
|
||||
"MENU_LABEL_DELETE": "Eyða",
|
||||
"MENU_OPTIONS_JVM_HEAP_MAX": "Hámarks hrúguminni",
|
||||
"MENU_OPTIONS_AUTOSAVE": "Sjálfvirk vistun",
|
||||
"CONTEXT_TIME_MINUTE_PLURAL": "Mínútur"
|
||||
}
|
||||
@@ -6,12 +6,11 @@
|
||||
"APP_WARNING_HEALTH_AND_SAFETY": "경고—건강과 안전을 위하여",
|
||||
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
||||
"MENU_MODULES" : "모듈",
|
||||
|
||||
|
||||
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
||||
"GAME_ACTION_ZOOM" : "확대·축소",
|
||||
"MENU_LABEL_RESET" : "재설정",
|
||||
"GAME_32BIT_WARNING1": "32비트 버전의 Java를 사용중인 것 같습니다.",
|
||||
"GAME_32BIT_WARNING2": "아래 링크에서 최신 64비트 Java를 내려받아 설치해주세요.",
|
||||
"GAME_32BIT_WARNING3": "https://www.java.com/ko/download/",
|
||||
"MENU_OPTION_STREAMERS_LAYOUT": "채팅창 오버레이",
|
||||
"MENU_LABEL_RESTART_REQUIRED": "재시작 필요",
|
||||
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
||||
@@ -20,10 +19,19 @@
|
||||
"MENU_OPTIONS_BLUR": "흐림",
|
||||
"MENU_OPTIONS_PARTICLES": "입자 수",
|
||||
"MENU_IO_IMPORT": "가져오기",
|
||||
"APP_NOMODULE_1": "현재 불러와진 모듈이 없습니다.",
|
||||
"APP_NOMODULE_2": "다음의 파일에서 불러오기 순서를 설정하고 게임을 재시작하십시오.",
|
||||
"MENU_LABEL_KEYCONFIG_HELP1": "키캡을 클릭해 컨트롤을 배정하십시오",
|
||||
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
||||
"MENU_OPTIONS_PERFORMANCE": "성능"
|
||||
"MENU_OPTIONS_PERFORMANCE": "성능",
|
||||
"MENU_LABEL_DELETE": "삭제",
|
||||
"MENU_OPTIONS_JVM_HEAP_MAX": "최대 힙 메모리",
|
||||
"MENU_OPTIONS_AUTOSAVE": "자동 저장",
|
||||
"CONTEXT_TIME_MINUTE_PLURAL": "분",
|
||||
"CONTEXT_TIME_SECOND_PLURAL": "초",
|
||||
"MENU_LABEL_SYSTEM_INFO": "시스템 정보",
|
||||
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "알림 표시 시간",
|
||||
"MENU_LABEL_STREAMING": "실시간 방송",
|
||||
"MENU_LABEL_EXTRA_JVM_ARGUMENTS": "추가 명령 인수",
|
||||
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
||||
"MENU_IO_AUTOSAVE": "자동 저장",
|
||||
"MENU_OPTIONS_DEBUG_CONSOLE": "디버그 콘솔"
|
||||
}
|
||||
|
||||
15
assets/locales/koKR/terrarum_sentences.json
Normal file
15
assets/locales/koKR/terrarum_sentences.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"GAME_32BIT_WARNING1": "32비트 버전의 Java를 사용중인 것 같습니다.",
|
||||
"GAME_32BIT_WARNING2": "아래 링크에서 최신 64비트 Java를 내려받아 설치해주세요.",
|
||||
"GAME_32BIT_WARNING3": "https://www.java.com/ko/download/",
|
||||
"GAME_APPLE_ROSETTA_WARNING1": "Apple Silicon이 탑재된 Mac을 사용 중이지만 x86 빌드의 게임을 실행 중입니다.",
|
||||
"GAME_APPLE_ROSETTA_WARNING2": "최적의 성능과 게임 경험을 위해 Apple Silicon용 빌드의 게임을 이용해 주십시오.",
|
||||
"APP_NOMODULE_1": "현재 불러와진 모듈이 없습니다.",
|
||||
"APP_NOMODULE_2": "다음의 파일에서 불러오기 순서를 설정하고 게임을 재시작하십시오.",
|
||||
"MENU_LABEL_KEYCONFIG_HELP1": "키캡을 클릭해 컨트롤을 배정하십시오",
|
||||
"GAME_PREV_SAVE_WAS_LOADED1": "가장 최근에 저장된 게임이 손상되었습니다.",
|
||||
"GAME_PREV_SAVE_WAS_LOADED2": "이전에 저장된 게임을 불러왔습니다.",
|
||||
"GAME_MORE_RECENT_AUTOSAVE1": "자동 저장된 게임이 수동으로 저장한 게임보다 더 최신입니다.",
|
||||
"GAME_MORE_RECENT_AUTOSAVE2": "불러올 게임을 선택해 주십시오.",
|
||||
"MENU_LABEL_SAVE_WILL_BE_DELETED": "선택된 세이브가 삭제됩니다."
|
||||
}
|
||||
BIN
assets/mods/basegame/gui/backdrop01.tga
LFS
Normal file
BIN
assets/mods/basegame/gui/backdrop01.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
@@ -14,4 +14,6 @@ id;classname
|
||||
258;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorBirch
|
||||
259;net.torvald.terrarum.modulebasegame.gameitems.ItemSwingingDoorRosewood
|
||||
|
||||
320;net.torvald.terrarum.modulebasegame.gameitems.ItemWorldPortal
|
||||
|
||||
999999;net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -16,5 +16,8 @@
|
||||
"GAME_ACTION_QUICKSEL": "Quick Select",
|
||||
"GAME_ACTION_CRAFT": "Craft",
|
||||
"GAME_CRAFTING": "Crafting",
|
||||
"GAME_CRAFTABLE_ITEMS": "Craftable Items"
|
||||
"GAME_CRAFTABLE_ITEMS": "Craftable Items",
|
||||
"MENU_LABEL_RENAME": "Rename",
|
||||
"GAME_ACTION_TELEPORT": "Teleport",
|
||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing."
|
||||
}
|
||||
@@ -17,5 +17,8 @@
|
||||
"GAME_ACTION_QUICKSEL": "빠른 선택",
|
||||
"GAME_ACTION_CRAFT": "제작하기",
|
||||
"GAME_CRAFTING": "제작",
|
||||
"GAME_CRAFTABLE_ITEMS": "제작 가능한 아이템"
|
||||
"GAME_CRAFTABLE_ITEMS": "제작 가능한 아이템",
|
||||
"MENU_LABEL_RENAME": "이름 바꾸기",
|
||||
"GAME_ACTION_TELEPORT": "텔레포트하기",
|
||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다."
|
||||
}
|
||||
BIN
assets/mods/basegame/sprites/fixtures/portal_device.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/fixtures/portal_device.tga
LFS
Normal file
Binary file not shown.
@@ -1,11 +1,11 @@
|
||||
id;drop;name;renderclass;accept;inputcount;inputtype;outputtype;javaclass;inventoryimg;branching
|
||||
8192;8192;WIRE_RED;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items16,1,9;1
|
||||
8193;8193;WIRE_GREEN;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items16,1,10;1
|
||||
8194;8194;WIRE_BLUE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items16,1,11;1
|
||||
#8195;8195;WIRE_BUNDLE;signal;digital_3bits;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items16,1,2;1
|
||||
8196;8196;WIRE_POWER_LOW;power;power_low;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items16,2,9;1
|
||||
8197;8197;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items16,3,9;1
|
||||
8198;8198;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items16,4,9;1
|
||||
8192;8192;WIRE_RED;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,4;1
|
||||
8193;8193;WIRE_GREEN;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,1,4;1
|
||||
8194;8194;WIRE_BLUE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,2,4;1
|
||||
#8195;8195;WIRE_BUNDLE;signal;digital_3bits;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,0;1
|
||||
8196;8196;WIRE_POWER_LOW;power;power_low;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,3,4;1
|
||||
8197;8197;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,4,4;1
|
||||
8198;8198;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,5,4;1
|
||||
|
||||
|
||||
# accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka not wires)
|
||||
|
||||
|
BIN
assets/mods/dwarventech/items/items.tga
LFS
Normal file
BIN
assets/mods/dwarventech/items/items.tga
LFS
Normal file
Binary file not shown.
@@ -23,12 +23,13 @@ cp $SRCFILES/AppRun $DESTDIR/AppRun
|
||||
chmod +x $DESTDIR/AppRun
|
||||
|
||||
# Copy over a Java runtime
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/
|
||||
mkdir $DESTDIR/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||
|
||||
# Copy over all the assets and a jarfile
|
||||
cp -r "../assets_release" $DESTDIR/
|
||||
mv $DESTDIR/assets_release $DESTDIR/assets
|
||||
cp -r "../out/TerrarumBuild.jar" $DESTDIR/assets/
|
||||
cp "../out/TerrarumBuild.jar" $DESTDIR/out/
|
||||
|
||||
# Pack everything to AppImage
|
||||
ARCH=arm_aarch64 "./$APPIMAGETOOL" $DESTDIR "out/$DESTDIR.AppImage" || { echo 'Building AppImage failed' >&2; exit 1; }
|
||||
|
||||
@@ -23,12 +23,13 @@ cp $SRCFILES/AppRun $DESTDIR/AppRun
|
||||
chmod +x $DESTDIR/AppRun
|
||||
|
||||
# Copy over a Java runtime
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/
|
||||
mkdir $DESTDIR/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||
|
||||
# Copy over all the assets and a jarfile
|
||||
cp -r "../assets_release" $DESTDIR/
|
||||
mv $DESTDIR/assets_release $DESTDIR/assets
|
||||
cp -r "../out/TerrarumBuild.jar" $DESTDIR/assets/
|
||||
cp "../out/TerrarumBuild.jar" $DESTDIR/out/
|
||||
|
||||
# Pack everything to AppImage
|
||||
"./$APPIMAGETOOL" $DESTDIR "out/$DESTDIR.AppImage" || { echo 'Building AppImage failed' >&2; exit 1; }
|
||||
|
||||
@@ -25,11 +25,12 @@ cp $SRCFILES/Terrarum.sh $DESTDIR/Contents/MacOS/
|
||||
chmod +x $DESTDIR/Contents/MacOS/Terrarum.sh
|
||||
|
||||
# Copy over a Java runtime
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/
|
||||
mkdir $DESTDIR/Contents/MacOS/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
# Copy over all the assets and a jarfile
|
||||
cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
||||
mv $DESTDIR/Contents/MacOS/assets_release $DESTDIR/Contents/MacOS/assets
|
||||
cp -r "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/assets/
|
||||
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
echo "Build successful: $DESTDIR"
|
||||
|
||||
@@ -25,11 +25,12 @@ cp $SRCFILES/Terrarum.sh $DESTDIR/Contents/MacOS/
|
||||
chmod +x $DESTDIR/Contents/MacOS/Terrarum.sh
|
||||
|
||||
# Copy over a Java runtime
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/
|
||||
mkdir $DESTDIR/Contents/MacOS/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
# Copy over all the assets and a jarfile
|
||||
cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
||||
mv $DESTDIR/Contents/MacOS/assets_release $DESTDIR/Contents/MacOS/assets
|
||||
cp -r "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/assets/
|
||||
cp "../out/TerrarumBuild.jar" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
echo "Build successful: $DESTDIR"
|
||||
|
||||
@@ -16,15 +16,21 @@ rm -rf $DESTDIR || true
|
||||
mkdir $DESTDIR
|
||||
|
||||
# Prepare an application
|
||||
cp $SRCFILES/Terrarum.bat $DESTDIR/
|
||||
if ! command -v x86_64-w64-mingw32-gcc &> /dev/null
|
||||
then
|
||||
echo 'Mingw32 not found; please install mingw64-cross-gcc (or similar) to your system' >&2; exit 1;
|
||||
fi
|
||||
|
||||
x86_64-w64-mingw32-gcc -o $DESTDIR/Terrarum.exe $SRCFILES/Terrarum.c || { echo 'Building EXE failed' >&2; exit 1; }
|
||||
|
||||
# Copy over a Java runtime
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/
|
||||
mkdir $DESTDIR/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||
|
||||
# Copy over all the assets and a jarfile
|
||||
cp -r "../assets_release" $DESTDIR/
|
||||
mv $DESTDIR/assets_release $DESTDIR/assets
|
||||
cp -r "../out/TerrarumBuild.jar" $DESTDIR/assets/
|
||||
cp "../out/TerrarumBuild.jar" $DESTDIR/out/
|
||||
|
||||
# Temporary solution: zip everything
|
||||
zip -r -9 -l "out/TerrarumWindows.x86.zip" $DESTDIR
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd "${0%/*}"
|
||||
./runtime-linux-arm/bin/java -Xms1G -Xmx6G -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./assets/TerrarumBuild.jar
|
||||
./out/runtime-linux-arm/bin/java -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./out/TerrarumBuild.jar
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd "${0%/*}"
|
||||
./runtime-linux-x86/bin/java -Xms1G -Xmx6G -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./assets/TerrarumBuild.jar
|
||||
./out/runtime-linux-x86/bin/java -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./out/TerrarumBuild.jar
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd "${0%/*}"
|
||||
./runtime-osx-arm/bin/java -XstartOnFirstThread -Xms1G -Xmx6G -jar ./assets/TerrarumBuild.jar
|
||||
./out/runtime-osx-arm/bin/java -jar ./out/TerrarumBuild.jar
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd "${0%/*}"
|
||||
./runtime-osx-x86/bin/java -XstartOnFirstThread -Xms1G -Xmx6G -jar ./assets/TerrarumBuild.jar
|
||||
./out/runtime-osx-x86/bin/java -jar ./out/TerrarumBuild.jar
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
cd /D "%~dp0"
|
||||
.\runtime-windows-x86\bin\java -Xms1G -Xmx6G -jar .\assets\TerrarumBuild.jar
|
||||
6
buildapp/terrarumwindows_x86/Terrarum.c
Normal file
6
buildapp/terrarumwindows_x86/Terrarum.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
return system(".\\out\\runtime-windows-x86\\bin\\java -jar .\\out\\TerrarumBuild.jar");
|
||||
}
|
||||
Binary file not shown.
BIN
lib/android-lint/common-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/common-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/guava-31.0.1-jre.jar
LFS
Normal file
BIN
lib/android-lint/guava-31.0.1-jre.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/intellij-core-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/intellij-core-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/kotlin-compiler-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/kotlin-compiler-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/kxml2-2.3.0.jar
LFS
Normal file
BIN
lib/android-lint/kxml2-2.3.0.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/layoutlib-api-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/layoutlib-api-31.0.1.jar
LFS
Normal file
Binary file not shown.
127
lib/android-lint/lint-31.0.1.pom
Normal file
127
lib/android-lint/lint-31.0.1.pom
Normal file
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.android.tools.lint</groupId>
|
||||
<artifactId>lint</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<name>com.android.tools.lint.lint</name>
|
||||
<description>Lint tools. Both a Command line tool and a library to add lint features to other tools</description>
|
||||
<url>http://tools.android.com/</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<name>The Android Open Source Project</name>
|
||||
</developer>
|
||||
</developers>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.lint</groupId>
|
||||
<artifactId>lint-api</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.lint</groupId>
|
||||
<artifactId>lint-checks</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.external.com-intellij</groupId>
|
||||
<artifactId>intellij-core</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.external.com-intellij</groupId>
|
||||
<artifactId>kotlin-compiler</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.external.org-jetbrains</groupId>
|
||||
<artifactId>uast</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.analytics-library</groupId>
|
||||
<artifactId>protos</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.analytics-library</groupId>
|
||||
<artifactId>shared</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.analytics-library</groupId>
|
||||
<artifactId>tracker</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.build</groupId>
|
||||
<artifactId>manifest-merger</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools.layoutlib</groupId>
|
||||
<artifactId>layoutlib-api</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools</groupId>
|
||||
<artifactId>sdk-common</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.android.tools</groupId>
|
||||
<artifactId>sdklib</artifactId>
|
||||
<version>31.0.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.0.1-jre</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.kxml</groupId>
|
||||
<artifactId>kxml2</artifactId>
|
||||
<version>2.3.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
<version>1.7.10</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
||||
<version>1.7.10</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
BIN
lib/android-lint/lint-api-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/lint-api-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/lint-checks-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/lint-checks-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/manifest-merger-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/manifest-merger-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/protos-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/protos-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/sdk-common-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/sdk-common-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/sdklib-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/sdklib-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/shared-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/shared-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/tracker-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/tracker-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/android-lint/uast-31.0.1.jar
LFS
Normal file
BIN
lib/android-lint/uast-31.0.1.jar
LFS
Normal file
Binary file not shown.
BIN
lib/classgraph-4.8.157-javadoc.jar
LFS
Normal file
BIN
lib/classgraph-4.8.157-javadoc.jar
LFS
Normal file
Binary file not shown.
BIN
lib/classgraph-4.8.157-sources.jar
LFS
Normal file
BIN
lib/classgraph-4.8.157-sources.jar
LFS
Normal file
Binary file not shown.
BIN
lib/classgraph-4.8.157.jar
LFS
Normal file
BIN
lib/classgraph-4.8.157.jar
LFS
Normal file
Binary file not shown.
@@ -1,3 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: net.torvald.terrarum.App
|
||||
Main-Class: net.torvald.terrarum.Principii
|
||||
|
||||
|
||||
@@ -231,6 +231,10 @@ final public class FastMath {
|
||||
return (float) (((c4 * u + c3) * u + c2) * u + c1);
|
||||
}
|
||||
|
||||
public static float interpolateCatmullRom(float u, float p0, float p1, float p2, float p3) {
|
||||
return interpolateCatmullRom(u, 0.5f, p0, p1, p2, p3);
|
||||
}
|
||||
|
||||
/**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
|
||||
* here is the interpolation matrix
|
||||
* m = [ 0.0 1.0 0.0 0.0 ]
|
||||
@@ -316,24 +320,25 @@ final public class FastMath {
|
||||
|
||||
|
||||
public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3) {
|
||||
return interpolateHermite(scale, p0, p1, p2, p3, 1f, 0f);
|
||||
}
|
||||
public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3, float tension, float bias) {
|
||||
// return interpolateHermite(scale, p0, p1, p2, p3, 0f, 0f);
|
||||
float mu2 = scale * scale;
|
||||
float mu3 = mu2 * scale;
|
||||
float biasTensionTerms = 0.5f;//(1f + bias) * (1f - tension) / 2f;
|
||||
|
||||
float m0 = (p1 - p0) * (1f + bias) * (1f - tension) / 2f;
|
||||
m0 += (p2 - p1) * (1f + bias) * (1f - tension) / 2f;
|
||||
float m1 = (p2 - p1) * (1f + bias) * (1f - tension) / 2f;
|
||||
m1 += (p3 - p2) * (1f + bias) * (1f - tension) / 2f;
|
||||
float m0 = (p1 - p0) * biasTensionTerms;
|
||||
float mTemp = (p2 - p1) * biasTensionTerms;
|
||||
m0 += mTemp;
|
||||
float m1 = mTemp;
|
||||
m1 += (p3 - p2) * biasTensionTerms;
|
||||
|
||||
float a0 = 2 * mu3 - 3 * mu2 + 1;
|
||||
float a1 = mu3 - 2 * mu2 + scale;
|
||||
float a2 = mu3 - mu2;
|
||||
float a3 = -2 * mu3 + 3 * mu2;
|
||||
float a0 = 2*mu3 - 3*mu2 + 1;
|
||||
float a1 = 1*mu3 - 2*mu2 + scale;
|
||||
float a2 = 1*mu3 - 1*mu2 + 0;
|
||||
float a3 = -2*mu3 + 3*mu2 + 0;
|
||||
|
||||
return a0 * p1 + a1 * m0 + a2 * m1 + a3 * p2;
|
||||
return a0*p1 + a1*m0 + a2*m1 + a3*p2;
|
||||
}
|
||||
//public static float interpolateHermite(float scale, float p0, float p1, float p2, float p3, float tension, float bias) {}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@ public class XXHash32 {
|
||||
|
||||
public static int hashGeoCoord(int x, int y) {
|
||||
int p = ((x & 65535) << 16) | (y & 65535);
|
||||
return hash(new byte[]{(byte) p, (byte)(p >>> 8), (byte)(p >>> 16), (byte)(p >>> 24)}, 10000);
|
||||
return hash(new byte[]{(byte) p, (byte)(p >>> 8), (byte)(p >>> 16), (byte)(p >>> 24)}, x ^ y);
|
||||
}
|
||||
|
||||
public static int hash(byte[] data, int seed) {
|
||||
|
||||
@@ -3,15 +3,15 @@ package net.torvald.reflection
|
||||
/**
|
||||
* Created by minjaesong on 2023-03-25.
|
||||
*/
|
||||
fun Any.extortField(name: String): Any? { // yes I'm deliberately using negative words for the function name
|
||||
inline fun <reified T> Any.extortField(name: String): T? { // yes I'm deliberately using negative words for the function name
|
||||
return this.javaClass.getDeclaredField(name).let {
|
||||
it.isAccessible = true
|
||||
it.get(this)
|
||||
it.get(this) as T?
|
||||
}
|
||||
}
|
||||
fun Any.forceInvoke(name: String, params: Array<Any>): Any? { // yes I'm deliberately using negative words for the function name
|
||||
inline fun <reified T> Any.forceInvoke(name: String, params: Array<Any>): T? { // yes I'm deliberately using negative words for the function name
|
||||
return this.javaClass.getDeclaredMethod(name, *(params.map { it.javaClass }.toTypedArray())).let {
|
||||
it.isAccessible = true
|
||||
it.invoke(this, *params)
|
||||
it.invoke(this, *params) as T?
|
||||
}
|
||||
}
|
||||
@@ -142,6 +142,12 @@ public class App implements ApplicationListener {
|
||||
|
||||
public static final int GLOBAL_FRAMERATE_LIMIT = 300;
|
||||
|
||||
private static String undesirableConditions;
|
||||
|
||||
public static String getUndesirableConditions() {
|
||||
return undesirableConditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* These languages won't distinguish regional differences (e.g. enUS and enUK, frFR and frCA)
|
||||
*/
|
||||
@@ -201,11 +207,11 @@ public class App implements ApplicationListener {
|
||||
* Sorted by the lastplaytime, in reverse order (index 0 is the most recent game played)
|
||||
*/
|
||||
public static ArrayList<UUID> sortedSavegameWorlds = new ArrayList();
|
||||
public static HashMap<UUID, DiskSkimmer> savegameWorlds = new HashMap<>(); // UNSORTED even with the TreeMap
|
||||
public static HashMap<UUID, SavegameCollection> savegameWorlds = new HashMap<>(); // UNSORTED even with the TreeMap
|
||||
public static HashMap<UUID, String> savegameWorldsName = new HashMap<>();
|
||||
|
||||
public static ArrayList<UUID> sortedPlayers = new ArrayList();
|
||||
public static HashMap<UUID, DiskSkimmer> savegamePlayers = new HashMap<>();
|
||||
public static HashMap<UUID, SavegameCollection> savegamePlayers = new HashMap<>();
|
||||
public static HashMap<UUID, String> savegamePlayersName = new HashMap<>();
|
||||
|
||||
public static void updateListOfSavegames() {
|
||||
@@ -346,10 +352,13 @@ public class App implements ApplicationListener {
|
||||
processorVendor = "Unknown CPU";
|
||||
}
|
||||
|
||||
if (processor.startsWith("Apple M") && Objects.equals(systemArch, "aarch64")) {
|
||||
if (processor.startsWith("Apple M") && systemArch.equals("aarch64")) {
|
||||
isAppleM = true;
|
||||
System.out.println("Apple Proprietary "+processor+" detected; don't expect smooth sailing...");
|
||||
}
|
||||
if (processor.startsWith("Apple M") && !systemArch.equals("aarch64")) {
|
||||
undesirableConditions = "apple_execution_through_rosetta";
|
||||
}
|
||||
|
||||
if (!IS_DEVELOPMENT_BUILD) {
|
||||
var p = UnsafeHelper.INSTANCE.allocate(64);
|
||||
@@ -374,8 +383,8 @@ public class App implements ApplicationListener {
|
||||
ShaderProgram.pedantic = false;
|
||||
|
||||
scr = new TerrarumScreenSize(getConfigInt("screenwidth"), getConfigInt("screenheight"));
|
||||
int width = (int) Math.round(scr.getWidth() * scr.getMagn());
|
||||
int height = (int) Math.round(scr.getHeight() * scr.getMagn());
|
||||
int width = scr.getWindowW();
|
||||
int height = scr.getWindowH();
|
||||
|
||||
Lwjgl3ApplicationConfiguration appConfig = new Lwjgl3ApplicationConfiguration();
|
||||
//appConfig.useGL30 = false; // https://stackoverflow.com/questions/46753218/libgdx-should-i-use-gl30
|
||||
@@ -557,7 +566,7 @@ public class App implements ApplicationListener {
|
||||
false,
|
||||
64, false, 0.5f, false
|
||||
);
|
||||
fontUITitle.setInterchar(2);
|
||||
fontUITitle.setInterchar(1);
|
||||
fontGameFBO = new TerrarumSansBitmap(FONT_DIR, false, true, false,
|
||||
false,
|
||||
64, false, 203f/255f, false
|
||||
@@ -631,7 +640,6 @@ public class App implements ApplicationListener {
|
||||
// process screenshot request
|
||||
if (screenshotRequested) {
|
||||
FrameBufferManager.begin(postProcessorOutFBO);
|
||||
screenshotRequested = false;
|
||||
try {
|
||||
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, scr.getWidth(), scr.getHeight());
|
||||
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
|
||||
@@ -643,6 +651,7 @@ public class App implements ApplicationListener {
|
||||
Terrarum.INSTANCE.getIngame().sendNotification("Failed to take screenshot: "+e.getMessage());
|
||||
}
|
||||
FrameBufferManager.end();
|
||||
screenshotRequested = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -767,12 +776,9 @@ public class App implements ApplicationListener {
|
||||
@Override
|
||||
public void resize(int w0, int h0) {
|
||||
|
||||
int w = (w0%2==0)?w0:w0+1;
|
||||
int h = (h0%2==0)?h0:h0+1;
|
||||
|
||||
float magn = (float) getConfigDouble("screenmagnifying");
|
||||
int width = Math.round(w / magn);
|
||||
int height = Math.round(h / magn);
|
||||
int width = (int) Math.floor(w0 / magn);
|
||||
int height = (int) Math.floor(h0 / magn);
|
||||
|
||||
|
||||
printdbg(this, "Resize called: "+width+","+height);
|
||||
@@ -782,7 +788,7 @@ public class App implements ApplicationListener {
|
||||
|
||||
//initViewPort(width, height);
|
||||
|
||||
scr.setDimension(width, height, magn, w, h);
|
||||
scr.setDimension(width, height, magn);
|
||||
|
||||
if (currentScreen != null) currentScreen.resize(scr.getWidth(), scr.getHeight());
|
||||
TerrarumPostProcessor.INSTANCE.resize(scr.getWidth(), scr.getHeight());
|
||||
@@ -855,7 +861,7 @@ public class App implements ApplicationListener {
|
||||
fullscreenQuad.dispose();
|
||||
logoBatch.dispose();
|
||||
batch.dispose();
|
||||
shapeRender.dispose();
|
||||
// shapeRender.dispose();
|
||||
|
||||
fontGame.dispose();
|
||||
fontGameFBO.dispose();
|
||||
@@ -1133,6 +1139,11 @@ public class App implements ApplicationListener {
|
||||
|
||||
public static RunningEnvironment environment;
|
||||
|
||||
/** defaultDir + "/Recycled/Players" */
|
||||
public static String recycledPlayersDir;
|
||||
/** defaultDir + "/Recycled/Worlds" */
|
||||
public static String recycledWorldsDir;
|
||||
|
||||
private static void getDefaultDirectory() {
|
||||
String OS = OSName.toUpperCase();
|
||||
if (OS.contains("WIN")) {
|
||||
@@ -1162,6 +1173,8 @@ public class App implements ApplicationListener {
|
||||
worldsDir = defaultDir + "/Worlds";
|
||||
configDir = defaultDir + "/config.json";
|
||||
loadOrderDir = defaultDir + "/LoadOrder.txt";
|
||||
recycledPlayersDir = defaultDir + "/Recycled/Players";
|
||||
recycledWorldsDir = defaultDir + "/Recycled/Worlds";
|
||||
|
||||
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
||||
System.out.println(String.format("os.version = %s", OSVersion));
|
||||
@@ -1171,10 +1184,12 @@ public class App implements ApplicationListener {
|
||||
|
||||
private static void createDirs() {
|
||||
File[] dirs = {
|
||||
new File(saveDir),
|
||||
// new File(saveDir),
|
||||
new File(saveSharedDir),
|
||||
new File(playersDir),
|
||||
new File(worldsDir)
|
||||
new File(worldsDir),
|
||||
new File(recycledPlayersDir),
|
||||
new File(recycledWorldsDir),
|
||||
};
|
||||
|
||||
for (File it : dirs) {
|
||||
|
||||
@@ -118,6 +118,7 @@ object CommonResourcePool {
|
||||
fun getAsTextureRegionPack(identifier: String) = getAs<TextureRegionPack>(identifier)
|
||||
fun getAsTextureRegion(identifier: String) = getAs<TextureRegion>(identifier)
|
||||
fun getAsTexture(identifier: String) = getAs<Texture>(identifier)
|
||||
fun getAsItemSheet(identifier: String) = getAs<ItemSheet>(identifier)
|
||||
|
||||
fun dispose() {
|
||||
pool.forEach { (name, u) ->
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import net.torvald.unicode.BULLET
|
||||
import net.torvald.unicode.ENDASH
|
||||
|
||||
@@ -223,6 +224,22 @@ Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
""").split('\n')
|
||||
|
||||
|
||||
private val javaVersion = System.getProperty("java.version")
|
||||
private val osName = App.OSName
|
||||
private val osVersion = App.OSVersion
|
||||
private val sysArch = App.systemArch
|
||||
private val processor = App.processor
|
||||
private val processorVendor = App.processorVendor
|
||||
private val glinfo = Gdx.graphics.glVersion.debugVersionString
|
||||
|
||||
val systeminfo: List<String>; get() = """
|
||||
JRE Version: $javaVersion
|
||||
Operation System: $osName $osVersion
|
||||
Architecture: $sysArch
|
||||
Processor: $processor ($processorVendor)
|
||||
GL Info: $glinfo
|
||||
""".split('\n')
|
||||
|
||||
|
||||
val gpl3: List<String>; get() = """ GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
@@ -10,6 +10,9 @@ import com.badlogic.gdx.Input
|
||||
object DefaultConfig {
|
||||
|
||||
val hashMap = hashMapOf<String, Any>(
|
||||
"jvm_xmx" to 4,
|
||||
"jvm_extra_cmd" to "",
|
||||
|
||||
"displayfps" to 0, // 0: no limit, non-zero: limit
|
||||
"displayfpsidle" to 0, // 0: no limit, non-zero: limit
|
||||
"displaycolourdepth" to 8,
|
||||
@@ -19,9 +22,9 @@ object DefaultConfig {
|
||||
"atlastexsize" to 2048,
|
||||
|
||||
"language" to App.getSysLang(),
|
||||
"notificationshowuptime" to 4096, // 4s
|
||||
"selecteditemnameshowuptime" to 4096, // 4s
|
||||
"autosaveinterval" to 262144, // 4m22s
|
||||
"notificationshowuptime" to 4000, // 4s
|
||||
"selecteditemnameshowuptime" to 4000, // 4s
|
||||
"autosaveinterval" to 300000, // 5s
|
||||
"multithread" to true,
|
||||
|
||||
"showhealthmessageonstartup" to true,
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameactors.ActorID
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.PHYS_EPSILON_DIST
|
||||
import net.torvald.terrarum.gameactors.BlockMarkerActor
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
@@ -26,6 +27,8 @@ import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.*
|
||||
import java.util.concurrent.locks.Lock
|
||||
import java.util.function.Consumer
|
||||
@@ -49,8 +52,8 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
||||
|
||||
override fun getMax(axis: Int, t: ActorWithBody): Double =
|
||||
when (axis) {
|
||||
0 -> t.hitbox.endX
|
||||
1 -> t.hitbox.endY
|
||||
0 -> t.hitbox.endX - PHYS_EPSILON_DIST
|
||||
1 -> t.hitbox.endY - PHYS_EPSILON_DIST
|
||||
else -> throw IllegalArgumentException("nonexistent axis $axis for ${dimensions}-dimensional object")
|
||||
}
|
||||
}
|
||||
@@ -406,6 +409,14 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
||||
return uiTooltip.message
|
||||
}
|
||||
|
||||
open fun requestForceSave(callback: () -> Unit) {
|
||||
|
||||
}
|
||||
|
||||
open fun saveTheGame(onSuccessful: () -> Unit, onError: (Throwable) -> Unit) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies most recent `save` to `save.1`, leaving `save` for overwriting, previous `save.1` will be copied to `save.2`
|
||||
*/
|
||||
@@ -422,25 +433,55 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
||||
// do not overwrite clean .2 with dirty .1
|
||||
val flags3 = FileInputStream(file3).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
if (!(flags3 == 0 && flags2 != 0) || !file3.exists()) file2.copyTo(file3, true)
|
||||
if (!(flags3 == 0 && flags2 != 0) || !file3.exists()) Files.move(file2.toPath(), file3.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||
try {
|
||||
// do not overwrite clean .2 with dirty .1
|
||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
||||
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) Files.move(file1.toPath(), file2.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||
try {
|
||||
if (file2.exists() && !file3.exists())
|
||||
file2.copyTo(file3, true)
|
||||
Files.move(file2.toPath(), file3.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
if (file1.exists() && !file2.exists())
|
||||
file1.copyTo(file2, true)
|
||||
Files.move(file1.toPath(), file2.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
|
||||
file.copyTo(file1, true)
|
||||
} catch (e: IOException) {}
|
||||
}
|
||||
|
||||
|
||||
fun makeSavegameBackupCopyAuto(file0: File): File {
|
||||
val file1 = File("${file0.absolutePath}.a")
|
||||
val file2 = File("${file0.absolutePath}.b")
|
||||
val file3 = File("${file0.absolutePath}.c")
|
||||
|
||||
try {
|
||||
// do not overwrite clean .2 with dirty .1
|
||||
val flags3 = FileInputStream(file3).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
if (!(flags3 == 0 && flags2 != 0) || !file3.exists()) Files.move(file2.toPath(), file3.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||
try {
|
||||
// do not overwrite clean .2 with dirty .1
|
||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) Files.move(file1.toPath(), file2.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||
try {
|
||||
if (file2.exists() && !file3.exists())
|
||||
Files.move(file2.toPath(), file3.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
if (file1.exists() && !file2.exists())
|
||||
Files.move(file1.toPath(), file2.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
|
||||
file0.copyTo(file1, true)
|
||||
} catch (e: IOException) {}
|
||||
|
||||
return file1
|
||||
}
|
||||
|
||||
|
||||
|
||||
// simple euclidean norm, squared
|
||||
private val actorDistanceCalculator = DistanceCalculator<ActorWithBody> { t: ActorWithBody, p: PointND ->
|
||||
@@ -449,7 +490,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
||||
val dist2 = (p.getOrd(0) - (t.hitbox.centeredX - world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
||||
val dist3 = (p.getOrd(0) - (t.hitbox.centeredX + world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
||||
|
||||
minOf(dist1, minOf(dist2, dist3))
|
||||
minOf(dist1, dist2, dist3)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -467,7 +508,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
||||
fun getActorsAt(worldX: Double, worldY: Double): List<ActorWithBody> {
|
||||
val outList = ArrayList<ActorWithBody>()
|
||||
try {
|
||||
actorsRTree.find(worldX, worldY, worldX + 1.0, worldY + 1.0, outList)
|
||||
actorsRTree.find(worldX, worldY, worldX, worldY, outList)
|
||||
}
|
||||
catch (e: NullPointerException) {}
|
||||
return outList
|
||||
|
||||
49
src/net/torvald/terrarum/ItemSheet.kt
Normal file
49
src/net/torvald/terrarum/ItemSheet.kt
Normal file
@@ -0,0 +1,49 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-06-06.
|
||||
*/
|
||||
class ItemSheet(ref: FileHandle, tileW: Int = 48, tileH: Int = 48) : Disposable {
|
||||
|
||||
private val textureRegionPack = TextureRegionPack(ref, tileW, tileH + 1)
|
||||
|
||||
init {
|
||||
val pixmap = Pixmap(ref)
|
||||
for (y in 0 until textureRegionPack.verticalCount) {
|
||||
for (x in 0 until textureRegionPack.horizontalCount) {
|
||||
var w = 0
|
||||
var h = 0
|
||||
for (i in 0..7) {
|
||||
// width
|
||||
w = w or (pixmap.getPixel(x * tileW + i, y * (tileH + 1)).and(255) > 127).toInt(7 - i)
|
||||
// height
|
||||
h = h or (pixmap.getPixel(x * tileW + i + 8, y * (tileH + 1)).and(255) > 127).toInt(7 - i)
|
||||
}
|
||||
|
||||
textureRegionPack.get(x, y).apply {
|
||||
this.setRegion(x * tileW, y * (tileH + 1) + 1, w, h)
|
||||
}
|
||||
|
||||
// println("[ItemSheet] ${ref.path()} ($x,$y) dim ($w,$h)")
|
||||
}
|
||||
}
|
||||
pixmap.dispose()
|
||||
}
|
||||
|
||||
val horizontalCount = textureRegionPack.horizontalCount
|
||||
val verticalCount = textureRegionPack.verticalCount
|
||||
|
||||
fun get(x: Int, y: Int) = textureRegionPack.get(x, y)
|
||||
|
||||
fun forEach(action: (TextureRegion) -> Unit) = textureRegionPack.regions.forEach(action)
|
||||
|
||||
override fun dispose() {
|
||||
textureRegionPack.dispose()
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.utils.JsonValue
|
||||
import net.torvald.terrarum.App.*
|
||||
import net.torvald.terrarum.App.setToGameConfig
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.WireCodex
|
||||
import net.torvald.terrarum.gameitems.GameItem
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import net.torvald.random.XXHash32
|
||||
import org.dyn4j.geometry.Vector2
|
||||
|
||||
/**
|
||||
@@ -115,6 +116,10 @@ class Point2i() {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = XXHash32.hashGeoCoord(x, y)
|
||||
|
||||
override fun toString() = "Point2i($x, $y)"
|
||||
|
||||
operator fun component1() = x
|
||||
operator fun component2() = y
|
||||
}
|
||||
|
||||
334
src/net/torvald/terrarum/Principii.java
Normal file
334
src/net/torvald/terrarum/Principii.java
Normal file
@@ -0,0 +1,334 @@
|
||||
package net.torvald.terrarum;
|
||||
|
||||
import com.badlogic.gdx.utils.JsonValue;
|
||||
import net.torvald.terrarum.utils.JsonFetcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Bootstrapper that launches the bundled JVM and injects VM configs such as -Xmx
|
||||
*
|
||||
* Created by minjaesong on 2023-06-22.
|
||||
*/
|
||||
public class Principii {
|
||||
|
||||
private static KVHashMap gameConfig = new KVHashMap();
|
||||
|
||||
private static String OSName = System.getProperty("os.name");
|
||||
|
||||
private static String operationSystem;
|
||||
/** %appdata%/Terrarum, without trailing slash */
|
||||
private static String defaultDir;
|
||||
/** defaultDir + "/config.json" */
|
||||
private static String configDir;
|
||||
|
||||
|
||||
public static void getDefaultDirRoot() {
|
||||
String OS = OSName.toUpperCase();
|
||||
if (OS.contains("WIN")) {
|
||||
operationSystem = "WINDOWS";
|
||||
defaultDir = System.getenv("APPDATA") + "/Terrarum";
|
||||
}
|
||||
else if (OS.contains("OS X") || OS.contains("MACOS")) { // OpenJDK for mac will still report "Mac OS X" with version number "10.16", even on Big Sur and beyond
|
||||
operationSystem = "OSX";
|
||||
defaultDir = System.getProperty("user.home") + "/Library/Application Support/Terrarum";
|
||||
}
|
||||
else if (OS.contains("NUX") || OS.contains("NIX") || OS.contains("BSD")) {
|
||||
operationSystem = "LINUX";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
}
|
||||
else if (OS.contains("SUNOS")) {
|
||||
operationSystem = "SOLARIS";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
}
|
||||
else {
|
||||
operationSystem = "UNKNOWN";
|
||||
defaultDir = System.getProperty("user.home") + "/.Terrarum";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
boolean devMode = false;
|
||||
|
||||
// if -ea flag is set, turn on all the debug prints
|
||||
try {
|
||||
assert false;
|
||||
}
|
||||
catch (AssertionError e) {
|
||||
devMode = true;
|
||||
}
|
||||
|
||||
String extracmd = devMode ? " -ea" : "";
|
||||
String OS = OSName.toUpperCase();
|
||||
String CPUARCH = System.getProperty("os.arch").toUpperCase();
|
||||
String runtimeRoot;
|
||||
String runtimeArch;
|
||||
if (!CPUARCH.equals("AMD64") && !CPUARCH.equals("X86_64") && !CPUARCH.equals("AARCH64")) { // macOS Rosetta2 reports X86_64
|
||||
System.err.println("Unsupported CPU architecture: " + CPUARCH);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
runtimeArch = (CPUARCH.equals("AMD64") || CPUARCH.equals("X86_64")) ? "x86" : "arm";
|
||||
}
|
||||
|
||||
if (OS.contains("WIN")) {
|
||||
runtimeRoot = "runtime-windows-" + runtimeArch;
|
||||
}
|
||||
else if (OS.contains("OS X") || OS.contains("MACOS")) { // OpenJDK for mac will still report "Mac OS X" with version number "10.16", even on Big Sur and beyond
|
||||
runtimeRoot = "runtime-osx-" + runtimeArch;
|
||||
extracmd += " -XstartOnFirstThread";
|
||||
}
|
||||
else {
|
||||
runtimeRoot = "runtime-linux-" + runtimeArch;
|
||||
extracmd += " -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd";
|
||||
}
|
||||
|
||||
String runtime = new File("out/"+runtimeRoot+"/bin/java").getAbsolutePath();
|
||||
System.out.println("Runtime path: "+runtime);
|
||||
|
||||
|
||||
|
||||
getDefaultDirRoot();
|
||||
configDir = defaultDir + "/config.json";
|
||||
|
||||
initialiseConfig();
|
||||
readConfigJson();
|
||||
|
||||
|
||||
int xmx = getConfigInt("jvm_xmx");
|
||||
String userDefinedExtraCmd = getConfigString("jvm_extra_cmd").trim();
|
||||
if (!userDefinedExtraCmd.isEmpty()) userDefinedExtraCmd = " "+userDefinedExtraCmd;
|
||||
|
||||
|
||||
|
||||
try {
|
||||
String[] cmd = (runtime+extracmd+userDefinedExtraCmd+" -Xms1G -Xmx"+xmx+"G -cp ./out/TerrarumBuild.jar net.torvald.terrarum.App").split(" ");
|
||||
ProcessBuilder pb = new ProcessBuilder(cmd);
|
||||
pb.inheritIO();
|
||||
System.exit(pb.start().waitFor());
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CONFIG //
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
private static int getConfigInt(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
|
||||
if (cfg instanceof Integer) return ((int) cfg);
|
||||
|
||||
double value = (double) cfg;
|
||||
|
||||
if (Math.abs(value % 1.0) < 0.00000001)
|
||||
return (int) Math.round(value);
|
||||
return ((int) cfg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
private static double getConfigDouble(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
return (cfg instanceof Integer) ? (((Integer) cfg) * 1.0) : ((double) (cfg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist.
|
||||
* *
|
||||
* @throws NullPointerException if the specified config simply does not exist.
|
||||
*/
|
||||
private static String getConfigString(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
return ((String) cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return config from config set. If the config does not exist, default value will be returned.
|
||||
* @param key
|
||||
* *
|
||||
* @return Config from config set or default config if it does not exist. If the default value is undefined, will return false.
|
||||
*/
|
||||
private static boolean getConfigBoolean(String key) {
|
||||
try {
|
||||
Object cfg = getConfigMaster(key);
|
||||
return ((boolean) cfg);
|
||||
}
|
||||
catch (NullPointerException keyNotFound) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*private static int[] getConfigIntArray(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonArray) {
|
||||
JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray();
|
||||
//return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt })
|
||||
int[] intArray = new int[jsonArray.size()];
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
intArray[i] = jsonArray.get(i).getAsInt();
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
else
|
||||
return ((int[]) cfg);
|
||||
}*/
|
||||
|
||||
private static double[] getConfigDoubleArray(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
return ((double[]) cfg);
|
||||
}
|
||||
|
||||
private static int[] getConfigIntArray(String key) {
|
||||
double[] a = getConfigDoubleArray(key);
|
||||
int[] r = new int[a.length];
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
r[i] = ((int) a[i]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*private static String[] getConfigStringArray(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonArray) {
|
||||
JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray();
|
||||
//return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt })
|
||||
String[] intArray = new String[jsonArray.size()];
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
intArray[i] = jsonArray.get(i).getAsString();
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
else
|
||||
return ((String[]) cfg);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown
|
||||
*/
|
||||
private static HashMap<String, Object> getDefaultConfig() {
|
||||
return DefaultConfig.INSTANCE.getHashMap();
|
||||
}
|
||||
|
||||
private static Object getConfigMaster(String key1) {
|
||||
String key = key1.toLowerCase();
|
||||
|
||||
Object config;
|
||||
try {
|
||||
config = gameConfig.get(key);
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
config = null;
|
||||
}
|
||||
|
||||
Object defaults;
|
||||
try {
|
||||
defaults = getDefaultConfig().get(key);
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
defaults = null;
|
||||
}
|
||||
|
||||
if (config == null) {
|
||||
if (defaults == null) {
|
||||
throw new NullPointerException("key not found: '" + key + "'");
|
||||
}
|
||||
else {
|
||||
return defaults;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true on successful, false on failure.
|
||||
*/
|
||||
private static Boolean readConfigJson() {
|
||||
System.out.println("Config file: " + configDir);
|
||||
|
||||
|
||||
try {
|
||||
// read from disk and build config from it
|
||||
JsonValue map = JsonFetcher.INSTANCE.invoke(configDir);
|
||||
|
||||
// make config
|
||||
for (JsonValue entry = map.child; entry != null; entry = entry.next) {
|
||||
setToGameConfigForced(entry, null);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
// write default config to game dir. Call th.is method again to read config from it.
|
||||
e.printStackTrace();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reads DefaultConfig to populate the gameConfig
|
||||
*/
|
||||
private static void initialiseConfig() {
|
||||
for (Map.Entry<String, Object> entry : DefaultConfig.INSTANCE.getHashMap().entrySet()) {
|
||||
gameConfig.set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will forcibly overwrite previously loaded config value.
|
||||
*
|
||||
* Key naming convention will be 'modName:propertyName'; if modName is null, the key will be just propertyName.
|
||||
*
|
||||
* @param value JsonValue (the key-value pair)
|
||||
* @param modName module name, nullable
|
||||
*/
|
||||
private static void setToGameConfigForced(JsonValue value, String modName) {
|
||||
gameConfig.set((modName == null) ? value.name : modName+":"+value.name,
|
||||
value.isArray() ? value.asDoubleArray() :
|
||||
value.isDouble() ? value.asDouble() :
|
||||
value.isBoolean() ? value.asBoolean() :
|
||||
value.isLong() ? value.asInt() :
|
||||
value.asString()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
113
src/net/torvald/terrarum/QuickDirtyLint.kt
Normal file
113
src/net/torvald/terrarum/QuickDirtyLint.kt
Normal file
@@ -0,0 +1,113 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import io.github.classgraph.ClassGraph
|
||||
import io.github.classgraph.ClassInfo
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameitems.GameItem
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-05-22.
|
||||
*/
|
||||
fun main() {
|
||||
|
||||
val superClasses = listOf(
|
||||
Actor::class.java,
|
||||
GameItem::class.java
|
||||
)
|
||||
|
||||
val serialisablePrimitives = listOf(
|
||||
// comparison: exact match
|
||||
"Z",
|
||||
"B",
|
||||
"C",
|
||||
"S",
|
||||
"I",
|
||||
"J",
|
||||
"F",
|
||||
"D",
|
||||
).flatMap { listOf(it, "[$it") }
|
||||
|
||||
val serialisableTypes = listOf(
|
||||
// arrays: has '[' prepended
|
||||
// comparison: startsWith
|
||||
|
||||
// primitives
|
||||
"Ljava/lang/String", // includes ZipCodedStr
|
||||
"Ljava/lang/Boolean",
|
||||
"Ljava/lang/Byte",
|
||||
"Ljava/lang/Character",
|
||||
"Ljava/lang/Short",
|
||||
"Ljava/lang/Integer",
|
||||
"Ljava/lang/Long",
|
||||
"Ljava/lang/Float",
|
||||
"Ljava/lang/Double",
|
||||
// has serialiser on net.torvald.terrarum.serialise.Common
|
||||
"Ljava/math/BigInteger",
|
||||
"Ljava/util/UUID",
|
||||
"Ljava/util/HashMap",
|
||||
"Ljava/util/HashSet",
|
||||
"Ljava/util/ArrayList",
|
||||
"Lnet/torvald/terrarum/gameworld/BlockLayer",
|
||||
"Lnet/torvald/terrarum/gameworld/WorldTime",
|
||||
// complex types
|
||||
"Lnet/torvald/gdx/graphics/Cvec",
|
||||
"Lnet/torvald/random/HQRNG",
|
||||
"Lnet/torvald/spriteanimation/SpriteAnimation",
|
||||
"Lnet/torvald/terrarum/Codex",
|
||||
"Lnet/torvald/terrarum/Point2d",
|
||||
"Lnet/torvald/terrarum/Point2i",
|
||||
"Lnet/torvald/terrarum/KVHashMap",
|
||||
"Lnet/torvald/terrarum/gameactors/Actor\$RenderOrder",
|
||||
"Lnet/torvald/terrarum/gameactors/ActorValue",
|
||||
"Lnet/torvald/terrarum/gameactors/Hitbox",
|
||||
"Lnet/torvald/terrarum/gameactors/Lightbox",
|
||||
"Lnet/torvald/terrarum/gameactors/PhysProperties",
|
||||
"Lnet/torvald/terrarum/gameitems/GameItem",
|
||||
"Lnet/torvald/terrarum/utils/HashArray",
|
||||
"Lnet/torvald/terrarum/utils/HashedWirings",
|
||||
"Lnet/torvald/terrarum/utils/HashedWiringGraph",
|
||||
"Lnet/torvald/terrarum/utils/WiringGraphMap",
|
||||
"Lnet/torvald/terrarum/savegame/ByteArray64",
|
||||
"Lnet/torvald/terrarum/modulebasegame/gameactors/ActorInventory",
|
||||
"Lnet/torvald/terrarum/modulebasegame/gameactors/BlockBox",
|
||||
"Lnet/torvald/terrarum/modulebasegame/gameactors/FixtureInventory",
|
||||
"Lkotlin/ranges/IntRange",
|
||||
"Lorg/dyn4j/geometry/Vector2",
|
||||
"Lcom/badlogic/gdx/graphics/Color",
|
||||
// subclasses
|
||||
"Lnet/torvald/terrarum/gameactors/BlockMarkerActor",
|
||||
"Lnet/torvald/terrarum/gameactors/Actor",
|
||||
"Lnet/torvald/terrarum/gameactors/ActorWithBody",
|
||||
"Lnet/torvald/terrarum/gameactors/ActorHumanoid",
|
||||
// composite types
|
||||
"Lkotlin/Pair<Ljava/lang/Integer;Ljava/lang/Integer;>"
|
||||
).flatMap { listOf(it, "[$it") }
|
||||
|
||||
val classaNonGrata = listOf(
|
||||
"net.torvald.terrarum.modulebasegame.MovableWorldCamera"
|
||||
)
|
||||
|
||||
ClassGraph().acceptPackages("net.torvald.terrarum")/*.verbose()*/.enableAllInfo().scan().let { scan ->
|
||||
val offendingFields = scan.allClasses.filter { classinfo ->
|
||||
superClasses.any { classinfo.extendsSuperclass(it) || classinfo.name == it.canonicalName } &&
|
||||
!classaNonGrata.contains(classinfo.name)
|
||||
}.flatMap { clazz ->
|
||||
clazz.declaredFieldInfo.filter { field ->
|
||||
!field.isTransient &&
|
||||
!field.isEnum &&
|
||||
!serialisablePrimitives.contains(field.typeSignatureOrTypeDescriptorStr) &&
|
||||
serialisableTypes.none { field.typeSignatureOrTypeDescriptorStr.startsWith(it) }
|
||||
}
|
||||
}
|
||||
|
||||
// println(offendingFields)
|
||||
|
||||
offendingFields.forEach {
|
||||
println("\u001B[1m${it.name}\u001B[m\n\t\u001B[32mfrom: \u001B[m${it.className}\n\t\u001B[32mtype: \u001B[m${it.typeSignatureOrTypeDescriptorStr}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
184
src/net/torvald/terrarum/SavegameCollection.kt
Normal file
184
src/net/torvald/terrarum/SavegameCollection.kt
Normal file
@@ -0,0 +1,184 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import kotlin.io.path.Path
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-06-24.
|
||||
*/
|
||||
class SavegameCollection(files0: List<DiskSkimmer>) {
|
||||
|
||||
/** Sorted in reverse by the last modified time of the files, index zero being the most recent */
|
||||
val files = files0.sortedByDescending {
|
||||
it.getLastModifiedTime().shl(2) or
|
||||
it.diskFile.extension.matches(Regex("^[abc]${'$'}")).toLong(1) or
|
||||
it.diskFile.extension.isBlank().toLong(0)
|
||||
}
|
||||
/** Sorted in reverse by the last modified time of the files, index zero being the most recent */
|
||||
val autoSaves = files.filter { it.diskFile.extension.matches(Regex("[a-z]")) }
|
||||
/** Sorted in reverse by the last modified time of the files, index zero being the most recent */
|
||||
val manualSaves = files.filter { !it.diskFile.extension.matches(Regex("[a-z]")) }
|
||||
|
||||
init {
|
||||
files.forEach { it.rebuild() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun collectFromBaseFilename(basedir: File, name: String): SavegameCollection {
|
||||
val files = basedir.listFiles().filter { it.name.startsWith(name) }
|
||||
.mapNotNull { try { DiskSkimmer(it, true) } catch (e: Throwable) { null } }
|
||||
return SavegameCollection(files)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the most recent not-corrupted file
|
||||
*/
|
||||
fun loadable(): DiskSkimmer {
|
||||
return files.first()
|
||||
}
|
||||
|
||||
fun moveToRecycle(basedir: String) {
|
||||
files.forEach {
|
||||
try {
|
||||
Files.move(it.diskFile.toPath(), Path(basedir, it.diskFile.name), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getBaseFile(): DiskSkimmer {
|
||||
return files.first { it.diskFile.extension.isBlank() }
|
||||
}
|
||||
}
|
||||
|
||||
class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollection?) {
|
||||
|
||||
private var manualPlayer: DiskSkimmer? = null
|
||||
private var manualWorld: DiskSkimmer? = null
|
||||
private var autoPlayer: DiskSkimmer? = null
|
||||
private var autoWorld: DiskSkimmer? = null
|
||||
|
||||
var status = 0 // 0: none available, 1: loadable manual save is newer than loadable auto; 2: loadable autosave is newer than loadable manual
|
||||
private set
|
||||
|
||||
var newerSaveIsDamaged = false // only when most recent save is corrupted
|
||||
private set
|
||||
|
||||
init {
|
||||
printdbg(this, "init ($player, $world)")
|
||||
|
||||
if (player != null && world != null) {
|
||||
|
||||
printdbg(this, "player files: " + player.files.joinToString { it.diskFile.name })
|
||||
printdbg(this, "world files:" + world.files.joinToString { it.diskFile.name })
|
||||
|
||||
// if a pair of files were saved successfully, they must have identical lastModifiedTime()
|
||||
var pc = 0; val pt = player.files[0].getLastModifiedTime()
|
||||
var wc = 0; val wt = world.files[0].getLastModifiedTime()
|
||||
while (pc < player.files.size && wc < world.files.size) {
|
||||
val pcf = player.files[pc]
|
||||
val pcm = pcf.getLastModifiedTime()
|
||||
val wcf = world.files[wc]
|
||||
val wcm = wcf.getLastModifiedTime()
|
||||
|
||||
printdbg(this, "pc=$pc, wc=$wc, pcm=$pcm, wcm=$wcm")
|
||||
|
||||
if (playerDiskNotDamaged(pcf) && worldDiskNotDamaged(wcf)) {
|
||||
|
||||
printdbg(this, "pcf.autosaved=${pcf.isAutosaved()}, wcf.autosaved=${wcf.isAutosaved()}")
|
||||
|
||||
when (pcf.isAutosaved().toInt(1) or wcf.isAutosaved().toInt()) {
|
||||
3 -> {
|
||||
if (autoPlayer == null && autoWorld == null) {
|
||||
autoPlayer = pcf
|
||||
autoWorld = wcf
|
||||
}
|
||||
pc += 1
|
||||
wc += 1
|
||||
}
|
||||
0 -> {
|
||||
if (manualPlayer == null && manualWorld == null) {
|
||||
manualPlayer = pcf
|
||||
manualWorld = wcf
|
||||
}
|
||||
pc += 1
|
||||
wc += 1
|
||||
}
|
||||
else -> {
|
||||
if (pcm > wcm)
|
||||
pc += 1
|
||||
else if (pcm == wcm) {
|
||||
pc += 1
|
||||
wc += 1
|
||||
}
|
||||
else
|
||||
wc += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (manualPlayer != null && manualWorld != null && autoPlayer != null && autoWorld != null)
|
||||
break
|
||||
}
|
||||
|
||||
if (manualPlayer != null && manualWorld != null && autoPlayer != null && autoWorld != null) {
|
||||
status = if (manualPlayer!!.getLastModifiedTime() > autoPlayer!!.getLastModifiedTime()) 1 else 2
|
||||
}
|
||||
else if (manualPlayer != null && manualWorld != null || autoPlayer != null && autoWorld != null) {
|
||||
status = 1
|
||||
}
|
||||
else {
|
||||
status = 0
|
||||
}
|
||||
|
||||
printdbg(this, "manualPlayer = ${manualPlayer?.diskFile?.path}")
|
||||
printdbg(this, "manualWorld = ${manualWorld?.diskFile?.path}")
|
||||
printdbg(this, "autoPlayer = ${autoPlayer?.diskFile?.path}")
|
||||
printdbg(this, "autoWorld = ${autoWorld?.diskFile?.path}")
|
||||
printdbg(this, "status = $status")
|
||||
}
|
||||
}
|
||||
|
||||
private fun DiskSkimmer.isAutosaved() = this.getSaveMode().and(0b0000_0010) != 0
|
||||
|
||||
private fun playerDiskNotDamaged(disk: DiskSkimmer): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
private fun worldDiskNotDamaged(disk: DiskSkimmer): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
fun moreRecentAutosaveAvailable() = (status == 2)
|
||||
fun saveAvaliable() = (status > 0)
|
||||
|
||||
fun getManualSave(): DiskPair? {
|
||||
if (status == 0) return null
|
||||
return DiskPair(manualPlayer!!, manualWorld!!)
|
||||
}
|
||||
|
||||
fun getAutoSave(): DiskPair? {
|
||||
if (status != 2) return null
|
||||
return DiskPair(autoPlayer!!, autoWorld!!)
|
||||
}
|
||||
|
||||
fun getLoadableSave(): DiskPair? {
|
||||
if (status == 0) return null
|
||||
return if (manualPlayer != null && manualWorld != null)
|
||||
DiskPair(manualPlayer!!, manualWorld!!)
|
||||
else
|
||||
DiskPair(autoPlayer!!, autoWorld!!)
|
||||
}
|
||||
}
|
||||
|
||||
data class DiskPair(val player: DiskSkimmer, val world: DiskSkimmer)
|
||||
@@ -31,6 +31,8 @@ import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.savegame.VDFileID.SAVEGAMEINFO
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.utils.JsonFetcher
|
||||
import net.torvald.terrarum.utils.forEachSiblings
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
@@ -62,11 +64,11 @@ object Terrarum : Disposable {
|
||||
*/
|
||||
const val PLAYER_REF_ID: Int = 0x91A7E2
|
||||
|
||||
inline fun inShapeRenderer(shapeRendererType: ShapeRenderer.ShapeType = ShapeRenderer.ShapeType.Filled, action: (ShapeRenderer) -> Unit) {
|
||||
/*inline fun inShapeRenderer(shapeRendererType: ShapeRenderer.ShapeType = ShapeRenderer.ShapeType.Filled, action: (ShapeRenderer) -> Unit) {
|
||||
shapeRender.begin(shapeRendererType)
|
||||
action(shapeRender)
|
||||
shapeRender.end()
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
var blockCodex = BlockCodex(); internal set
|
||||
@@ -627,7 +629,8 @@ fun Double.sqrt() = Math.sqrt(this)
|
||||
fun Float.sqrt() = FastMath.sqrt(this)
|
||||
fun Int.abs() = this.absoluteValue
|
||||
fun Double.bipolarClamp(limit: Double) = this.coerceIn(-limit, limit)
|
||||
fun Boolean.toInt() = if (this) 1 else 0
|
||||
fun Boolean.toInt(shift: Int = 0) = if (this) 1.shl(shift) else 0
|
||||
fun Boolean.toLong(shift: Int = 0) = if (this) 1L.shl(shift) else 0L
|
||||
fun Int.bitCount() = java.lang.Integer.bitCount(this)
|
||||
fun Long.bitCount() = java.lang.Long.bitCount(this)
|
||||
|
||||
@@ -797,15 +800,17 @@ fun AppUpdateListOfSavegames() {
|
||||
}
|
||||
}.sortedByDescending { it.getLastModifiedTime() }.forEachIndexed { index, it ->
|
||||
println("${index+1}.\t${it.diskFile.absolutePath}")
|
||||
it.rebuild() // disk skimmer was created without initialisation, so do it now
|
||||
it.rebuild()
|
||||
|
||||
val jsonFile = it.getFile(SAVEGAMEINFO)!!
|
||||
val json = JsonReader().parse(ByteArray64Reader(jsonFile.bytes, Common.CHARSET).readText())
|
||||
val worldUUID = UUID.fromString(json.getString("worldIndex"))
|
||||
var worldUUID: UUID? = null
|
||||
JsonFetcher.readFromJsonString(ByteArray64Reader(jsonFile.bytes, Common.CHARSET)).forEachSiblings { name, value ->
|
||||
if (name == "worldIndex") worldUUID = UUID.fromString(value.asString())
|
||||
}
|
||||
|
||||
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
||||
if (!App.savegameWorlds.contains(worldUUID)) {
|
||||
App.savegameWorlds[worldUUID] = it
|
||||
App.savegameWorlds[worldUUID] = SavegameCollection.collectFromBaseFilename(File(worldsDir), it.diskFile.name)
|
||||
App.savegameWorldsName[worldUUID] = it.getDiskName(Common.CHARSET)
|
||||
App.sortedSavegameWorlds.add(worldUUID)
|
||||
}
|
||||
@@ -827,15 +832,17 @@ fun AppUpdateListOfSavegames() {
|
||||
}
|
||||
}.sortedByDescending { it.getLastModifiedTime() }.forEachIndexed { index, it ->
|
||||
println("${index+1}.\t${it.diskFile.absolutePath}")
|
||||
it.rebuild() // disk skimmer was created without initialisation, so do it now
|
||||
it.rebuild()
|
||||
|
||||
val jsonFile = it.getFile(SAVEGAMEINFO)!!
|
||||
val json = JsonReader().parse(ByteArray64Reader(jsonFile.bytes, Common.CHARSET).readText())
|
||||
val playerUUID = UUID.fromString(json.getString("uuid"))
|
||||
var playerUUID: UUID? = null
|
||||
JsonFetcher.readFromJsonString(ByteArray64Reader(jsonFile.bytes, Common.CHARSET)).forEachSiblings { name, value ->
|
||||
if (name == "uuid") playerUUID = UUID.fromString(value.asString())
|
||||
}
|
||||
|
||||
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
||||
if (!App.savegamePlayers.contains(playerUUID)) {
|
||||
App.savegamePlayers[playerUUID] = it
|
||||
App.savegamePlayers[playerUUID] = SavegameCollection.collectFromBaseFilename(File(playersDir), it.diskFile.name)
|
||||
App.savegamePlayersName[playerUUID] = it.getDiskName(Common.CHARSET)
|
||||
App.sortedPlayers.add(playerUUID)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
const val DEFAULT_LOADORDER_FILE = """# Load Order
|
||||
# Modules are loaded from top to bottom.
|
||||
# You can disable basegame, but we don't recommend.
|
||||
# Name of the module corresponds with the name of the directory the module is stored in,
|
||||
# typically under:
|
||||
# 1. assets/mods of the installation path (the modules comes with the release of the game)
|
||||
# 2. %APPDATA%/Modules (the modules installed by the user)
|
||||
# where %APPDATA% is:
|
||||
# Windows -- C:\Users\<username>\AppData\Roaming\Terrarum
|
||||
# macOS -- /Users/<username>/Library/Application Support/Terrarum
|
||||
# Linux -- /home/<username>/.Terrarum
|
||||
# Please refrain from removing 'basegame' on the load order -- it may render the game unpalyable.
|
||||
|
||||
basegame
|
||||
"""
|
||||
|
||||
@@ -33,14 +33,16 @@ class TerrarumScreenSize(scrw: Int = defaultW, scrh: Int = defaultH) {
|
||||
val tvSafeActionWidth: Int; get() = Math.round(width * TV_SAFE_ACTION)
|
||||
val tvSafeActionHeight: Int; get() = Math.round(height * TV_SAFE_ACTION)
|
||||
|
||||
/** Apparent window size. `roundToEven(width * magn)` */
|
||||
var windowW: Int = 0; private set
|
||||
/** Apparent window size. `roundToEven(height * magn)` */
|
||||
var windowH: Int = 0; private set
|
||||
|
||||
init {
|
||||
setDimension(maxOf(minimumW, scrw), maxOf(minimumH, scrh), App.getConfigDouble("screenmagnifying").toFloat(), maxOf(minimumW, scrw), maxOf(minimumH, scrh))
|
||||
setDimension(maxOf(minimumW, scrw), maxOf(minimumH, scrh), App.getConfigDouble("screenmagnifying").toFloat())
|
||||
}
|
||||
|
||||
fun setDimension(scrw: Int, scrh: Int, magn: Float, ww: Int, wh: Int) {
|
||||
fun setDimension(scrw: Int, scrh: Int, magn: Float,) {
|
||||
width = scrw and 0x7FFFFFFE
|
||||
height = scrh and 0x7FFFFFFE
|
||||
wf = scrw.toFloat()
|
||||
@@ -54,11 +56,11 @@ class TerrarumScreenSize(scrw: Int = defaultW, scrh: Int = defaultH) {
|
||||
|
||||
this.magn = magn
|
||||
|
||||
windowW = ww
|
||||
windowH = wh
|
||||
windowW = (scrw * magn).ceilInt() and 0x7FFFFFFE
|
||||
windowH = (scrh * magn).ceilInt() and 0x7FFFFFFE
|
||||
|
||||
|
||||
printdbg(this, "Window dim: $ww x $wh, called by:")
|
||||
printdbg(this, "Window dim: $windowW x $windowH, called by:")
|
||||
printStackTrace(this)
|
||||
}
|
||||
|
||||
|
||||
@@ -136,11 +136,11 @@ class UIItemInventoryCatBar(
|
||||
private val underlineColour = Color(0xeaeaea_40.toInt())
|
||||
private val underlineHighlightColour = mainButtons[0].highlightCol
|
||||
|
||||
private var highlighterXPos = mainButtons[selectedIndex].posX.toFloat()
|
||||
private var highlighterXPos = mainButtons[selectedIndex].posX
|
||||
private var highlighterXStart = highlighterXPos
|
||||
private var highlighterXEnd = highlighterXPos
|
||||
|
||||
private val highlighterYPos = catIcons.tileH + 4f
|
||||
private val highlighterYPos = catIcons.tileH + 4
|
||||
private var highlighterMoving = false
|
||||
private val highlighterMoveDuration: Second = 0.15f
|
||||
private var highlighterMoveTimer: Second = 0f
|
||||
@@ -196,11 +196,11 @@ class UIItemInventoryCatBar(
|
||||
highlighterMoveTimer += delta
|
||||
|
||||
highlighterXPos = Movement.moveQuick(
|
||||
highlighterXStart,
|
||||
highlighterXEnd,
|
||||
highlighterXStart.toFloat(),
|
||||
highlighterXEnd.toFloat(),
|
||||
highlighterMoveTimer,
|
||||
highlighterMoveDuration
|
||||
)
|
||||
).roundToInt()
|
||||
|
||||
if (highlighterMoveTimer > highlighterMoveDuration) {
|
||||
highlighterMoveTimer = 0f
|
||||
@@ -224,10 +224,10 @@ class UIItemInventoryCatBar(
|
||||
// normal stuffs
|
||||
val oldIndex = selectedIndex
|
||||
|
||||
highlighterXStart = mainButtons[selectedIndex].posX.toFloat() // using old selectedIndex
|
||||
highlighterXStart = mainButtons[selectedIndex].posX // using old selectedIndex
|
||||
selectedIndex = index
|
||||
highlighterMoving = true
|
||||
highlighterXEnd = mainButtons[selectedIndex].posX.toFloat() // using new selectedIndex
|
||||
highlighterXEnd = mainButtons[selectedIndex].posX // using new selectedIndex
|
||||
|
||||
selectionChangeListener?.invoke(oldIndex, index)
|
||||
}
|
||||
@@ -290,12 +290,12 @@ class UIItemInventoryCatBar(
|
||||
if (selectedPanel == 1) {
|
||||
// indicator
|
||||
batch.color = underlineHighlightColour
|
||||
batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2).round(), posY + highlighterYPos)
|
||||
batch.draw(underlineIndTex, (highlighterXPos - buttonGapSize / 2), posY + highlighterYPos.toFloat())
|
||||
|
||||
// label
|
||||
batch.color = Color.WHITE
|
||||
catIconsLabels[selectedIcon]().let {
|
||||
App.fontGame.draw(batch, it, posX + ((width - App.fontGame.getWidth(it)) / 2).toFloat(), posY + highlighterYPos + 4)
|
||||
App.fontGame.draw(batch, it, posX + ((width - App.fontGame.getWidth(it)) / 2), posY + highlighterYPos + 4)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
97
src/net/torvald/terrarum/UnserialisableTypeIssueRegistry.kt
Normal file
97
src/net/torvald/terrarum/UnserialisableTypeIssueRegistry.kt
Normal file
@@ -0,0 +1,97 @@
|
||||
package net.torvald.terrarum
|
||||
|
||||
/*import com.android.tools.lint.client.api.IssueRegistry
|
||||
import com.android.tools.lint.client.api.UElementHandler
|
||||
import com.android.tools.lint.detector.api.*
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameitems.GameItem
|
||||
import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.savegame.ByteArray64
|
||||
import net.torvald.terrarum.utils.*
|
||||
import org.jetbrains.uast.UClass
|
||||
import org.jetbrains.uast.UField
|
||||
import org.jetbrains.uast.util.classSetOf
|
||||
import org.jetbrains.uast.util.isInstanceOf
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* https://medium.com/@vanniktech/writing-your-first-lint-check-39ad0e90b9e6
|
||||
* https://medium.com/mobile-app-development-publication/making-custom-lint-for-kotlin-code-8a6c203bf474
|
||||
* https://github.com/googlesamples/android-custom-lint-rules
|
||||
* https://googlesamples.github.io/android-custom-lint-rules/api-guide.html
|
||||
*
|
||||
* Created by minjaesong on 2023-05-22.
|
||||
*/
|
||||
class UnserialisableTypeIssueRegistry : IssueRegistry() {
|
||||
override val issues = listOf(ISSUE_SAVEGAME_UNSERIALISABLE_TYPE_USED_WITHOUT_TRANSIENT)
|
||||
}
|
||||
|
||||
val ISSUE_SAVEGAME_UNSERIALISABLE_TYPE_USED_WITHOUT_TRANSIENT = Issue.create("TerrarumNonTransientUnserialisableType",
|
||||
"Unserialisable Type Used Without Care",
|
||||
"Unserialisable type is used on the potentially serialised class without @Transient annotation",
|
||||
Category.CORRECTNESS,
|
||||
9,
|
||||
Severity.ERROR,
|
||||
Implementation(TerrarumNonTransientUnserialisableType::class.java, EnumSet.of(Scope.JAVA_FILE))
|
||||
)
|
||||
|
||||
class TerrarumNonTransientUnserialisableType : Detector(), Detector.UastScanner {
|
||||
override fun getApplicablePsiTypes() = listOf(UClass::class.java)
|
||||
override fun createUastHandler(context: JavaContext) = TerrarumNonTransientUnserialisableTypeHandler(context)
|
||||
|
||||
class TerrarumNonTransientUnserialisableTypeHandler(private val context: JavaContext) : UElementHandler() {
|
||||
override fun visitClass(clazz: UClass) {
|
||||
/*if (clazz.name?.isDefinedCamelCase() == false) {
|
||||
context.report(ISSUE_SAVEGAME_UNSERIALISABLE_TYPE_USED_WITHOUT_TRANSIENT, clazz,
|
||||
context.getNameLocation(clazz),
|
||||
"Not named in defined camel case.")
|
||||
}*/
|
||||
}
|
||||
|
||||
override fun visitField(node: UField) {
|
||||
if (node.uastParent.isInstanceOf(classSetOf(Actor::class.java, GameItem::class.java)) &&
|
||||
!node.hasAnnotation("Transient") &&
|
||||
!node.isInstanceOf(classSetOf(
|
||||
// primitives
|
||||
String::class.java,
|
||||
Array<String>::class.java,
|
||||
Boolean::class.java,
|
||||
Byte::class.java,
|
||||
ByteArray::class.java,
|
||||
ByteArray64::class.java,
|
||||
Short::class.java,
|
||||
ShortArray::class.java,
|
||||
Int::class.java,
|
||||
IntArray::class.java,
|
||||
Long::class.java,
|
||||
LongArray::class.java,
|
||||
Float::class.java,
|
||||
FloatArray::class.java,
|
||||
Double::class.java,
|
||||
DoubleArray::class.java,
|
||||
// has serialiser on net.torvald.terrarum.serialise.Common
|
||||
BigInteger::class.java,
|
||||
ZipCodedStr::class.java,
|
||||
BlockLayer::class.java,
|
||||
WorldTime::class.java,
|
||||
HashArray::class.java,
|
||||
HashedWirings::class.java,
|
||||
HashedWiringGraph::class.java,
|
||||
WiringGraphMap::class.java,
|
||||
UUID::class.java,
|
||||
HQRNG::class.java,
|
||||
))) {
|
||||
|
||||
context.report(
|
||||
ISSUE_SAVEGAME_UNSERIALISABLE_TYPE_USED_WITHOUT_TRANSIENT,
|
||||
node,
|
||||
context.getNameLocation(node),
|
||||
"Unserialisable type is used on the potentially serialised class without @Transient annotation"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -151,4 +151,8 @@ class WireCodex {
|
||||
|
||||
printdbg(this, "Setting prop ${prop.id} ->>\t${prop.nameKey}")
|
||||
}
|
||||
|
||||
fun getAllWiresThatAccepts(accept: String): List<Pair<ItemID, WireProp>> {
|
||||
return wireProps.filter { it.value.accepts == accept }.toList()
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ object ScreencapNogui: ConsoleCommand {
|
||||
PixmapIO2.writeTGA(Gdx.files.absolute(App.defaultDir + "/Exports/${args[1]}.tga"), p, true)
|
||||
p.dispose()
|
||||
}
|
||||
IngameRenderer.screencapRequested = true
|
||||
IngameRenderer.requestScreencap()
|
||||
Echo("FBO exported to$ccG Exports/${args[1]}.tga")
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -148,5 +148,5 @@ object AVKey {
|
||||
*
|
||||
* example value: `"SIxM+kGlrjZgLx5Zeqz7,;:UIZ5Q=2WT35SgKpOp.,vvf'fNW3G<ROimy(Y;E<,-mdtr5|^RGOqr0x*T*lC,YABr1oQwErKG)pGC'gUG"`
|
||||
*/
|
||||
const val WORLD_PORTAL_DICT = ""
|
||||
const val WORLD_PORTAL_DICT = "worldportaldict"
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package net.torvald.terrarum.gameactors
|
||||
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.ReferencingRanges
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.savegame.toBigEndian
|
||||
import net.torvald.terrarum.utils.PasswordBase32
|
||||
@@ -82,6 +84,9 @@ abstract class Actor : Comparable<Actor>, Runnable {
|
||||
|
||||
if (this is Pocketed)
|
||||
inventory.actor = this
|
||||
if (this is ActorHumanoid && vehicleRidingActorID != null) {
|
||||
vehicleRiding = INGAME.getActorByID(vehicleRidingActorID!!) as Controllable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,10 +13,20 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import kotlin.math.floor
|
||||
|
||||
/**
|
||||
* Used as construction markers and fixture ghost images
|
||||
* Used as construction markers and fixture ghost images.
|
||||
*
|
||||
* `isVisible` behaves differently by `markerMode`.
|
||||
* - FIXTURE_GHOST: `isVisible` toggles if the ghost is being updated. FALSE - will not be updated and also not visible
|
||||
* - BLOCK_MARKER: `isVisible` controls the visibility. FALSE - invisible, TRUE - always visible
|
||||
*
|
||||
* MarkerMode must be set manually after calling `setGhost` -- the `unsetGhost` will not reset the field.
|
||||
*/
|
||||
class BlockMarkerActor : ActorWithBody(Actor.RenderOrder.OVERLAY, physProp = PhysProperties.MOBILE_OBJECT), NoSerialise {
|
||||
|
||||
enum class MarkerMode {
|
||||
FIXTURE_GHOST, BLOCK_MARKER
|
||||
}
|
||||
|
||||
private val defaultSize = 16.0
|
||||
|
||||
override var referenceID: ActorID = 2147483647 // custom refID
|
||||
@@ -29,7 +39,7 @@ class BlockMarkerActor : ActorWithBody(Actor.RenderOrder.OVERLAY, physProp = Phy
|
||||
get() = CommonResourcePool.getAsTextureRegionPack("blockmarkings_common")
|
||||
|
||||
private var ghost: SpriteAnimation? = null
|
||||
private var hasGhost = false
|
||||
var markerMode: MarkerMode = MarkerMode.FIXTURE_GHOST
|
||||
var ghostColour = Color.WHITE
|
||||
|
||||
|
||||
@@ -38,9 +48,10 @@ class BlockMarkerActor : ActorWithBody(Actor.RenderOrder.OVERLAY, physProp = Phy
|
||||
renderOrder = Actor.RenderOrder.OVERLAY // for some reason the constructor didn't work
|
||||
}
|
||||
|
||||
|
||||
override fun drawBody(batch: SpriteBatch) {
|
||||
if (isVisible) {
|
||||
if (hasGhost) {
|
||||
if (markerMode == MarkerMode.FIXTURE_GHOST) {
|
||||
if (INGAME.actorNowPlaying != null) {
|
||||
mouseInInteractableRange(INGAME.actorNowPlaying!!) {
|
||||
batch.shader = App.shaderGhastlyWhite
|
||||
@@ -59,7 +70,7 @@ class BlockMarkerActor : ActorWithBody(Actor.RenderOrder.OVERLAY, physProp = Phy
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (markerMode == MarkerMode.BLOCK_MARKER) {
|
||||
batch.shader = null
|
||||
batch.color = markerColour
|
||||
batch.draw(blockMarkings.get(markerShape, 0), hitbox.startX.toFloat(), hitbox.startY.toFloat())
|
||||
@@ -91,13 +102,12 @@ class BlockMarkerActor : ActorWithBody(Actor.RenderOrder.OVERLAY, physProp = Phy
|
||||
|
||||
fun setGhost(actor: ActorWithBody) {
|
||||
ghost = actor.sprite
|
||||
hasGhost = true
|
||||
markerMode = MarkerMode.FIXTURE_GHOST
|
||||
hitbox.setDimension(actor.baseHitboxW.toDouble(), actor.baseHitboxH.toDouble())
|
||||
}
|
||||
|
||||
fun unsetGhost() {
|
||||
ghost = null
|
||||
hasGhost = false
|
||||
setGhostColourNone()
|
||||
hitbox.setDimension(TILE_SIZED, TILE_SIZED)
|
||||
}
|
||||
|
||||
@@ -241,6 +241,7 @@ object IME {
|
||||
TerrarumIMEConf(name, copying, lang, candidatesCount, if (keysymtable == null) keysyms else null, if (keysymtable == null) null else keysymtable, mode),
|
||||
{ headkey, shifted, alted, lowLayerKeysym ->
|
||||
val a = jsval.invokeMember("accept", headkey, shifted, alted, lowLayerKeysym)
|
||||
// println(a.getArrayElement(0).asString().map { it.code.toString(16) })
|
||||
a.getArrayElement(0).asString().toCanditates() to a.getArrayElement(1).asString()
|
||||
}, {
|
||||
jsval.invokeMember("backspace").asString().toCanditates()
|
||||
|
||||
@@ -29,7 +29,7 @@ class IMEDictionary(private val filename: String) {
|
||||
private var dictLoaded = false
|
||||
|
||||
private fun loadDict() {
|
||||
val reader = FileReader(File("assets/keylayout/", filename))
|
||||
val reader = FileReader(File("assets/keylayout/", filename), Charsets.UTF_8)
|
||||
reader.forEachLine {
|
||||
if (it.contains(',')) {
|
||||
val (key, value) = it.split(',')
|
||||
|
||||
@@ -13,6 +13,9 @@ import net.torvald.terrarum.itemproperties.Material
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.savegame.ByteArray64
|
||||
import net.torvald.terrarum.utils.HashArray
|
||||
import net.torvald.terrarum.utils.ZipCodedStr
|
||||
import org.dyn4j.geometry.Vector2
|
||||
|
||||
typealias ItemID = String
|
||||
|
||||
@@ -39,10 +39,12 @@ class SimpleGameWorld : GameWorld() {
|
||||
override lateinit var layerTerrain: BlockLayer
|
||||
}
|
||||
|
||||
open class GameWorld() : Disposable {
|
||||
open class GameWorld(
|
||||
val worldIndex: UUID // should not be immutable as JSON loader will want to overwrite it
|
||||
) : Disposable {
|
||||
|
||||
constructor() : this(UUID.randomUUID())
|
||||
|
||||
// var worldName: String = "New World"
|
||||
var worldIndex: UUID = UUID.randomUUID() // should not be immutable as JSON loader will want to overwrite it
|
||||
var worldCreator: UUID = UUID(0L,0L) // TODO record a value to this
|
||||
var width: Int = 999; private set
|
||||
var height: Int = 999; private set
|
||||
@@ -387,14 +389,14 @@ open class GameWorld() : Disposable {
|
||||
return wiringGraph[blockAddr]?.get(itemID)?.emt
|
||||
}
|
||||
|
||||
fun getWireRecvStateOf(x: Int, y: Int, itemID: ItemID): ArrayList<WireRecvState>? {
|
||||
fun getWireReceptionStateOf(x: Int, y: Int, itemID: ItemID): ArrayList<WireReceptionState>? {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||
return getWireRecvStateUnsafe(blockAddr, itemID)
|
||||
return getWireReceptionStateUnsafe(blockAddr, itemID)
|
||||
}
|
||||
|
||||
fun getWireRecvStateUnsafe(blockAddr: BlockAddress, itemID: ItemID): ArrayList<WireRecvState>? {
|
||||
return wiringGraph[blockAddr]?.get(itemID)?.rcv
|
||||
fun getWireReceptionStateUnsafe(blockAddr: BlockAddress, itemID: ItemID): ArrayList<WireReceptionState>? {
|
||||
return wiringGraph[blockAddr]?.get(itemID)?.rcp
|
||||
}
|
||||
|
||||
fun setWireGraphOf(x: Int, y: Int, itemID: ItemID, cnx: Int) {
|
||||
@@ -427,7 +429,7 @@ open class GameWorld() : Disposable {
|
||||
wiringGraph[blockAddr]!![itemID]!!.emt.set(vector)
|
||||
}
|
||||
|
||||
fun addWireRecvStateOf(x: Int, y: Int, itemID: ItemID, state: WireRecvState) {
|
||||
fun addWireRecvStateOf(x: Int, y: Int, itemID: ItemID, state: WireReceptionState) {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||
return addWireRecvStateOfUnsafe(blockAddr, itemID, state)
|
||||
@@ -439,13 +441,13 @@ open class GameWorld() : Disposable {
|
||||
return clearAllWireRecvStateUnsafe(blockAddr)
|
||||
}
|
||||
|
||||
fun addWireRecvStateOfUnsafe(blockAddr: BlockAddress, itemID: ItemID, state: WireRecvState) {
|
||||
fun addWireRecvStateOfUnsafe(blockAddr: BlockAddress, itemID: ItemID, state: WireReceptionState) {
|
||||
if (wiringGraph[blockAddr] == null)
|
||||
wiringGraph[blockAddr] = WiringGraphMap()
|
||||
if (wiringGraph[blockAddr]!![itemID] == null)
|
||||
wiringGraph[blockAddr]!![itemID] = WiringSimCell(0)
|
||||
|
||||
wiringGraph[blockAddr]!![itemID]!!.rcv.add(state)
|
||||
wiringGraph[blockAddr]!![itemID]!!.rcp.add(state)
|
||||
}
|
||||
|
||||
fun getAllWiringGraph(x: Int, y: Int): HashMap<ItemID, WiringSimCell>? {
|
||||
@@ -460,7 +462,7 @@ open class GameWorld() : Disposable {
|
||||
|
||||
fun clearAllWireRecvStateUnsafe(blockAddr: BlockAddress) {
|
||||
wiringGraph[blockAddr]?.forEach {
|
||||
it.value.rcv.clear()
|
||||
it.value.rcp.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +654,7 @@ open class GameWorld() : Disposable {
|
||||
val ws: SortedArrayList<ItemID> = SortedArrayList<ItemID>() // what could possibly go wrong bloating up the RAM footprint when it's practically infinite these days?
|
||||
)
|
||||
|
||||
data class WireRecvState(
|
||||
data class WireReceptionState(
|
||||
var dist: Int = -1, // how many tiles it took to traverse
|
||||
var src: Point2i = Point2i(0,0) // xy position
|
||||
// to get the state, use the src to get the state of the source emitter directly, then use dist to apply attenuation
|
||||
@@ -664,7 +666,7 @@ open class GameWorld() : Disposable {
|
||||
data class WiringSimCell(
|
||||
var cnx: Int = 0, // connections. [1, 2, 4, 8] = [RIGHT, DOWN, LEFT, UP]
|
||||
val emt: Vector2 = Vector2(0.0, 0.0), // i'm emitting this much power
|
||||
val rcv: ArrayList<WireRecvState> = ArrayList() // how far away are the power sources
|
||||
val rcp: ArrayList<WireReceptionState> = ArrayList() // how far away are the power sources
|
||||
)
|
||||
|
||||
fun getTemperature(worldTileX: Int, worldTileY: Int): Float? {
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.torvald.terrarum.gameworld
|
||||
import com.badlogic.gdx.utils.Queue
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
@@ -468,14 +469,15 @@ object WorldSimulator {
|
||||
/**
|
||||
* @return List of FixtureBases, safe to cast into Electric
|
||||
*/
|
||||
private fun wiresimGetSourceBlocks(): List<FixtureBase> =
|
||||
INGAME.actorContainerActive.filterIsInstance<FixtureBase>().filter {
|
||||
it is Electric && it.inUpdateRange(world) && it.wireEmitterTypes.isNotEmpty()
|
||||
private fun wiresimGetSourceBlocks(): List<Electric> =
|
||||
INGAME.actorContainerActive.filterIsInstance<Electric>().filter {
|
||||
it.inUpdateRange(world) && it.wireEmitterTypes.isNotEmpty()
|
||||
}
|
||||
|
||||
private val wireSimMarked = HashSet<Long>()
|
||||
private val wireSimPoints = Queue<WireGraphCursor>()
|
||||
private val oldTraversedNodes = ArrayList<WireGraphCursor>()
|
||||
private val fixtureCache = HashMap<Point2i, Pair<Electric, WireEmissionType>>() // also instance of Electric
|
||||
|
||||
private fun simulateWires(delta: Float) {
|
||||
// unset old wires before we begin
|
||||
@@ -484,14 +486,15 @@ object WorldSimulator {
|
||||
}
|
||||
|
||||
oldTraversedNodes.clear()
|
||||
fixtureCache.clear()
|
||||
|
||||
wiresimGetSourceBlocks().let { sources ->
|
||||
// signal-emitting fixtures must set emitState of its own tiles via update()
|
||||
sources.forEach {
|
||||
(it as Electric).wireEmitterTypes.forEach { wireType, bbi ->
|
||||
it.wireEmitterTypes.forEach { bbi, wireType ->
|
||||
|
||||
val startingPoint = it.worldBlockPos!! + it.blockBoxIndexToPoint2i(bbi)
|
||||
val signal = (it as Electric).wireEmission[bbi] ?: Vector2(0.0, 0.0)
|
||||
val signal = it.wireEmission[bbi] ?: Vector2(0.0, 0.0)
|
||||
|
||||
world.getAllWiringGraph(startingPoint.x, startingPoint.y)?.keys?.filter { WireCodex[it].accepts == wireType }?.forEach { wire ->
|
||||
val simStartingPoint = WireGraphCursor(startingPoint, wire)
|
||||
@@ -506,6 +509,8 @@ object WorldSimulator {
|
||||
|
||||
private fun traverseWireGraph(world: GameWorld, wire: ItemID, startingPoint: WireGraphCursor, signal: Vector2) {
|
||||
|
||||
val emissionType = WireCodex[wire].accepts
|
||||
|
||||
fun getAdjacent(cnx: Int, point: WireGraphCursor): List<WireGraphCursor> {
|
||||
val r = ArrayList<WireGraphCursor>()
|
||||
for (dir in intArrayOf(RIGHT, DOWN, LEFT, UP)) {
|
||||
@@ -540,6 +545,28 @@ object WorldSimulator {
|
||||
enq(x)
|
||||
}
|
||||
}
|
||||
|
||||
// do something with the power receiver
|
||||
val tilePoint = Point2i(point.x, point.y)
|
||||
var fixture = fixtureCache[tilePoint]
|
||||
var tileOffsetFromFixture: Point2i? = null
|
||||
if (fixture == null) {
|
||||
INGAME.getActorsAt(point.x * TILE_SIZED, point.y * TILE_SIZED).filterIsInstance<Electric>().firstOrNull().let { found ->
|
||||
if (found != null) {
|
||||
// get offset from the fixture's origin
|
||||
tileOffsetFromFixture = found.intTilewiseHitbox.let { Point2i(it.startX.toInt(), it.startY.toInt()) } - tilePoint
|
||||
|
||||
// println("$tilePoint; ${found.javaClass.canonicalName}, $tileOffsetFromFixture, ${found.getWireSinkAt(tileOffsetFromFixture!!)}")
|
||||
|
||||
if (found.getWireSinkAt(tileOffsetFromFixture!!) == emissionType) {
|
||||
fixtureCache[tilePoint] = found to emissionType
|
||||
fixture = found to emissionType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fixture?.first?.updateOnWireGraphTraversal(tileOffsetFromFixture!!.x, tileOffsetFromFixture!!.y, fixture!!.second)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,9 @@ object Lang {
|
||||
|
||||
private val bindOp = ">>="
|
||||
|
||||
fun getOrNull(key: String?, capitalise: Boolean = true) =
|
||||
if (key == null) null else get(key, capitalise)
|
||||
|
||||
/**
|
||||
* Syntax example:
|
||||
*
|
||||
|
||||
@@ -28,14 +28,8 @@ class EntryPoint : ModuleEntryPoint() {
|
||||
printdbg(this, "Hello, world!")
|
||||
|
||||
// load common resources to the AssetsManager
|
||||
CommonResourcePool.addToLoadingList("$moduleName.items16") {
|
||||
TextureRegionPack(ModMgr.getGdxFile(moduleName, "items/items.tga"), 16, 16)
|
||||
}
|
||||
CommonResourcePool.addToLoadingList("$moduleName.items24") {
|
||||
TextureRegionPack(ModMgr.getGdxFile(moduleName, "items/items24.tga"), 24, 24)
|
||||
}
|
||||
CommonResourcePool.addToLoadingList("$moduleName.items48") {
|
||||
TextureRegionPack(ModMgr.getGdxFile(moduleName, "items/items48.tga"), 48, 48)
|
||||
CommonResourcePool.addToLoadingList("$moduleName.items") {
|
||||
ItemSheet(ModMgr.getGdxFile(moduleName, "items/items.tga"))
|
||||
}
|
||||
CommonResourcePool.loadAll()
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.badlogic.gdx.utils.Disposable
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.measureDebugTime
|
||||
import net.torvald.terrarum.App.*
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
@@ -21,6 +21,7 @@ import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.weather.WeatherMixer.render
|
||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
@@ -204,7 +205,7 @@ object IngameRenderer : Disposable {
|
||||
actorsRenderOverlay: List<ActorWithBody>,
|
||||
particlesContainer : CircularArray<ParticleBase>,
|
||||
player: ActorWithBody? = null,
|
||||
uiContainer: UIContainer? = null
|
||||
uiContainer: UIContainer? = null,
|
||||
) {
|
||||
renderingActorsCount = (actorsRenderBehind.size) +
|
||||
(actorsRenderMiddle.size) +
|
||||
@@ -365,13 +366,19 @@ object IngameRenderer : Disposable {
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (screencapRequested) {
|
||||
screencapRequested = false
|
||||
printdbg(this, "Screencap was requested, processing...")
|
||||
var hasError = false
|
||||
try {
|
||||
screencapExportCallback(fboMixedOut)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
printdbgerr(this, "An error occured while taking screencap:")
|
||||
e.printStackTrace()
|
||||
hasError = true
|
||||
}
|
||||
printdbg(this, "Screencap ${if (hasError) "failed" else "successful"}")
|
||||
screencapBusy = false
|
||||
screencapRequested = false
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@@ -416,11 +423,18 @@ object IngameRenderer : Disposable {
|
||||
* This "screencap" will capture the game WITHOUT gui and postprocessors!
|
||||
* To capture the entire game, use [App.requestScreenshot]
|
||||
*/
|
||||
@Volatile internal var screencapRequested = false
|
||||
@Volatile internal var fboRGBexportedLatch = false
|
||||
@Volatile private var screencapRequested = false
|
||||
@Volatile internal var screencapBusy = false; private set
|
||||
@Volatile internal var screencapExportCallback: (FrameBuffer) -> Unit = {}
|
||||
@Volatile internal lateinit var fboRGBexport: Pixmap
|
||||
|
||||
fun requestScreencap() {
|
||||
screencapRequested = true
|
||||
screencapBusy = true
|
||||
printdbg(this, "requestScreencap called from:")
|
||||
printStackTrace(this)
|
||||
}
|
||||
|
||||
private fun drawToRGB(
|
||||
actorsRenderBehind: List<ActorWithBody>?,
|
||||
actorsRenderMiddle: List<ActorWithBody>?,
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.torvald.terrarum.modulebasegame
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.Camera
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.*
|
||||
@@ -26,6 +27,7 @@ import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.WorldSimulator
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver
|
||||
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
||||
@@ -34,6 +36,7 @@ import net.torvald.terrarum.modulebasegame.serialise.LoadSavegame
|
||||
import net.torvald.terrarum.modulebasegame.serialise.ReadActor
|
||||
import net.torvald.terrarum.modulebasegame.serialise.WriteSavegame
|
||||
import net.torvald.terrarum.modulebasegame.ui.*
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.gradEndCol
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams
|
||||
@@ -42,6 +45,7 @@ import net.torvald.terrarum.savegame.VDUtil
|
||||
import net.torvald.terrarum.savegame.VirtualDisk
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.ui.Toolkit.hdrawWidth
|
||||
import net.torvald.terrarum.ui.UIAutosaveNotifier
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
@@ -53,6 +57,7 @@ import net.torvald.unicode.EMDASH
|
||||
import net.torvald.util.CircularArray
|
||||
import org.khelekore.prtree.PRTree
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
/**
|
||||
@@ -144,10 +149,11 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
val SIZE_NORMAL = Point2i(9000, 2250)
|
||||
val SIZE_LARGE = Point2i(13500, 2970)
|
||||
val SIZE_HUGE = Point2i(22500, 4500)
|
||||
val WORLDSIZE = if (App.IS_DEVELOPMENT_BUILD)
|
||||
arrayOf(Point2i(2880, 1350), SIZE_SMALL, SIZE_NORMAL, SIZE_LARGE, SIZE_HUGE)
|
||||
val NEW_WORLD_SIZE = if (App.IS_DEVELOPMENT_BUILD)
|
||||
arrayOf(Point2i(2880, 1350), /*SIZE_SMALL, */SIZE_NORMAL, SIZE_LARGE, SIZE_HUGE)
|
||||
else
|
||||
arrayOf(SIZE_SMALL, SIZE_NORMAL, SIZE_LARGE, SIZE_HUGE)
|
||||
arrayOf(/*SIZE_SMALL, */SIZE_NORMAL, SIZE_LARGE, SIZE_HUGE)
|
||||
val WORLDPORTAL_NEW_WORLD_SIZE = arrayOf(SIZE_SMALL, SIZE_NORMAL, SIZE_LARGE, SIZE_HUGE)
|
||||
|
||||
val worldgenThreadExecutor = ThreadExecutor()
|
||||
}
|
||||
@@ -259,7 +265,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
|
||||
IngameRenderer.setRenderedWorld(world)
|
||||
|
||||
blockMarkingActor.isVisible = true
|
||||
|
||||
super.show() // this function sets gameInitialised = true
|
||||
}
|
||||
@@ -417,10 +423,15 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
// 2. cannot sync up the "counter" to determine whether both are finished
|
||||
uiAutosaveNotifier.setAsOpen()
|
||||
val saveTime_t = App.getTIME_T()
|
||||
printdbg(this, "Immediate Save")
|
||||
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.PLAYER, playerDisk, getPlayerSaveFiledesc(playerSavefileName), this, true, autosaveOnErrorAction) {
|
||||
printdbg(this, "immediate save callback from PLAYER")
|
||||
|
||||
makeSavegameBackupCopy(getPlayerSaveFiledesc(playerSavefileName))
|
||||
|
||||
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.WORLD, worldDisk, getWorldSaveFiledesc(worldSavefileName), this, true, autosaveOnErrorAction) {
|
||||
printdbg(this, "immediate save callback from WORLD")
|
||||
|
||||
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName)) // don't put it on the postInit() or render(); must be called using callback
|
||||
uiAutosaveNotifier.setAsClose()
|
||||
}
|
||||
@@ -469,13 +480,14 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
world.worldCreator = UUID.fromString(player.uuid.toString())
|
||||
|
||||
printdbg(this, "new woridIndex: ${world.worldIndex}")
|
||||
printdbg(this, "new worldIndex: ${world.worldIndex}")
|
||||
printdbg(this, "worldCurrentlyPlaying: ${player.worldCurrentlyPlaying}")
|
||||
|
||||
actorNowPlaying = player
|
||||
actorGamer = player
|
||||
forceAddActor(player)
|
||||
|
||||
WeatherMixer.internalReset()
|
||||
}
|
||||
|
||||
KeyToggler.forceSet(Input.Keys.Q, false)
|
||||
@@ -520,7 +532,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
// pie menu
|
||||
uiPieMenu = UIQuickslotPie()
|
||||
uiPieMenu.setPosition(drawWidth / 2, App.scr.halfh)
|
||||
uiPieMenu.setPosition(hdrawWidth, App.scr.halfh)
|
||||
|
||||
// vital metre
|
||||
// fill in getter functions by
|
||||
@@ -654,21 +666,21 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
// what if there's multiple of such fixtures? whatever, you are supposed to DISALLOW such situation.
|
||||
for (kk in actorsUnderMouse.indices) {
|
||||
if (mouseInInteractableRange(actor) {
|
||||
actorsUnderMouse[kk].mainUI?.let {
|
||||
uiOpened = true
|
||||
actorsUnderMouse[kk].mainUI?.let {
|
||||
uiOpened = true
|
||||
|
||||
// property 'uiFixture' is a dedicated property that the TerrarumIngame recognises.
|
||||
// when it's not null, the UI will be updated and rendered
|
||||
// when the UI is closed, it'll be replaced with a null value
|
||||
uiFixture = it
|
||||
it.setPosition(
|
||||
(Toolkit.drawWidth - it.width) / 4,
|
||||
(App.scr.height - it.height) / 4 // what the fuck?
|
||||
)
|
||||
it.setAsOpen()
|
||||
}
|
||||
0L
|
||||
} == 0L) break
|
||||
// property 'uiFixture' is a dedicated property that the TerrarumIngame recognises.
|
||||
// when it's not null, the UI will be updated and rendered
|
||||
// when the UI is closed, it'll be replaced with a null value
|
||||
uiFixture = it
|
||||
it.setPosition(
|
||||
(Toolkit.drawWidth - it.width) / 4,
|
||||
(App.scr.height - it.height) / 4 // what the fuck?
|
||||
)
|
||||
it.setAsOpen()
|
||||
}
|
||||
0L
|
||||
} == 0L) break
|
||||
}
|
||||
|
||||
if (!uiOpened) {
|
||||
@@ -714,6 +726,10 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
gameUpdateGovernor.reset()
|
||||
|
||||
if (UILoadGovernor.previousSaveWasLoaded) {
|
||||
sendNotification(listOf(Lang["GAME_PREV_SAVE_WAS_LOADED1"], Lang["GAME_PREV_SAVE_WAS_LOADED2"]))
|
||||
}
|
||||
|
||||
gameFullyLoaded = true
|
||||
}
|
||||
|
||||
@@ -850,7 +866,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
//notifier.update(delta)
|
||||
// open/close fake blur UI according to what's opened
|
||||
if (uiInventoryPlayer.isVisible ||
|
||||
getUIFixture.get()?.isVisible == true) {
|
||||
getUIFixture.get()?.isVisible == true || worldTransitionOngoing) {
|
||||
uiBlur.setAsOpen()
|
||||
}
|
||||
else {
|
||||
@@ -866,6 +882,26 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
//println("paused = $paused")
|
||||
|
||||
if ((!paused && !App.isScreenshotRequested()) && newWorldLoadedLatch) newWorldLoadedLatch = false
|
||||
|
||||
|
||||
if (doThingsAfterSave) {
|
||||
saveRequested2 = false
|
||||
doThingsAfterSave = false
|
||||
saveCallback!!()
|
||||
}
|
||||
|
||||
if (saveRequested2) {
|
||||
saveRequested2 = false
|
||||
doForceSave()
|
||||
}
|
||||
|
||||
if (worldTransitionPauseRequested > 0) { // let a frame to update before locking (=pausing) entirely
|
||||
worldTransitionPauseRequested -= 1
|
||||
}
|
||||
else if (worldTransitionPauseRequested == 0) {
|
||||
paused = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -900,6 +936,93 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
actorNowPlaying,
|
||||
uiContainer// + uiFixture
|
||||
)
|
||||
|
||||
// quick and dirty way to show
|
||||
if (worldTransitionOngoing) {
|
||||
batch.inUse {
|
||||
batch.color = gradEndCol
|
||||
Toolkit.fillArea(batch, 0, 0, App.scr.width, App.scr.height)
|
||||
|
||||
|
||||
batch.color = Color.WHITE
|
||||
val t = Lang["MENU_IO_SAVING"]
|
||||
val circleSheet = CommonResourcePool.getAsTextureRegionPack("loading_circle_64")
|
||||
Toolkit.drawTextCentered(batch, App.fontGame, t, Toolkit.drawWidth, 0, ((App.scr.height - circleSheet.tileH) / 2) - 40)
|
||||
|
||||
// -1..63
|
||||
val index =
|
||||
((WriteSavegame.saveProgress / WriteSavegame.saveProgressMax) * circleSheet.horizontalCount * circleSheet.verticalCount).roundToInt() - 1
|
||||
if (index >= 0) {
|
||||
val sx = index % circleSheet.horizontalCount
|
||||
val sy = index / circleSheet.horizontalCount
|
||||
// q&d fix for ArrayIndexOutOfBoundsException caused when saving huge world... wut?
|
||||
if (sx in 0 until circleSheet.horizontalCount && sy in 0 until circleSheet.horizontalCount) {
|
||||
batch.draw(
|
||||
circleSheet.get(sx, sy),
|
||||
((Toolkit.drawWidth - circleSheet.tileW) / 2).toFloat(),
|
||||
((App.scr.height - circleSheet.tileH) / 2).toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var worldTransitionOngoing = false
|
||||
private var worldTransitionPauseRequested = -1
|
||||
private var saveRequested2 = false
|
||||
private var saveCallback: (() -> Unit)? = null
|
||||
private var doThingsAfterSave = false
|
||||
|
||||
override fun requestForceSave(callback: () -> Unit) {
|
||||
saveCallback = callback
|
||||
worldTransitionOngoing = true
|
||||
saveRequested2 = true
|
||||
worldTransitionPauseRequested = 1
|
||||
blockMarkingActor.isVisible = false
|
||||
}
|
||||
|
||||
internal fun doForceSave() {
|
||||
// TODO show appropriate UI
|
||||
// uiBlur.setAsOpen()
|
||||
|
||||
saveTheGame({ // onSuccessful
|
||||
System.gc()
|
||||
autosaveTimer = 0f
|
||||
|
||||
// TODO hide appropriate UI
|
||||
uiBlur.setAsClose()
|
||||
doThingsAfterSave = true
|
||||
}, { // onError
|
||||
// TODO show failure message
|
||||
|
||||
// TODO hide appropriate UI
|
||||
uiBlur.setAsClose()
|
||||
})
|
||||
}
|
||||
|
||||
override fun saveTheGame(onSuccessful: () -> Unit, onError: (Throwable) -> Unit) {
|
||||
val saveTime_t = App.getTIME_T()
|
||||
val playerSavefile = getPlayerSaveFiledesc(INGAME.playerSavefileName)
|
||||
val worldSavefile = getWorldSaveFiledesc(INGAME.worldSavefileName)
|
||||
|
||||
|
||||
INGAME.makeSavegameBackupCopy(playerSavefile)
|
||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.PLAYER, INGAME.playerDisk, playerSavefile, INGAME as TerrarumIngame, false, onError) {
|
||||
|
||||
INGAME.makeSavegameBackupCopy(worldSavefile)
|
||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.WORLD, INGAME.worldDisk, worldSavefile, INGAME as TerrarumIngame, false, onError) {
|
||||
// callback:
|
||||
// rebuild the disk skimmers
|
||||
INGAME.actorContainerActive.filterIsInstance<IngamePlayer>().forEach {
|
||||
printdbg(this, "Game Save callback -- rebuilding the disk skimmer for IngamePlayer ${it.actorValue.getAsString(AVKey.NAME)}")
|
||||
// it.rebuildingDiskSkimmer?.rebuild()
|
||||
}
|
||||
|
||||
// return to normal state
|
||||
onSuccessful()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val maxRenderableWires = ReferencingRanges.ACTORS_WIRES.last - ReferencingRanges.ACTORS_WIRES.first + 1
|
||||
@@ -1106,13 +1229,13 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
uiAutosaveNotifier.setAsOpen()
|
||||
|
||||
val saveTime_t = App.getTIME_T()
|
||||
val playerSavefile = getPlayerSaveFiledesc(INGAME.playerSavefileName)
|
||||
val worldSavefile = getWorldSaveFiledesc(INGAME.worldSavefileName)
|
||||
val playerSavefile0 = getPlayerSaveFiledesc(INGAME.playerSavefileName)
|
||||
val worldSavefile0 = getWorldSaveFiledesc(INGAME.worldSavefileName)
|
||||
|
||||
INGAME.makeSavegameBackupCopy(playerSavefile)
|
||||
val playerSavefile = INGAME.makeSavegameBackupCopyAuto(playerSavefile0)
|
||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.PLAYER, INGAME.playerDisk, playerSavefile, INGAME as TerrarumIngame, true, autosaveOnErrorAction) {
|
||||
|
||||
INGAME.makeSavegameBackupCopy(worldSavefile)
|
||||
val worldSavefile = INGAME.makeSavegameBackupCopyAuto(worldSavefile0)
|
||||
WriteSavegame(saveTime_t, WriteSavegame.SaveMode.QUICK_WORLD, INGAME.worldDisk, worldSavefile, INGAME as TerrarumIngame, true, autosaveOnErrorAction) {
|
||||
// callback:
|
||||
// rebuild the disk skimmers
|
||||
@@ -1263,9 +1386,9 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
val fixturesUnderHand = ArrayList<FixtureBase>()
|
||||
val mobsUnderHand = ArrayList<ActorWithBody>()
|
||||
actorsUnderMouse.forEach {
|
||||
if (it is FixtureBase && it.mainUI == null)
|
||||
if (it is FixtureBase) // && it.mainUI == null) // pickup avail check must be done against fixture.canBeDespawned
|
||||
fixturesUnderHand.add(it)
|
||||
else
|
||||
else if (it !is FixtureBase)
|
||||
mobsUnderHand.add(it)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum.modulebasegame
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.InputAdapter
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
@@ -13,17 +14,20 @@ import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.App.printdbgerr
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||
import net.torvald.terrarum.console.CommandDict
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gameactors.ai.ActorAI
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
||||
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
@@ -64,50 +68,72 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
private lateinit var demoWorld: GameWorld
|
||||
private lateinit var cameraNodes: FloatArray // camera Y-pos
|
||||
private val cameraNodeWidth = 15
|
||||
private val lookaheadDist = cameraNodeWidth * TILE_SIZED
|
||||
private fun getPointAt(px: Double): Double {
|
||||
val ww = TILE_SIZEF * demoWorld.width
|
||||
val x = px % ww
|
||||
|
||||
val indexThis = ((x / ww * cameraNodes.size).floorInt())
|
||||
val xwstart: Double = indexThis.toDouble() / cameraNodes.size * ww
|
||||
val xwend: Double = ((indexThis + 1).toDouble() / cameraNodes.size) * ww
|
||||
val xw: Double = xwend - xwstart
|
||||
val xperc: Double = (x - xwstart) / xw
|
||||
|
||||
// return FastMath.interpolateLinear(xperc.toFloat(), cameraNodes[indexThis fmod cameraNodes.size], cameraNodes[(indexThis + 1) fmod cameraNodes.size]).toDouble()
|
||||
return FastMath.interpolateCatmullRom(xperc.toFloat(),
|
||||
cameraNodes[(indexThis - 1) fmod cameraNodes.size],
|
||||
cameraNodes[(indexThis - 0) fmod cameraNodes.size],
|
||||
cameraNodes[(indexThis + 1) fmod cameraNodes.size],
|
||||
cameraNodes[(indexThis + 2) fmod cameraNodes.size]
|
||||
).toDouble()
|
||||
}
|
||||
private val cameraAI = object : ActorAI {
|
||||
|
||||
private var firstTime = true
|
||||
private val lookaheadDist = 100.0
|
||||
|
||||
private fun getPointAt(px: Double): Float {
|
||||
val ww = TILE_SIZEF * demoWorld.width
|
||||
val x = px % ww
|
||||
|
||||
val indexThis = ((x / ww * cameraNodes.size).floorInt()) fmod cameraNodes.size
|
||||
val xwstart: Float = indexThis.toFloat() / cameraNodes.size * ww
|
||||
val xwend: Float = ((indexThis + 1).toFloat() / cameraNodes.size) * ww
|
||||
val xw: Float = xwend - xwstart
|
||||
val xperc: Double = (x - xwstart) / xw
|
||||
|
||||
return FastMath.interpolateLinear(xperc.toFloat(), cameraNodes[indexThis], cameraNodes[(indexThis + 1) % cameraNodes.size])
|
||||
}
|
||||
|
||||
override fun update(actor: Actor, delta: Float) {
|
||||
val ww = TILE_SIZEF * demoWorld.width
|
||||
val actor = actor as CameraPlayer
|
||||
|
||||
val px: Double = actor.hitbox.canonicalX + actor.actorValue.getAsDouble(AVKey.SPEED)!!
|
||||
val pxP = px - lookaheadDist * cos(actor.targetBearing)
|
||||
val pxN = px + lookaheadDist * cos(actor.targetBearing)
|
||||
val stride = cos(actor.bearing1A) * actor.actorValue.getAsDouble(AVKey.SPEED)!!
|
||||
|
||||
val yP = getPointAt(pxP)
|
||||
val yN = getPointAt(pxN)
|
||||
val x1 = actor.hitbox.startX// + stride
|
||||
val y1 = actor.hitbox.startY
|
||||
|
||||
val y = (yP + yN) / 2f
|
||||
val px1L = x1 - lookaheadDist
|
||||
val px1C = x1
|
||||
val px1R = x1 + lookaheadDist
|
||||
val py1L = getPointAt(px1L)
|
||||
val py1C = getPointAt(px1C)
|
||||
val py1R = getPointAt(px1R)
|
||||
|
||||
val px2L = (px1L + px1C) / 2.0
|
||||
val px2R = (px1C + px1R) / 2.0
|
||||
val py2L = (py1L + py1C) / 2.0
|
||||
val py2R = (py1C + py1R) / 2.0
|
||||
|
||||
val x2 = (px2L + px2R) / 2
|
||||
val y2 = (py2L + py2R) / 2
|
||||
|
||||
val theta = atan2(py2R - py2L, px2R - px2L)
|
||||
|
||||
if (firstTime) {
|
||||
firstTime = false
|
||||
actor.hitbox.setPositionY(y - 8.0)
|
||||
actor.hitbox.setPosition(x1, getPointAt(x1))
|
||||
}
|
||||
else {
|
||||
//actor.moveTo(px, y - 8.0)
|
||||
//actor.hitbox.setPosition(px, y - 8.0)
|
||||
actor.moveTo(atan2((yN - yP).toDouble(), pxN - pxP))
|
||||
actor.bearing1A = atan2(py1C - py1L, px1C - px1L)
|
||||
actor.bearing1B = atan2(py1R - py1C, px1R - px1C)
|
||||
actor.bearing2A = atan2(py2R - py2L, px2R - px2L)
|
||||
actor.moveTo(theta)
|
||||
// actor.hitbox.setPosition(x2, y2) // there is no reason it would work -- speed is wildly inconsistent as the angle reaches 90deg
|
||||
}
|
||||
|
||||
if (actor.hitbox.canonicalX > ww) {
|
||||
if (actor.hitbox.startX > ww) {
|
||||
actor.hitbox.translatePosX(-ww.toDouble())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
private lateinit var cameraPlayer: ActorWithBody
|
||||
@@ -123,9 +149,9 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
private lateinit var worldFBO: FloatFrameBuffer
|
||||
|
||||
private val warning32bitJavaIcon = TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/32_bit_warning.tga")))
|
||||
private val warningAppleRosettaIcon = TextureRegion(Texture(Gdx.files.internal("assets/graphics/gui/apple_rosetta_warning.tga")))
|
||||
|
||||
init {
|
||||
warning32bitJavaIcon.flip(false, false)
|
||||
gameUpdateGovernor = ConsistentUpdateRate.also { it.reset() }
|
||||
}
|
||||
|
||||
@@ -139,7 +165,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||
val world = ReadSimpleWorld(reader, file)
|
||||
demoWorld = world
|
||||
demoWorld.worldTime.timeDelta = 0//60
|
||||
demoWorld.worldTime.timeDelta = 330 // a year = 8 minutes
|
||||
printdbg(this, "Demo world loaded")
|
||||
}
|
||||
catch (e: IOException) {
|
||||
@@ -153,7 +179,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
||||
|
||||
// construct camera nodes
|
||||
val nodeCount = demoWorld.width / 10
|
||||
val nodeCount = demoWorld.width / cameraNodeWidth
|
||||
cameraNodes = kotlin.FloatArray(nodeCount) {
|
||||
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
|
||||
var travelDownCounter = 0
|
||||
@@ -238,6 +264,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
printdbg(this, "update list of savegames")
|
||||
// to show "Continue" and "Load" on the titlescreen, uncomment this line
|
||||
App.updateListOfSavegames()
|
||||
UILoadGovernor.reset()
|
||||
|
||||
|
||||
loadThingsWhileIntroIsVisible()
|
||||
@@ -254,9 +281,14 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
|
||||
private val updateScreen = { delta: Float ->
|
||||
demoWorld.globalLight = WeatherMixer.globalLightNow
|
||||
// TODO: desynched weather and time-of-day change
|
||||
|
||||
val forcedTime = 39693
|
||||
// demoWorld.globalLight = WeatherMixer.globalLightNow
|
||||
demoWorld.globalLight = WeatherMixer.getGlobalLightOfTime(demoWorld, forcedTime)
|
||||
demoWorld.updateWorldTime(delta)
|
||||
WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
||||
// WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
||||
WeatherMixer.forceTimeAt = forcedTime
|
||||
cameraPlayer.update(delta)
|
||||
|
||||
// worldcamera update AFTER cameraplayer in this case; the other way is just an exception for actual ingame SFX
|
||||
@@ -269,6 +301,24 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
private val particles = CircularArray<ParticleBase>(16, true)
|
||||
|
||||
private fun drawLineOnWorld(x1: Float, y1: Float, x2: Float, y2: Float) {
|
||||
val w = 2.0f
|
||||
App.shapeRender.rectLine(
|
||||
x1 - WorldCamera.x, App.scr.height - (y1 - WorldCamera.y),
|
||||
x2 - WorldCamera.x, App.scr.height - (y2 - WorldCamera.y),
|
||||
w
|
||||
)
|
||||
}
|
||||
private fun drawLineOnWorld(x1: Double, y1: Double, x2: Double, y2: Double) {
|
||||
val ww = demoWorld.width * TILE_SIZE
|
||||
drawLineOnWorld(x1.toFloat(), y1.toFloat(), x2.toFloat(), y2.toFloat())
|
||||
drawLineOnWorld(x1.toFloat() + ww, y1.toFloat(), x2.toFloat() + ww, y2.toFloat())
|
||||
}
|
||||
|
||||
private val baseSlopeCol = Color(0f, 0.9f, 0.85f, 1f)
|
||||
private val firstOrderSlopeCol = Color(0f, 0.4f, 0f, 1f)
|
||||
private val secondOrderSlopeCol = Color(1f, 0.3f, 0.6f, 1f)
|
||||
|
||||
private val renderScreen = { delta: Float ->
|
||||
Gdx.graphics.setTitle(TerrarumIngame.getCanonicalTitle())
|
||||
|
||||
@@ -291,6 +341,52 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
particles,
|
||||
uiContainer = uiContainer
|
||||
)
|
||||
|
||||
if (KeyToggler.isOn(Input.Keys.F10)) {
|
||||
App.shapeRender.inUse {
|
||||
|
||||
val actor = cameraPlayer as CameraPlayer
|
||||
|
||||
val x1 = actor.hitbox.startX
|
||||
val y1 = actor.hitbox.startY
|
||||
|
||||
val px1L = x1 - lookaheadDist// * cos(actor.bearing1A)
|
||||
val px1C = x1
|
||||
val px1R = x1 + lookaheadDist// * cos(actor.bearing1B)
|
||||
val py1L = getPointAt(px1L)
|
||||
val py1C = getPointAt(px1C)
|
||||
val py1R = getPointAt(px1R)
|
||||
|
||||
val px2L = (px1L + px1C) / 2.0
|
||||
val px2R = (px1C + px1R) / 2.0
|
||||
val py2L = (py1L + py1C) / 2.0
|
||||
val py2R = (py1C + py1R) / 2.0
|
||||
|
||||
it.color = firstOrderSlopeCol
|
||||
drawLineOnWorld(px1L, py1L, px1C, py1C)
|
||||
drawLineOnWorld(px1C, py1C, px1R, py1R)
|
||||
|
||||
/*(1..cameraNodes.lastIndex + 16).forEach { index0 ->
|
||||
val x1 = (index0 - 1) * cameraNodeWidth * TILE_SIZEF; val x2 = (index0 - 0) * cameraNodeWidth * TILE_SIZEF
|
||||
val y1 = cameraNodes[(index0 - 1) fmod cameraNodes.size]; val y2 = cameraNodes[index0 fmod cameraNodes.size]
|
||||
drawLineOnWorld(x1, y1, x2, y2)
|
||||
}*/
|
||||
it.color = baseSlopeCol
|
||||
val points = (0..App.scr.width).map { x ->
|
||||
val worldX = (WorldCamera.x + x).toDouble()
|
||||
worldX to getPointAt(worldX)
|
||||
}
|
||||
points.forEachIndexed { index, (x, y) ->
|
||||
if (index > 0) {
|
||||
drawLineOnWorld(points[index - 1].first, points[index - 1].second, x, y)
|
||||
}
|
||||
}
|
||||
|
||||
it.color = secondOrderSlopeCol
|
||||
drawLineOnWorld(px2L, py2L, px2R, py2R)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printdbgerr(this, "Demoworld is already been destroyed")
|
||||
@@ -333,16 +429,34 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
batch.color = Color.WHITE
|
||||
|
||||
if (App.is32BitJVM && uiRemoCon.currentRemoConContents.parent == null) {
|
||||
// if (uiRemoCon.currentRemoConContents.parent == null) {
|
||||
val linegap = 4
|
||||
val imgTxtGap = 10
|
||||
val yoff = App.scr.height - App.scr.tvSafeGraphicsHeight - 64 - (3*(20+linegap)) - imgTxtGap - 9
|
||||
Toolkit.drawCentered(batch, warning32bitJavaIcon, yoff)
|
||||
for (i in 0..2) {
|
||||
val text = Lang.get("GAME_32BIT_WARNING${i+1}", (i != 2))
|
||||
if (i == 2) batch.color = Toolkit.Theme.COL_SELECTED
|
||||
App.fontGame.draw(batch, text, ((drawWidth - App.fontGame.getWidth(text)) / 2).toFloat(), yoff + imgTxtGap + 64f + linegap + i*(20+linegap))
|
||||
// warn: 32-bit
|
||||
val linegap = 4
|
||||
val imgTxtGap = 10
|
||||
val yoff = App.scr.height - App.scr.tvSafeGraphicsHeight - 64 - (3*(20+linegap)) - imgTxtGap - 9
|
||||
if (uiRemoCon.currentRemoConContents.parent == null) {
|
||||
var texts = emptyList<String>()
|
||||
var textcols = emptyList<Color>()
|
||||
if (App.is32BitJVM) {
|
||||
Toolkit.drawCentered(batch, warning32bitJavaIcon, yoff)
|
||||
texts = (1..3).map { Lang.get("GAME_32BIT_WARNING$it", (it != 3)) }
|
||||
textcols = (1..3).map { if (it == 3) Toolkit.Theme.COL_SELECTED else Color.WHITE }
|
||||
}
|
||||
// warn: rosetta on Apple M-chips
|
||||
else if (App.getUndesirableConditions() == "apple_execution_through_rosetta") {
|
||||
Toolkit.drawCentered(batch, warningAppleRosettaIcon, yoff)
|
||||
texts = (1..2).map { Lang.get("GAME_APPLE_ROSETTA_WARNING$it") }
|
||||
textcols = texts.map { Color.WHITE }
|
||||
}
|
||||
|
||||
|
||||
texts.forEachIndexed { i, text ->
|
||||
batch.color = textcols[i]
|
||||
App.fontGame.draw(
|
||||
batch,
|
||||
text,
|
||||
((drawWidth - App.fontGame.getWidth(text)) / 2).toFloat(),
|
||||
yoff + imgTxtGap + 64f + linegap + i * (20 + linegap)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,6 +494,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
uiRemoCon.dispose()
|
||||
demoWorld.dispose()
|
||||
warning32bitJavaIcon.texture.dispose()
|
||||
warningAppleRosettaIcon.texture.dispose()
|
||||
}
|
||||
|
||||
override fun inputStrobed(e: TerrarumKeyboardEvent) {
|
||||
@@ -436,7 +551,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
override val hitbox = Hitbox(0.0, 0.0, 2.0, 2.0)
|
||||
|
||||
init {
|
||||
actorValue[AVKey.SPEED] = 1.666
|
||||
actorValue[AVKey.SPEED] = 1.666 * (if (Math.random() < 1.0 / 65536.0) -1 else 1) // some easter egg
|
||||
hitbox.setPosition(
|
||||
HQRNG().nextInt(demoWorld.width) * TILE_SIZED,
|
||||
0.0 // Y pos: placeholder; camera AI will take it over
|
||||
@@ -476,7 +591,14 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
|
||||
var targetBearing = 0.0
|
||||
var currentBearing = Double.NaN
|
||||
var currentBearing = 0.0
|
||||
|
||||
var bearing1A = 0.0
|
||||
var bearing1B = 0.0
|
||||
var bearing1C = 0.0
|
||||
var bearing2A = 0.0
|
||||
var bearing2B = 0.0
|
||||
var bearing3A = 0.0
|
||||
|
||||
override fun moveTo(bearing: Double) {
|
||||
targetBearing = bearing
|
||||
@@ -496,6 +618,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
val xdiff = if (xdiff1 < 0) xdiff2 else xdiff1
|
||||
val ydiff = toY - hitbox.canonicalY
|
||||
|
||||
moveTo(atan2(ydiff, xdiff))
|
||||
hitbox.setPositionX(hitbox.canonicalX % ww)
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
||||
this.physProp = physProp
|
||||
}
|
||||
|
||||
var vehicleRiding: Controllable? = null // usually player only
|
||||
|
||||
@Transient internal var vehicleRiding: Controllable? = null // usually player only
|
||||
var vehicleRidingActorID: ActorID? = null
|
||||
|
||||
|
||||
/** Must be set by PlayerFactory */
|
||||
|
||||
@@ -14,11 +14,111 @@ import org.dyn4j.geometry.Vector2
|
||||
import java.util.*
|
||||
|
||||
typealias BlockBoxIndex = Int
|
||||
typealias WireEmissionType = String
|
||||
|
||||
interface Electric {
|
||||
val wireEmitterTypes: HashMap<String, BlockBoxIndex>
|
||||
val wireEmission: HashMap<BlockBoxIndex, Vector2>
|
||||
val wireConsumption: HashMap<BlockBoxIndex, Vector2>
|
||||
open class Electric : FixtureBase {
|
||||
|
||||
protected constructor() : super() {
|
||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Making the sprite: do not address the CommonResourcePool directly; just do it like this snippet:
|
||||
*
|
||||
* ```makeNewSprite(FixtureBase.getSpritesheet("basegame", "sprites/fixtures/tiki_torch.tga", 16, 32))```
|
||||
*/
|
||||
constructor(
|
||||
blockBox0: BlockBox,
|
||||
blockBoxProps: BlockBoxProps = BlockBoxProps(0),
|
||||
renderOrder: RenderOrder = RenderOrder.MIDDLE,
|
||||
nameFun: () -> String,
|
||||
mainUI: UICanvas? = null,
|
||||
inventory: FixtureInventory? = null,
|
||||
id: ActorID? = null
|
||||
) : super(renderOrder, PhysProperties.IMMOBILE, id) {
|
||||
blockBox = blockBox0
|
||||
setHitboxDimension(TILE_SIZE * blockBox.width, TILE_SIZE * blockBox.height, 0, 0)
|
||||
this.blockBoxProps = blockBoxProps
|
||||
this.renderOrder = renderOrder
|
||||
this.nameFun = nameFun
|
||||
this.mainUI = mainUI
|
||||
this.inventory = inventory
|
||||
|
||||
if (mainUI != null)
|
||||
App.disposables.add(mainUI)
|
||||
|
||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ELECTIC_THRESHOLD_HIGH = 0.9
|
||||
const val ELECTRIC_THRESHOLD_LOW = 0.1
|
||||
const val ELECTRIC_THRESHOLD_EDGE_DELTA = 0.7
|
||||
}
|
||||
|
||||
fun getWireEmitterAt(point: Point2i) = this.wireEmitterTypes[pointToBlockBoxIndex(point)]
|
||||
fun getWireEmitterAt(x: Int, y: Int) = this.wireEmitterTypes[pointToBlockBoxIndex(x, y)]
|
||||
fun getWireSinkAt(point: Point2i) = this.wireSinkTypes[pointToBlockBoxIndex(point)]
|
||||
fun getWireSinkAt(x: Int, y: Int) = this.wireSinkTypes[pointToBlockBoxIndex(x, y)]
|
||||
|
||||
fun setWireEmitterAt(x: Int, y: Int, type: WireEmissionType) { wireEmitterTypes[pointToBlockBoxIndex(x, y)] = type }
|
||||
fun setWireSinkAt(x: Int, y: Int, type: WireEmissionType) { wireSinkTypes[pointToBlockBoxIndex(x, y)] = type }
|
||||
fun setWireEmissionAt(x: Int, y: Int, emission: Vector2) { wireEmission[pointToBlockBoxIndex(x, y)] = emission }
|
||||
fun setWireConsumptionAt(x: Int, y: Int, consumption: Vector2) { wireConsumption[pointToBlockBoxIndex(x, y)] = consumption }
|
||||
|
||||
@Transient val wireEmitterTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||
@Transient val wireSinkTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||
@Transient val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
@Transient val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
|
||||
/** Triggered when 'digital_bit' rises from low to high. Edge detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onRisingEdge(readFrom: BlockBoxIndex) {}
|
||||
/** Triggered when 'digital_bit' rises from high to low. Edge detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onFallingEdge(readFrom: BlockBoxIndex) {}
|
||||
/** Triggered when 'digital_bit' is held high. This function WILL NOT be triggered simultaneously with the rising edge. Level detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onSignalHigh(readFrom: BlockBoxIndex) {}
|
||||
/** Triggered when 'digital_bit' is held low. This function WILL NOT be triggered simultaneously with the falling edge. Level detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onSignalLow(readFrom: BlockBoxIndex) {}
|
||||
|
||||
|
||||
private val oldSinkStatus: Array<Vector2>
|
||||
|
||||
open fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
|
||||
val index = pointToBlockBoxIndex(offsetX, offsetY)
|
||||
val old = oldSinkStatus[index]
|
||||
val wx = offsetX + intTilewiseHitbox.startX.toInt()
|
||||
val wy = offsetY + intTilewiseHitbox.startY.toInt()
|
||||
val new = WireCodex.getAllWiresThatAccepts("digital_bit").fold(Vector2()) { acc, (id, _) ->
|
||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||
}
|
||||
}
|
||||
|
||||
if (sinkType == "digital_bit") {
|
||||
if (new.x - old.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTIC_THRESHOLD_HIGH)
|
||||
onRisingEdge(index)
|
||||
else if (old.x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
|
||||
onFallingEdge(index)
|
||||
else if (new.x >= ELECTIC_THRESHOLD_HIGH)
|
||||
onSignalHigh(index)
|
||||
else if (new.y <= ELECTRIC_THRESHOLD_LOW)
|
||||
onSignalLow(index)
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
super.update(delta)
|
||||
oldSinkStatus.indices.forEach { index ->
|
||||
val wx = (index % blockBox.width) + intTilewiseHitbox.startX.toInt()
|
||||
val wy = (index / blockBox.width) + intTilewiseHitbox.startY.toInt()
|
||||
val new = WireCodex.getAllWiresThatAccepts(getWireSinkAt(index % blockBox.width, index / blockBox.width) ?: "").fold(Vector2()) { acc, (id, _) ->
|
||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||
}
|
||||
}
|
||||
oldSinkStatus[index].set(new)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,15 +135,20 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
protected set
|
||||
|
||||
lateinit var blockBox: BlockBox // something like TapestryObject will want to redefine this
|
||||
|
||||
fun blockBoxIndexToPoint2i(it: BlockBoxIndex): Point2i = this.blockBox.width.let { w -> Point2i(it % w, it / w) }
|
||||
var blockBoxProps: BlockBoxProps = BlockBoxProps(0)
|
||||
fun pointToBlockBoxIndex(point: Point2i) = point.y * this.blockBox.width + point.x
|
||||
fun pointToBlockBoxIndex(x: Int, y: Int) = y * this.blockBox.width + x
|
||||
|
||||
@Transient var blockBoxProps: BlockBoxProps = BlockBoxProps(0)
|
||||
@Transient var nameFun: () -> String = { "" }
|
||||
@Transient var mainUI: UICanvas? = null
|
||||
var inventory: FixtureInventory? = null
|
||||
|
||||
protected var actorThatInstalledThisFixture: UUID? = null
|
||||
|
||||
private constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
|
||||
protected constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
|
||||
protected constructor(renderOrder: RenderOrder, physProp: PhysProperties, id: ActorID?) : super(renderOrder, physProp, id)
|
||||
|
||||
|
||||
/**
|
||||
@@ -244,7 +349,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
|
||||
if (canBeDespawned) {
|
||||
printdbg(this, "despawn at T${INGAME.WORLD_UPDATE_TIMER}: ${nameFun()}")
|
||||
printStackTrace(this)
|
||||
// printStackTrace(this)
|
||||
|
||||
// remove filler block
|
||||
forEachBlockbox { x, y, _, _ ->
|
||||
@@ -312,7 +417,13 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
}
|
||||
|
||||
override fun flagDespawn() {
|
||||
if (canBeDespawned) flagDespawn = true
|
||||
if (canBeDespawned) {
|
||||
printdbg(this, "Fixture at (${this.intTilewiseHitbox}) flagging despawn: ${this.javaClass.canonicalName}")
|
||||
flagDespawn = true
|
||||
}
|
||||
else {
|
||||
printdbg(this, "Fixture at (${this.intTilewiseHitbox}) CANNOT be despawned: ${this.javaClass.canonicalName}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,10 +462,10 @@ interface CuedByWireChange {
|
||||
* Standard 32-bit binary flags.
|
||||
*
|
||||
* (LSB)
|
||||
* - 0: fluid resist - when FALSE, the fixture will break itself to item/nothing.
|
||||
* For example, crops has this flag FALSE.
|
||||
* - 1: don't drop item when broken - when TRUE, the fixture will simply disappear instead of
|
||||
* dropping itself. For example, crop has this flag TRUE.
|
||||
* - 0: fluid intolerance - when SET, the fixture will break itself to item/nothing (depends on the flag #1).
|
||||
* For example, crops have this flag SET.
|
||||
* - 1: no drops - when SET, the fixture will simply disappear instead of dropping itself.
|
||||
* For example, crops have this flag SET.
|
||||
*
|
||||
* (MSB)
|
||||
*
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import net.torvald.terrarum.CommonResourcePool
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
@@ -11,12 +7,7 @@ import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import org.dyn4j.geometry.Vector2
|
||||
|
||||
class FixtureLogicSignalEmitter : FixtureBase, Electric {
|
||||
|
||||
override val wireEmitterTypes: HashMap<String, BlockBoxIndex> = HashMap()
|
||||
override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
override val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
|
||||
class FixtureLogicSignalEmitter : Electric {
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 1, 1),
|
||||
@@ -27,21 +18,16 @@ class FixtureLogicSignalEmitter : FixtureBase, Electric {
|
||||
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/signal_source.tga")
|
||||
|
||||
density = 1400.0
|
||||
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, -1)
|
||||
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, 1)
|
||||
|
||||
makeNewSprite(TextureRegionPack(itemImage.texture, TILE_SIZE, TILE_SIZE)).let {
|
||||
it.setRowsAndFrames(1,1)
|
||||
}
|
||||
|
||||
actorValue[AVKey.BASEMASS] = MASS
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
// the values does not get preserved on save reload??
|
||||
wireEmitterTypes["digital_bit"] = 0
|
||||
wireEmission[0] = Vector2(1.0, 0.0)
|
||||
|
||||
super.update(delta)
|
||||
setWireEmitterAt(0, 0, "digital_bit")
|
||||
setWireEmissionAt(0, 0, Vector2(1.0, 0.0))
|
||||
}
|
||||
|
||||
override fun dispose() { }
|
||||
|
||||
@@ -23,7 +23,7 @@ internal class FixtureStorageChest : FixtureBase {
|
||||
(mainUI as UIStorageChest).chestInventory = this.inventory!!
|
||||
(mainUI as UIStorageChest).chestNameFun = this.nameFun
|
||||
|
||||
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, -1)
|
||||
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, 1)
|
||||
|
||||
makeNewSprite(TextureRegionPack(CommonResourcePool.getAsTextureRegion("itemplaceholder_16").texture, 16, 16)).let {
|
||||
it.setRowsAndFrames(1,1)
|
||||
|
||||
@@ -126,7 +126,7 @@ open class FixtureSwingingDoorBase : FixtureBase {
|
||||
(if (isOpacityActuallyLuminosity) lightBoxList else shadeBoxList)[0].light = opacity
|
||||
|
||||
// define physical size
|
||||
setHitboxDimension(TILE_SIZE * tilewiseHitboxWidth, TILE_SIZE * tilewiseHitboxHeight, 0, 0)
|
||||
setHitboxDimension(TILE_SIZE * tilewiseHitboxWidth, TILE_SIZE * tilewiseHitboxHeight, 0, 1)
|
||||
blockBox = BlockBox(BlockBox.FULL_COLLISION, tilewiseHitboxWidth, tilewiseHitboxHeight)
|
||||
|
||||
doorHoldLength = hashMapOf(
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import net.torvald.random.XXHash64
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.WireCodex
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.WorldgenLoadScreen
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory.Companion.CAPACITY_MODE_WEIGHT
|
||||
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||
import net.torvald.terrarum.modulebasegame.serialise.LoadSavegame
|
||||
import net.torvald.terrarum.modulebasegame.serialise.ReadActor
|
||||
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIWorldPortal
|
||||
import net.torvald.terrarum.savegame.ByteArray64Reader
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.savegame.VDFileID
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import java.util.HashMap
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-05-28.
|
||||
*/
|
||||
class FixtureWorldPortal : Electric {
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 5, 2),
|
||||
nameFun = { Lang["ITEM_WORLD_PORTAL"] },
|
||||
mainUI = UIWorldPortal(),
|
||||
// inventory = FixtureInventory(200, CAPACITY_MODE_WEIGHT)
|
||||
) {
|
||||
// TODO do something with (mainUI as UIWorldPortal).***
|
||||
// (mainUI as UIWorldPortal).let { ui ->
|
||||
// ui.transitionalCargo.chestInventory = this.inventory!!
|
||||
// ui.transitionalCargo.chestNameFun = this.nameFun
|
||||
// }
|
||||
|
||||
(mainUI as UIWorldPortal).host = this
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
val itemImage = FixtureItemBase.getItemImageFromSheet("basegame", "sprites/fixtures/portal_device.tga", 80, 32)
|
||||
|
||||
density = 2900.0
|
||||
setHitboxDimension(80, 32, 0, 0)
|
||||
makeNewSprite(TextureRegionPack(itemImage.texture, 80, 32)).let {
|
||||
it.setRowsAndFrames(1,1)
|
||||
}
|
||||
|
||||
actorValue[AVKey.BASEMASS] = FixtureLogicSignalEmitter.MASS
|
||||
|
||||
setWireSinkAt(2, 1, "digital_bit")
|
||||
}
|
||||
|
||||
@Transient internal var teleportRequest: TeleportRequest? = null
|
||||
|
||||
override fun update(delta: Float) {
|
||||
super.update(delta)
|
||||
}
|
||||
|
||||
override fun onRisingEdge(readFrom: BlockBoxIndex) {
|
||||
printdbg(this, "teleport! $teleportRequest")
|
||||
teleportRequest?.let {
|
||||
if (it.worldDiskToLoad != null && it.worldLoadParam != null) {
|
||||
throw InternalError("Contradiction -- worldDiskToLoad and worldLoadParam are both not null: $teleportRequest")
|
||||
}
|
||||
|
||||
val player = INGAME.actorGamer
|
||||
|
||||
// load existing
|
||||
val jobAfterSave: () -> Unit
|
||||
if (it.worldDiskToLoad != null) {
|
||||
UILoadGovernor.worldDisk = it.worldDiskToLoad
|
||||
UILoadGovernor.playerDisk = App.savegamePlayers[player.uuid]!!.files[0]
|
||||
jobAfterSave = {
|
||||
UILoadGovernor.playerDisk!!.rebuild()
|
||||
LoadSavegame(UILoadGovernor.playerDisk!!, UILoadGovernor.worldDisk!!)
|
||||
}
|
||||
}
|
||||
// create new
|
||||
else {
|
||||
jobAfterSave = {
|
||||
val wx = it.worldLoadParam!!.width
|
||||
val wy = it.worldLoadParam!!.height
|
||||
val seed = it.worldLoadParam!!.worldGenSeed
|
||||
val name = it.worldLoadParam!!.savegameName
|
||||
printdbg(this, "generate for teleportation! Size=${wx}x${wy}, Name=$name, Seed=$seed")
|
||||
|
||||
val ingame = TerrarumIngame(App.batch)
|
||||
val worldParam = TerrarumIngame.NewGameParams(player, it.worldLoadParam)
|
||||
ingame.gameLoadInfoPayload = worldParam
|
||||
ingame.gameLoadMode = TerrarumIngame.GameLoadMode.CREATE_NEW
|
||||
|
||||
Terrarum.setCurrentIngameInstance(ingame)
|
||||
val loadScreen = WorldgenLoadScreen(ingame, wx, wy)
|
||||
App.setLoadScreen(loadScreen)
|
||||
}
|
||||
}
|
||||
|
||||
INGAME.requestForceSave(jobAfterSave)
|
||||
|
||||
|
||||
teleportRequest = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun reload() {
|
||||
super.reload()
|
||||
|
||||
// TODO do something with (mainUI as UIWorldPortal).***
|
||||
}
|
||||
|
||||
internal data class TeleportRequest(
|
||||
val worldDiskToLoad: DiskSkimmer?, // for loading existing worlds
|
||||
val worldLoadParam: TerrarumIngame.NewWorldParameters? // for creating new world
|
||||
)
|
||||
}
|
||||
@@ -16,7 +16,8 @@ import net.torvald.terrarum.itemproperties.Material
|
||||
*/
|
||||
open class HumanoidNPC : ActorHumanoid, AIControlled, CanBeAnItem {
|
||||
|
||||
override lateinit var ai: ActorAI
|
||||
var aiName: String = ""
|
||||
@Transient override lateinit var ai: ActorAI
|
||||
|
||||
companion object {
|
||||
val DEFAULT_COLLISION_TYPE = COLLISION_DYNAMIC
|
||||
@@ -26,6 +27,7 @@ open class HumanoidNPC : ActorHumanoid, AIControlled, CanBeAnItem {
|
||||
|
||||
constructor(ai: ActorAI, born: Long) : super(born) {
|
||||
this.ai = ai
|
||||
this.aiName = ai::class.java.canonicalName
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -25,7 +25,7 @@ class PhysTestBall : ActorWithBody(RenderOrder.MIDDLE, PhysProperties.PHYSICS_OB
|
||||
}
|
||||
|
||||
override fun drawBody(batch: SpriteBatch) {
|
||||
Terrarum.inShapeRenderer {
|
||||
/*Terrarum.inShapeRenderer {
|
||||
it.color = color
|
||||
it.circle(
|
||||
hitbox.startX.toFloat() - 1f,
|
||||
@@ -44,7 +44,7 @@ class PhysTestBall : ActorWithBody(RenderOrder.MIDDLE, PhysProperties.PHYSICS_OB
|
||||
hitbox.startY.toFloat() - 1f,
|
||||
hitbox.width.toFloat()
|
||||
)
|
||||
}
|
||||
}*/
|
||||
|
||||
//println(moveDelta)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user