Compare commits

...

148 Commits

Author SHA1 Message Date
minjaesong
8eff89a7cb fix: inputstrober not working 2026-04-04 22:59:30 +09:00
minjaesong
73c7c8942e title screen fade-in transition 2026-04-04 22:33:10 +09:00
minjaesong
6118f30d5f async loading (hopefully?) 2026-04-04 17:05:00 +09:00
minjaesong
981418d0c7 async loading (hopefully) 2026-04-04 01:56:40 +09:00
CuriousTorvald
3cbfb5c10f Update CodeQL workflow to exclude certain languages 2026-03-29 00:22:48 +09:00
minjaesong
1a0b754cde font update, video sprite (TAV) 2026-03-15 13:26:05 +09:00
CuriousTorvald
db3a1f9a39 Modify funding configuration in FUNDING.yml
Updated funding options to include GitHub Sponsors and a PayPal link.
2026-03-13 19:20:45 +09:00
minjaesong
247fd6195f wiki update (asset archiving, building instructions) 2026-02-28 10:53:51 +09:00
minjaesong
97d22913bf custom asset archive loading 2026-02-22 00:09:48 +09:00
minjaesong
2dea82bb9c font update 2026-02-20 11:10:38 +09:00
minjaesong
7c8baa151f asset archiving wip 2026-02-20 10:39:53 +09:00
minjaesong
04b49b8a5c asset archiving wip, font update 2026-02-19 09:57:59 +09:00
minjaesong
661d516800 buildapp update 2026-02-17 05:04:27 +09:00
minjaesong
9efb800d47 alpha blending diagnostic shaders 2026-02-13 21:03:01 +09:00
minjaesong
93c5822c7b finally fixing contradictory key press handling (left+right, up+down) 2026-02-13 19:52:14 +09:00
minjaesong
4d9252dd80 world control hint 2026-02-10 20:17:43 +09:00
minjaesong
232bc0297d copyright year update 2026-02-10 16:00:41 +09:00
minjaesong
612871eb2a fix: moving platform is dragging player into the terrain again 2026-02-09 09:46:35 +09:00
minjaesong
8bbe79acfe pushing down on moving platform will dismount 2026-02-09 03:15:11 +09:00
minjaesong
54715e41b0 fix: sinking platform taking actors with it 2026-02-09 03:06:28 +09:00
minjaesong
e91b7ceb0d player can exit from sinking platform by jumping 2026-02-09 02:54:56 +09:00
minjaesong
855e0ea12a moving platforms can 'steal' actors 2026-02-09 02:34:49 +09:00
minjaesong
5394f17686 moving platform fix: double speed gain 2026-02-09 02:25:52 +09:00
minjaesong
72aae3cffd moving platform kinda working 2026-02-08 23:54:07 +09:00
minjaesong
b5b9e22091 platform wip3 2026-02-08 20:02:39 +09:00
minjaesong
5b1d0ca049 platform surface friction 2026-02-08 03:53:10 +09:00
minjaesong
623ee14d93 platform wip2 2026-02-08 03:43:37 +09:00
minjaesong
b328b609cc watchface: 'Y' is more distinguished 2026-02-08 03:12:49 +09:00
minjaesong
ff9f02322b moving platform wip 2026-02-08 02:06:29 +09:00
minjaesong
4997353f83 wtf 2026-02-07 16:39:33 +09:00
minjaesong
068d0bf1b2 control preset to be stored into separate file 2026-02-07 16:19:42 +09:00
minjaesong
e838991826 new: #if(n)def preprocessor for Terrarum-formatted CSVs 2026-01-19 17:50:44 +09:00
minjaesong
63566a507b new: world update ahchoring 2026-01-19 17:08:31 +09:00
minjaesong
104481a7d5 fix: fixture pickup mess with quickslots and needed empty hands 2026-01-17 20:50:26 +09:00
minjaesong
a4df761359 wire sim incremental graph update (partial) 2026-01-08 23:20:24 +09:00
minjaesong
aa22fe69ff wire sim refactor 2026-01-08 19:06:20 +09:00
minjaesong
e14e689dce fix: bogoflops counter being overestimated on M4 Mac due to Math.random() reliance 2025-11-27 10:41:13 +09:00
minjaesong
767aa09a17 faster block tiling hash 2025-10-13 20:08:22 +09:00
minjaesong
99bd56317d bump AirCompressor to 2.0.2 2025-09-01 17:51:52 +09:00
minjaesong
3f6f599865 1 meter is now 25 pixels 2025-08-08 01:01:45 +09:00
minjaesong
c803ddfae8 why the hell I thought circular buffering would be better, when it makes FOUR memcpy insead of TWO 2025-07-04 06:13:04 +09:00
minjaesong
f11ea557be reverting FFT changes 2025-06-29 19:29:02 +09:00
minjaesong
3f787108b2 more small optimisation of FFT 2025-06-26 19:14:39 +09:00
minjaesong
6bdf585b49 realFFT is somehow faster while everything else stays the same? 2025-06-26 19:08:16 +09:00
minjaesong
fa56fc14bf deploying new wood textures 2025-05-18 19:33:03 +09:00
minjaesong
d922aa5d67 finished wooden texture 48 2025-05-18 15:21:14 +09:00
minjaesong
0ca5e6435c better wooden plank texture wip 2025-05-18 14:54:33 +09:00
minjaesong
3b755f52da testing new wooden plank texture 2025-05-18 13:28:56 +09:00
minjaesong
b167f20935 randomised music generator for test item 2025-05-09 20:02:20 +09:00
minjaesong
41c47a0777 minor readme update 2025-05-09 19:58:04 +09:00
minjaesong
5495e017d5 more canisters 2025-04-29 22:59:26 +09:00
minjaesong
488a214a19 TODO new fluid container system 2025-04-29 21:11:36 +09:00
minjaesong
946824f861 copyright date 2024 to 2025 2025-04-07 22:54:09 +09:00
minjaesong
dabcfe03ed clipboard wip 2025-04-06 22:21:35 +09:00
minjaesong
06a8fd38d1 more computer stuffs 2025-04-01 21:03:09 +09:00
minjaesong
a4b6ad1d5f more minor codes 2025-04-01 20:50:57 +09:00
minjaesong
1c0162ec25 wire ports for computers first draught 2025-03-31 22:21:13 +09:00
minjaesong
b6ee5ee0f7 computer wires 2025-03-30 20:00:02 +09:00
minjaesong
51da0612d2 sprites 2025-03-30 18:07:02 +09:00
minjaesong
0c35faa548 external classloader from modmgr 2025-03-30 17:00:39 +09:00
minjaesong
852c0b7dcc omfg is it actually working now? 2025-03-25 17:50:10 +09:00
minjaesong
759f8a4c4e bottom parts on conveyor now works 2025-03-25 16:58:55 +09:00
minjaesong
506ca7a7b1 curved parts on conveyor now works 2025-03-25 14:15:34 +09:00
minjaesong
42eee2bba7 small steps man :p 2025-03-24 22:02:07 +09:00
minjaesong
d77e1f38dc finally code's working as intended 2025-03-23 22:12:33 +09:00
minjaesong
e5f8e3b76d curved parts are finally appearing where they should 2025-03-23 21:11:52 +09:00
minjaesong
f5744550a4 straight part of the belt now use proper maths 2025-03-23 20:34:52 +09:00
minjaesong
bbd0bc7eb2 some mac-specific codes 2025-03-22 23:40:58 +09:00
minjaesong
7188fddc7e more conveyor aesthetics 2025-03-22 23:29:23 +09:00
minjaesong
5c2d201151 more versatile weather CLUT defs 2025-03-22 19:39:35 +09:00
minjaesong
c54cafae0f more conveyor visuals 2025-03-21 15:04:43 +09:00
minjaesong
3c8f272d4a conveyor wip 2025-03-21 14:30:32 +09:00
minjaesong
bbe28903d8 more conveyor aesthetics 2025-03-17 20:58:34 +09:00
minjaesong
b19b7c7e79 btex.xml 2025-03-17 19:40:45 +09:00
minjaesong
73bf7f8793 more belt graphics 2025-03-16 21:57:04 +09:00
minjaesong
5631b8e807 more belt graphics 2025-03-16 20:17:02 +09:00
minjaesong
dba941d4de rubber coloured belts 2025-03-16 18:16:28 +09:00
minjaesong
27b4137455 belts using their own shaperenderer 2025-03-16 16:36:26 +09:00
minjaesong
9af3f3b883 fixed rendering of belts 2025-03-15 22:08:09 +09:00
minjaesong
b577df0155 partially working conveyor 2025-03-15 21:40:14 +09:00
minjaesong
18feeb1826 wip conveyor drawfun 2025-03-14 20:51:24 +09:00
minjaesong
d598ef497d wippieeee 2025-03-13 21:30:04 +09:00
minjaesong
e652ace37b conveyer belt wip 2025-03-10 21:33:47 +09:00
minjaesong
bdd00676e6 no-auto-pickup variant of droppeditem 2025-03-09 12:56:26 +09:00
minjaesong
19bc779ae1 more token ring stuff 2025-03-08 22:17:36 +09:00
minjaesong
16cac2f1ab fixing minor bugs 2025-03-04 20:56:12 +09:00
minjaesong
a362ade9af some refactoring on FixtureRingBusCore 2025-03-03 22:01:22 +09:00
minjaesong
fea4e34733 ring bus debugger ui wip 2025-03-03 21:27:35 +09:00
minjaesong
f861a2727d now with watchdogs 2025-03-02 20:42:03 +09:00
minjaesong
2bb1c8400e more token ring stuff 2025-03-02 19:47:52 +09:00
minjaesong
ef4a5d6eb9 token ring stuff and renaming things to avoid confusion 2025-03-02 15:04:53 +09:00
minjaesong
f74b7218b0 token ring stuff wip 2025-03-01 23:03:56 +09:00
minjaesong
f154b2348b token ring stuff wip 2025-02-28 22:44:57 +09:00
minjaesong
e889b397d0 token ring stuff wip 2025-02-27 20:58:14 +09:00
minjaesong
65f771e9de replacing N'gasta with random Lorem texts to avoid possible copyright issues 2025-02-24 21:48:17 +09:00
minjaesong
8a26f328c7 more postal codes 2025-02-20 19:41:41 +09:00
minjaesong
37d6d3004b fix: targeted voucher code not working 2025-02-15 23:56:53 +09:00
minjaesong
ad68e04b83 working redeem code generator 2025-02-15 23:25:30 +09:00
minjaesong
4aae0bf733 redeem code gen wip 2025-02-15 20:05:17 +09:00
minjaesong
c2d0803ee3 redeem code gen wip 2025-02-15 16:18:30 +09:00
minjaesong
3d5672bc4d redeem code gen wip 2025-02-13 21:06:13 +09:00
minjaesong
22786f9a28 better wire branching control 2025-02-09 21:56:46 +09:00
minjaesong
34d8f1504f actorvalue blob clone wip 2025-02-09 20:55:42 +09:00
minjaesong
497782b428 integration of blob and actorvalue 2025-02-09 14:58:06 +09:00
minjaesong
fd0732cd39 actorvalue: new format 'blob' 2025-02-08 22:47:01 +09:00
minjaesong
d4e81c8c06 instance info 2025-02-01 21:04:12 +09:00
minjaesong
69ebdbc542 fix: some NaNs that can be caused by scroll bars 2025-02-01 20:51:40 +09:00
minjaesong
a2006b0354 debugging thing update 2025-02-01 19:31:07 +09:00
minjaesong
150b4e6b6b 'contrast strip' for volume control 2025-02-01 19:11:59 +09:00
minjaesong
b3b86b0965 a debug item 2025-02-01 14:53:14 +09:00
minjaesong
ff2a022394 item and sprite for 'document' type items 2025-01-31 22:44:08 +09:00
minjaesong
bb1da3b1ec working ItemFileRef instantiation and serialisation 2025-01-30 11:53:21 +09:00
minjaesong
29034e2104 mediumidentifier to loosely follow MIME format 2025-01-28 23:08:39 +09:00
minjaesong
daa6c09b52 more on itemfileref 2025-01-28 21:34:11 +09:00
minjaesong
879cc79bbf code input wip 2025-01-27 23:23:27 +09:00
minjaesong
6b4b7917d9 mysterious wip 2025-01-22 21:10:21 +09:00
minjaesong
ed9d8cffd6 more codes 2025-01-19 19:54:40 +09:00
minjaesong
3d34b9162b fix: AZERTY layout was missing < key 2025-01-17 17:40:45 +09:00
minjaesong
1b69d74291 minor fixes 2025-01-15 20:39:44 +09:00
minjaesong
15e3276f46 redeem code input wip 2025-01-15 16:07:04 +09:00
minjaesong
51dd99fd80 better post definition 2025-01-15 13:23:28 +09:00
minjaesong
c14720d649 better code font 2025-01-15 10:57:07 +09:00
minjaesong
f4fb7cccfb audio compressor option is now available 2025-01-11 23:46:54 +09:00
minjaesong
c10823ddce postal system wip 2024-12-29 19:49:27 +09:00
minjaesong
c1a5624167 locales for comp 2024-12-26 12:35:20 +09:00
minjaesong
3eee0dcd62 a working compressor this time 2024-12-26 12:28:12 +09:00
minjaesong
cc3e59796f i don't know if it's even working lol 2024-12-25 15:18:07 +09:00
minjaesong
9dc2dffef9 bandpass dsp 2024-12-22 15:56:35 +09:00
minjaesong
fe4318877a shader preloading 2024-12-16 19:36:58 +09:00
minjaesong
3322878074 both outline and a shadow for 'behind' actors 2024-12-05 21:47:02 +09:00
minjaesong
869b751488 prebuild update 2024-11-30 22:49:01 +09:00
minjaesong
450129f650 better shadow for wall-stickers 2024-11-30 20:52:52 +09:00
minjaesong
bf626e35da buttons for crafting/techtree transition 2024-11-26 22:29:48 +09:00
minjaesong
e581099aec minor numbers changes 2024-11-26 08:15:55 +09:00
minjaesong
95af4e8f53 tech tree view wip 2024-11-25 23:50:28 +09:00
minjaesong
661c4cdc4d more prominent shadow around wall-sticking tiles 2024-11-24 22:41:44 +09:00
minjaesong
a24eab209b shallow shadow improvements 2024-11-24 19:13:12 +09:00
minjaesong
6ec5ba5603 no shadows against skybox 2024-11-24 18:52:44 +09:00
minjaesong
8cf4b5d9a9 shadows around actors as well as terrain 2024-11-24 17:02:00 +09:00
minjaesong
5bf60cfa82 now terrain also lives on its own framebuffer 2024-11-24 13:19:20 +09:00
minjaesong
5cc7db8ecc putting some actors into their own framebuffer for shadowing 2024-11-24 13:10:08 +09:00
minjaesong
89b12aabb4 new debug cmd ExportFBO 2024-11-24 12:53:44 +09:00
minjaesong
f5846d9bae screen blur helper class 2024-11-23 21:17:16 +09:00
minjaesong
d460447331 for alpha 2 release 2024-11-16 11:12:47 +09:00
minjaesong
63fe28eee2 wrap-up commits for "not a true Alpha 2.0 release I was hoping for" 2024-11-15 23:41:25 +09:00
minjaesong
2d7ef6e9ff fix: edge detection of electric fixture not working 2024-10-31 23:40:49 +09:00
minjaesong
fa3a129991 worldportal ui fix 2024-10-31 10:53:11 +09:00
minjaesong
4cc74a85d1 fix: prev commit was made haphazardly 2024-10-30 18:10:30 +09:00
476 changed files with 78531 additions and 1655 deletions

2
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
github: [curioustorvald]
custom: ["https://paypal.me/curioustorvald"]

99
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,99 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '41 4 * * 0'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: java-kotlin
build-mode: none
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- name: Run manual build steps
if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"

View File

@@ -27,7 +27,6 @@
<element id="extracted-dir" path="$PROJECT_DIR$/lib/commons-math3-3.6.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/JTransforms-3.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/JLargeArrays-1.5.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/aircompressor-0.25.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="$PROJECT_DIR$/lib/gdx-1.12.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-backend-lwjgl3-1.12.1.jar" path-in-jar="/" />
@@ -87,6 +86,7 @@
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.0.0/kotlin-stdlib-2.0.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/2.0.0/kotlin-stdlib-jdk7-2.0.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/GetBatteryStatus.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/aircompressor-2.0.2.jar" path-in-jar="/" />
</root>
</artifact>
</component>

View File

@@ -1,5 +1,6 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="RIGHT_MARGIN" value="999" />
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>

View File

@@ -1,14 +1,14 @@
<component name="libraryTable">
<library name="io.airlift.aircompressor" type="repository">
<properties maven-id="io.airlift:aircompressor:0.25" />
<properties maven-id="io.airlift:aircompressor:2.0.2" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/aircompressor-0.25.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/aircompressor-2.0.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/aircompressor-0.25-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/aircompressor-2.0.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/aircompressor-0.25-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/aircompressor-2.0.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -0,0 +1,16 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Terrarum (no prebuild, release-mode assets)" type="JarApplication">
<option name="JAR_PATH" value="$PROJECT_DIR$/out/TerrarumBuild.jar" />
<option name="VM_PARAMETERS" value="-ea -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd" />
<option name="PROGRAM_PARAMETERS" value="--assets buildapp/out/assets.tevd" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH" value="17" />
<module name="TerrarumBuild" />
<method v="2">
<option name="BuildArtifacts" enabled="true">
<artifact name="TerrarumBuild" />
</option>
<option name="RunConfigurationTask" enabled="false" run_configuration_name="QuickDirtyLint" run_configuration_type="Application" />
</method>
</configuration>
</component>

1
.idea/vcs.xml generated
View File

@@ -2,5 +2,6 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/Terrarum.wiki" vcs="Git" />
</component>
</project>

176
CLAUDE.md Normal file
View File

@@ -0,0 +1,176 @@
# Terrarum
A modular 2D side-scrolling tilemap platformer engine and game, built on LibGDX with Kotlin/Java. GPL-3.0.
## Build & Run
- **IDE**: IntelliJ IDEA (project files: `Terrarum_renewed.iml`, `TerrarumBuild.iml`)
- **JDK**: 21
- **Language**: Kotlin + Java mixed; Kotlin is primary, `App.java` and `FrameBufferManager.java` are Java
- **Dependencies**: All libraries are in `lib/` (fat-jar approach, no Maven/Gradle). Includes LibGDX, GraalVM JS (modified), dyn4j (Vector2 only), custom bitmap font lib
- **Entry point**: `net.torvald.terrarum.Principii.main()` (Java) which launches `App` (the LibGDX `ApplicationListener`)
- **Distribution**: `buildapp/` scripts produce per-platform bundles with jlink'd runtimes
- **Assets**: `assets/` for development, `assets_release/` for distribution. Custom `.tevd` archive format for release assets (`AssetCache.kt`)
## Project Structure
```
src/net/torvald/terrarum/
App.java -- Main application class (LibGDX ApplicationListener). GL thread, render loop, splash screen
CommonResourcePool.kt -- Thread-safe GL resource loading with dispatch queues
ModMgr.kt -- Module manager. Scans/loads game modules, provides getGdxFile/getJavaClass
IngameInstance.kt -- Base class for game screens (show/hide/render/resize lifecycle)
Terrarum.kt -- Game-level singleton (ingame instance management, extension functions)
GameUpdateGovernor.kt -- Update/render tick governors (ConsistentUpdateRate, Anarchy)
MusicService.kt -- Music playback management
modulebasegame/
EntryPoint.kt -- Basegame module entry point (registers items, fixtures, blocks, weather)
TitleScreen.kt -- Title screen (demo world rendering, async loading)
TerrarumIngame.kt -- Main gameplay screen
IngameRenderer.kt -- World rendering pipeline (FBO composition, lightmap, blur, shadows)
BuildingMaker.kt -- Building editor screen
worlddrawer/
WorldCamera.kt -- Camera position tracking (follows player, interpolated movement)
LightmapRenderer.kt -- Per-tile RGB+UV light calculation and rasterisation
BlocksDrawer.kt -- Tile rendering
FeaturesDrawer.kt -- Wire/feature overlay rendering
gamecontroller/
IME.kt -- Input Method Engine (GraalVM JS keyboard layouts, loaded on daemon thread)
weather/
WeatherMixer.kt -- Weather state machine, skybox rendering
SkyboxModelHosek.kt -- Physically-based sky model
```
## Architecture: Threading & GL Dispatch
All OpenGL calls (Texture, ShaderProgram, FrameBuffer creation) **must** happen on the GL thread. The codebase uses a dispatch mechanism to safely create GL resources from background threads.
### CommonResourcePool (the dispatch hub)
```
Background Thread GL Thread (App.render)
| |
|-- addToLoadingList("name", { Texture() })|
|-- loadAll() |
| | |
| +-- if on GL thread: run directly |
| +-- if not: enqueue to |
| glDispatchQueue + latch.await() |
| CommonResourcePool.update()
| |-- poll glDispatchQueue
| | run loadfun, latch.countDown()
| |-- poll glRunnableQueue
| | run block, latch.countDown()
| |-- poll slowLoadingQueue (one per tick)
| |
+-- latch released, continues <------------+
```
Key methods:
- `loadAll()` -- batch load; blocks background thread until GL thread processes
- `loadAllSlowly()` -- timesliced; one resource per tick via `update()`
- `runOnGLThread { }` -- run arbitrary block on GL thread, blocking caller
- `update()` -- called every tick from `App.render()`, processes all queues
- `getOrPut(name, loadfun, killfun)` -- thread-safe get-or-create with GL dispatch
### App.java Boot Sequence
```
create()
-> postInit() [GL thread, synchronous]
|-- load shaders, fonts, audio device, IME
|-- CommonResourcePool.setGLThread(currentThread)
|-- spawn Terrarum-PostInitLoader thread:
| ModMgr.invoke() // module entry points (dispatched to GL via runOnGLThread)
| CommonResourcePool.loadAllSlowly() // timesliced resource loading
| loadingThreadDone = true
+-- return (non-blocking)
render() loop [GL thread]
while currentScreen == null:
|-- drawSplash()
|-- CommonResourcePool.update() // process GL dispatch queues
|-- when loadingThreadDone && loaded:
| postLoadInit() // tile atlas, audio mixer, Terrarum.initialise()
| setScreen(titleScreen) // transitions to title screen
```
### TitleScreen Async Loading
`TitleScreen.show()` returns immediately after starting a background thread. The splash screen continues displaying until all loading completes.
```
show()
|-- quick GL setup (viewport, input processor, FBO, savegame list)
|-- spawn Terrarum-TitleScreenLoader thread:
| load demo world, compute camera nodes, bogoflops, audio reset
| backgroundLoadDone = true
+-- return
renderImpl() [GL thread, every frame]
if !loadDone:
|-- App.drawSplash()
|-- processGLLoadStep() // state machine, one step per frame:
| 0: wait for backgroundLoadDone
| 1: SkyboxModelHosek.loadlut()
| 2: IngameRenderer.setRenderedWorld + WeatherMixer init
| 3: load halfgrad texture
| 4: UIFakeGradOverlay
| 5: UIFakeBlurOverlay
| 6: UIRemoCon
| 7: MusicService.enterScene, gameUpdateGovernor.reset(), loadDone=true
else:
normal title screen rendering (world + UI via IngameRenderer)
```
### IME Loading
`IME.kt` object `init {}` spawns a `Terrarum-IMELoader` daemon thread for GraalVM JS context binding and key layout/IME file scanning. Icon texture loading remains synchronous (requires GL thread).
### ModMgr Class Initialisation
`ModMgr.kt` object `init {}` only does metadata loading and class instantiation (fast). The heavy `invoke()` method runs entry points wrapped in `CommonResourcePool.runOnGLThread { }` to avoid GL calls on the wrong thread. This separation prevents `<clinit>` lock deadlocks where a background thread holding the class init lock blocks on a GL dispatch latch while the GL thread tries to access the same class.
## Architecture: Rendering Pipeline
### IngameRenderer
Singleton object. Lazily initialised on first `invoke()` call via `invokeInit()`.
Render path (per frame):
1. `LightmapRenderer.recalculate()` -- every 3 frames, computes per-tile RGBA light values
2. `prepLightmapRGBA()` -- Kawase blur on lightmap into `lightmapFbo`
3. `BlocksDrawer.renderData()` -- prepare tile draw data
4. `drawToRGB()` -- render world tiles + actors into `fboRGB` (with shadow FBOs)
5. `drawToA()` -- render alpha/glow channel
6. Composite: sky -> world -> light multiply -> emissive blend -> vibrancy -> UI
7. Output to `App.renderFBO`, then `TerrarumPostProcessor.draw()` applies final effects
**Critical ordering in `resize()`**: `BlocksDrawer.resize()` and `LightmapRenderer.resize()` must be called **before** `lightmapFbo` creation, because `lightmapFbo` dimensions derive from `LightmapRenderer.lightBuffer` size.
### WorldCamera
Follows an `ActorWithBody` (player or camera actor). Position interpolated per frame. `WorldCamera.x/y` = top-left corner of visible area. `gdxCamX/Y` = centre of visible area. `moveCameraToWorldCoord()` positions the IngameRenderer camera for world-space drawing; `setCameraPosition(0,0)` positions it for screen-space drawing.
### FBO Extension Functions
- `FrameBuffer.inAction(camera, batch) { }` -- bind FBO, set camera to FBO dimensions (Y-down), run block, restore camera to screen dimensions
- `FrameBuffer.inActionF(camera, batch) { }` -- same but Y-up (for flipped FBO content)
Both save/restore `camera.position` and call `setToOrtho` with `App.scr.wf/hf` on exit.
## Key Conventions
- **GL thread safety**: Any code creating `Texture`, `TextureRegion`, `TextureRegionPack`, `ShaderProgram`, `FrameBuffer`, or `Pixmap` must run on the GL thread. Use `CommonResourcePool.runOnGLThread { }` when on a background thread.
- **Kotlin `object` singletons**: First access triggers `<clinit>`. Keep `init {}` blocks fast (no blocking, no GL dispatch). Defer heavy work to explicit `invoke()` methods.
- **`ConcurrentHashMap` cannot store null values**. Use `HashMap` for maps that need nullable values (e.g. `poolKillFun`).
- **`@Volatile`** for cross-thread boolean flags (`loadDone`, `backgroundLoadDone`, etc.)
- **`lateinit var` guards**: Use `::prop.isInitialized` checks in `resize()` and `dispose()` for properties set during async loading steps.
- **`ConsistentUpdateRate`**: Accumulates delta time; may call `updateFunction` multiple times before `renderFunction`. Call `.reset()` before transitioning to active rendering to avoid catch-up storms.
- **Textures**: Use TGA format. Images with semitransparency must be TGA; opaque images may be PNG.
- **Coordinate system**: Y-down (camera `setToOrtho(true, ...)`). `setCameraPosition(0, 0)` places origin at screen top-left, which is not LibGDX nor OpenGL works natively, hence the existence of `FlippingSpriteBatch`. If the user reports renders are flipped vertically, try draw()/drawFlipped() accordingly.
- **ROUNDWORLD**: World wraps horizontally. `WorldCamera.x` uses `fmod worldWidth`. Lightmap and tile drawing account for wrapping.

View File

@@ -1,5 +1,7 @@
package net.torvald.terrarum.modulecomputers
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.ItemSheet
import net.torvald.terrarum.ModMgr
import net.torvald.terrarum.ModuleEntryPoint
@@ -11,7 +13,17 @@ class EntryPoint : ModuleEntryPoint() {
private val moduleName = "dwarventech"
override fun invoke() {
// load common resources to the AssetsManager
CommonResourcePool.addToLoadingList("$moduleName.items") {
ItemSheet(ModMgr.getGdxFile(moduleName, "items/items.tga"))
}
CommonResourcePool.loadAll()
ModMgr.GameItemLoader.invoke(moduleName)
ModMgr.GameBlockLoader.invoke(moduleName)
ModMgr.GameWatchdogLoader.register(moduleName, NetFrameWatchdog())
println("[${moduleName[0].toUpperCase()}${moduleName.substring(1)}] Dirtboard(tm) go drrrrr")
}

View File

@@ -0,0 +1,17 @@
package net.torvald.terrarum.modulecomputers
import net.torvald.terrarum.App
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.TerrarumWorldWatchdog
import net.torvald.terrarum.modulebasegame.gameworld.NetRunner
/**
* Created by minjaesong on 2025-03-02.
*/
class NetFrameWatchdog : TerrarumWorldWatchdog(App.TICK_SPEED * 60) {
override fun invoke(world: GameWorld) {
(world.extraFields["tokenring"] as? NetRunner)?.let {
it.purgeDeadFrames()
}
}
}

View File

@@ -0,0 +1,135 @@
package net.torvald.terrarum.modulecomputers.gameactors
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.BlockBox
import net.torvald.terrarum.modulebasegame.gameactors.Electric
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2025-03-30.
*/
class FixtureComputerConsole : Electric {
@Transient override val spawnNeedsStableFloor = true
@Transient override val spawnNeedsWall = false
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 2),
nameFun = { Lang["ITEM_COMPUTER_CONSOLE"] }
)
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_operator_terminal.tga")
makeNewSprite(TextureRegionPack(itemImage.texture, 2*TILE_SIZE, 2*TILE_SIZE)).let {
it.setRowsAndFrames(1,1)
}
setWireSinkAt(0, 1, "io_bus")
setWireSinkAt(1, 1, "power_low")
}
}
/**
* Created by minjaesong on 2025-03-30.
*/
class FixtureComputerProcessor : Electric {
@Transient override val spawnNeedsStableFloor = true
@Transient override val spawnNeedsWall = false
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 3),
nameFun = { Lang["ITEM_COMPUTER_PROCESSOR"] }
)
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_cpu.tga")
makeNewSprite(TextureRegionPack(itemImage.texture, 2*TILE_SIZE, 3*TILE_SIZE)).let {
it.setRowsAndFrames(1,1)
}
setWireSinkAt(0, 0, "memory_bus")
setWireSinkAt(0, 1, "serial")
setWireSinkAt(1, 1, "serial")
setWireSinkAt(0, 2, "io_bus")
setWireSinkAt(1, 2, "power_low")
}
}
/**
* Created by minjaesong on 2025-04-01.
*/
class FixtureNetworkInterface : Electric {
@Transient override val spawnNeedsStableFloor = true
@Transient override val spawnNeedsWall = false
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 3),
nameFun = { Lang["ITEM_NETWORK_INTERFACE"] }
)
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_network_interface.tga")
makeNewSprite(TextureRegionPack(itemImage.texture, 2*TILE_SIZE, 3*TILE_SIZE)).let {
it.setRowsAndFrames(1,1)
}
setWireSinkAt(0, 0, "token_ring")
setWireSinkAt(1, 0, "token_ring")
setWireSinkAt(0, 2, "serial")
setWireSinkAt(1, 2, "power_low")
}
}
/**
* Created by minjaesong on 2025-04-01.
*/
class FixtureNetworkBridge : Electric {
@Transient override val spawnNeedsStableFloor = true
@Transient override val spawnNeedsWall = false
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 3),
nameFun = { Lang["ITEM_NETWORK_BRIDGE"] }
)
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_network_bridge.tga")
makeNewSprite(TextureRegionPack(itemImage.texture, 2*TILE_SIZE, 3*TILE_SIZE)).let {
it.setRowsAndFrames(1,1)
}
setWireSinkAt(0, 0, "token_ring")
setWireSinkAt(1, 0, "token_ring")
setWireSinkAt(0, 1, "token_ring")
setWireSinkAt(1, 1, "token_ring")
setWireSinkAt(1, 2, "power_low")
}
}
/**
* Created by minjaesong on 2025-04-01.
*/
class FixtureMemoryCabinet : Electric {
@Transient override val spawnNeedsStableFloor = true
@Transient override val spawnNeedsWall = false
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 2, 3),
nameFun = { Lang["ITEM_MEMORY_CABINET"] }
)
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_memory_stack_1.tga")
makeNewSprite(TextureRegionPack(itemImage.texture, 1*TILE_SIZE, 3*TILE_SIZE)).let {
it.setRowsAndFrames(1,1)
}
setWireSinkAt(0, 0, "memory_bus")
}
}

View File

@@ -0,0 +1,289 @@
package net.torvald.terrarum.modulecomputers.gameactors
import com.badlogic.gdx.utils.Queue
import net.torvald.random.HQRNG
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Point2i
import net.torvald.terrarum.modulebasegame.gameactors.BlockBox
import net.torvald.terrarum.modulebasegame.gameactors.Electric
import net.torvald.terrarum.modulebasegame.gameworld.NetFrame
import net.torvald.terrarum.modulebasegame.gameworld.NetRunner
import net.torvald.terrarum.ui.UICanvas
import org.dyn4j.geometry.Vector2
import kotlin.math.sign
/**
* Created by minjaesong on 2025-03-01.
*/
open class FixtureRingBusCore : Electric {
@Transient private val rng = HQRNG()
val mac = rng.nextInt()
companion object {
const val INITIAL_LISTENING_TIMEOUT = 300
const val SIGNAL_TOO_WEAK_THRESHOLD = 1.0 / 16.0
}
private constructor() : super()
private var portEmit = Point2i(0, 0)
private var portSink = Point2i(1, 0)
constructor(portEmit: Point2i, portSink: Point2i, blockBox: BlockBox, nameFun: () -> String) : super(
blockBox0 = blockBox,
nameFun = nameFun,
) {
this.portEmit = portEmit
this.portSink = portSink
}
private fun setEmitterAndSink() {
clearStatus()
setWireEmitterAt(portEmit.x, portEmit.y, "10base2")
setWireSinkAt(portSink.x, portSink.y, "10base2")
}
init {
setEmitterAndSink()
if (!INGAME.world.extraFields.containsKey("tokenring")) {
INGAME.world.extraFields["tokenring"] = NetRunner()
}
}
override fun reload() {
super.reload()
setEmitterAndSink()
if (!INGAME.world.extraFields.containsKey("tokenring")) {
INGAME.world.extraFields["tokenring"] = NetRunner()
}
}
internal val msgQueue = Queue<Pair<Int, ByteArray>>()
internal val msgLog = Queue<Pair<Int, NetFrame>>()
private var statusAbort = false
private var activeMonitorStatus = 0 // 0: unknown, 1: known and not me, 2: known and it's me
private var lastAccessTime = -1L
open protected val ringBusFirmware = RingBusFirmware(0)
private enum class RingBusState {
NORMAL,
ABORT, // will "eat away" any receiving frames unless the frame is a ballot frame
ELECTING,
IVE_GOT_ELECTED
}
private var currentState = RingBusState.NORMAL
override fun updateSignal() {
val time_t = INGAME.world.worldTime.TIME_T
if (lastAccessTime == -1L) lastAccessTime = time_t
// monitor the input port
val inn = getWireStateAt(1, 0, "10base2")
// if a signal is there
if (inn.x >= SIGNAL_TOO_WEAK_THRESHOLD) {
lastAccessTime = time_t
val frameNumber = (inn.y + (0.5 * inn.y.sign)).toInt()
if (frameNumber != 0) { // frame number must be non-zero
processFrameBasedOnState(frameNumber)
} else {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2())
}
} else {
handleNoSignal(time_t)
}
}
private fun processFrameBasedOnState(frameNumber: Int) {
try {
val frame = getFrameByNumber(frameNumber)
when (currentState) {
RingBusState.NORMAL -> handleNormalState(frame, frameNumber)
RingBusState.ABORT -> handleAbortState(frame, frameNumber)
RingBusState.ELECTING -> handleElectingState(frame, frameNumber)
RingBusState.IVE_GOT_ELECTED -> handleIveGotElectedState(frame, frameNumber)
}
} catch (e: NullPointerException) {
handleFrameLoss()
}
}
private fun handleNormalState(frame: NetFrame, frameNumber: Int) {
if (msgQueue.notEmpty() || frame.shouldIintercept(mac)) {
val newFrame = doSomethingWithFrame(frame) ?: frameNumber
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, newFrame.toDouble()))
if (newFrame != frameNumber) {
frame.discardFrame()
}
} else {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, frameNumber.toDouble()))
}
}
private fun handleAbortState(frame: NetFrame, frameNumber: Int) {
if (frame.getFrameType() == "token") {
currentState = RingBusState.NORMAL
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, frameNumber.toDouble()))
} else if (frame.getFrameType() == "abort") {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, frameNumber.toDouble()))
} else {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2())
}
}
private fun handleElectingState(frame: NetFrame, frameNumber: Int) {
if (frame.getFrameType() == "ballot") {
if (frame.getBallot() < mac) {
frame.setBallot(mac)
}
if (frame.getSender() == mac && frame.getBallot() == mac) {
currentState = RingBusState.IVE_GOT_ELECTED
// elected Active Monitor sends out the first token
val newFrame = emitNewFrame(NetFrame.makeToken(mac))
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, newFrame.toDouble()))
} else {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, frameNumber.toDouble()))
}
} else {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, frameNumber.toDouble()))
}
}
private fun handleIveGotElectedState(frame: NetFrame, frameNumber: Int) {
if (frame.getFrameType() == "abort") {
// immediately return to normal state
val newFrame = emitNewFrame(NetFrame.makeToken(mac))
currentState = RingBusState.NORMAL
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, newFrame.toDouble()))
} else {
// make sure to skip a turn after the election, even if the NIC has something to send out
currentState = RingBusState.NORMAL
setWireEmissionAt(portEmit.x, portEmit.y, Vector2())
}
}
private fun handleFrameLoss() {
emitNewFrame(NetFrame.makeAbort(mac))
currentState = RingBusState.ABORT
}
private fun handleNoSignal(time_t: Long) {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2())
if (time_t - lastAccessTime > INITIAL_LISTENING_TIMEOUT) {
currentState = RingBusState.ELECTING
emitNewFrame(NetFrame.makeBallot(mac))
lastAccessTime = time_t
}
}
protected fun doSomethingWithFrame(incomingFrame: NetFrame): Int? {
return when (incomingFrame.getFrameType()) {
"token" -> doSomethingWithToken(incomingFrame)
"data" -> doSomethingWithData(incomingFrame)
"ack" -> doSomethingWithAck(incomingFrame)
"ballot" -> doSomethingWithBallot(incomingFrame)
"abort" -> 0
else -> null /* returns the frame untouched */
}
}
private fun getFrameByNumber(number: Int) = (INGAME.world.extraFields["tokenring"] as NetRunner)[number]
private fun emitNewFrame(frame: NetFrame): Int {
return (INGAME.world.extraFields["tokenring"] as NetRunner).addFrame(frame).also {
setWireEmissionAt(portEmit.x, portEmit.y, Vector2(1.0, it.toDouble()))
}
}
protected fun doSomethingWithToken(incomingFrame: NetFrame): Int? {
if (msgQueue.isEmpty) return null
val (recipient, msgByte) = msgQueue.removeFirst()
return emitNewFrame(NetFrame.makeData(mac, recipient, msgByte))
}
protected fun doSomethingWithData(incomingFrame: NetFrame): Int? {
val rec = incomingFrame.getDataRecipient()
// if the message is for me, put incoming message into queue, then send out ack
if (rec == mac) {
msgLog.addLast(rec to incomingFrame)
val datagramme = incomingFrame.getDataContents()
val (ret, nextMsg) = if (datagramme == null) (-1 to null) else ringBusFirmware.workWithDataFrame(mac, datagramme)
// make ack
return emitNewFrame(NetFrame.makeAck(mac, incomingFrame.getSender(), ret))
}
else return null
}
protected fun doSomethingWithAck(incomingFrame: NetFrame): Int? {
if (msgQueue.isEmpty) return null
val topMsg = msgQueue.first()
// if the ACK is sent to me...
if (incomingFrame.getDataRecipient() == mac && incomingFrame.getSender() == topMsg.first) {
// ack or nak?
val successful = (incomingFrame.getAckStatus() == 0)
// if successful, remove the message from the queue, then send out empty token
// if failed, keep the message, then send out empty token anyway
if (successful) {
msgQueue.removeFirst()
}
// make an empty token
return emitNewFrame(NetFrame.makeToken(mac))
}
else return null
}
protected fun doSomethingWithBallot(incomingFrame: NetFrame): Int? {
val ballotStatus = incomingFrame.getFrameNumber()
// frame is in election phase
if (ballotStatus == 0) {
// if i'm also in the election phase, participate
if (activeMonitorStatus == 0) {
if (incomingFrame.getBallot() < mac) {
incomingFrame.setBallot(mac)
}
// check if the election must be finished
if (incomingFrame.getSender() == mac && incomingFrame.getBallot() == mac) {
activeMonitorStatus = 2
// send out first empty token
return emitNewFrame(NetFrame.makeToken(mac))
}
}
// if i'm in the winner announcement phase, kill the frame
else {
incomingFrame.discardFrame()
return 0
}
}
// frame is in winner announcement phase
else if (ballotStatus == 1) {
activeMonitorStatus = 1
}
return null
}
}

View File

@@ -0,0 +1,62 @@
package net.torvald.terrarum.modulecomputers.gameactors
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.Point2i
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.BlockBox
import net.torvald.terrarum.modulebasegame.gameworld.NetFrame.Companion.toMAC
import net.torvald.terrarum.modulecomputers.ui.UIRingBusAnalyser
import net.torvald.terrarum.modulecomputers.ui.UIRingBusExerciser
/**
* Created by minjaesong on 2025-03-03.
*/
class FixtureRingBusExerciser : FixtureRingBusCore {
constructor() : super(
portEmit = Point2i(0, 0),
portSink = Point2i(1, 0),
blockBox = BlockBox(BlockBox.NO_COLLISION, 2, 2),
nameFun = { Lang["ITEM_DEBUG_RING_BUS_EXERCISER"] }
) {
this.mainUI = UIRingBusExerciser(this)
}
override fun drawBody(frameDelta: Float, batch: SpriteBatch) {
super.drawBody(frameDelta, batch)
// draw its own MAC address
drawUsingDrawFunInGoodPosition(frameDelta) { x, y ->
App.fontSmallNumbers.draw(batch, super.mac.toMAC(), x, y + 2*TILE_SIZE - 12)
}
}
}
/**
* Created by minjaesong on 2025-03-03.
*/
class FixtureRingBusAnalyser : FixtureRingBusCore {
constructor() : super(
portEmit = Point2i(0, 0),
portSink = Point2i(1, 0),
blockBox = BlockBox(BlockBox.NO_COLLISION, 2, 1),
nameFun = { Lang["ITEM_DEBUG_RING_BUS_ANALYSER"] },
) {
this.mainUI = UIRingBusAnalyser(this)
}
override fun drawBody(frameDelta: Float, batch: SpriteBatch) {
super.drawBody(frameDelta, batch)
// draw its own MAC address
drawUsingDrawFunInGoodPosition(frameDelta) { x, y ->
App.fontSmallNumbers.draw(batch, super.mac.toMAC(), x, y + 1*TILE_SIZE - 12)
}
}
}

View File

@@ -0,0 +1,60 @@
package net.torvald.terrarum.modulecomputers.gameactors
import net.torvald.terrarum.serialise.*
open class RingBusFirmware(val devtype: Int) {
fun workWithDataFrame(hostMAC: Int, datagramme: ByteArray): Pair<Int, ByteArray?> {
if (datagramme.size < 12) return -1 to null
val protocol = datagramme[0].toUint()
val mode = datagramme[1].toUint()
val arg1 = datagramme.toBigInt16(2)
val recipient = datagramme.toBigInt32(4)
val sender = datagramme.toBigInt32(8)
val body = datagramme.sliceArray(12 until datagramme.size)
return invoke(hostMAC, protocol, mode, arg1, recipient, sender, body, datagramme)
}
open fun invoke(hostMAC: Int, protocol: Int, mode: Int, arg1: Int, recipient: Int, sender: Int, body: ByteArray, datagramme: ByteArray): Pair<Int, ByteArray?> {
return when (protocol) {
1 -> 0 to echo(recipient, sender, body)
2 -> 0 to blockTransfer(arg1, recipient, sender, body)
4 -> 0 to deviceDiscovery(hostMAC, datagramme)
else -> -1 to null
}
}
open fun echo(recipient: Int, sender: Int, body: ByteArray): ByteArray {
return ByteArray(8 + body.size).makeEmptyPacket(1, 1, 0, recipient, sender).also {
it.writeBigInt48(System.currentTimeMillis(), 12)
System.arraycopy(body, 6, this, 6, body.size - 6)
}
}
open fun blockTransfer(sequence: Int, recipient: Int, sender: Int, body: ByteArray): ByteArray {
return ByteArray(12).makeEmptyPacket(2, 1, sequence, recipient, sender) // always ACK
}
open fun deviceDiscovery(host: Int, wholeMessage: ByteArray): ByteArray {
return ByteArray(wholeMessage.size + 6).also {
System.arraycopy(wholeMessage, 0, it, 0, wholeMessage.size)
it[it.size - 5] = devtype.toByte()
it.writeBigInt32(host, it.size - 4)
}
}
private fun ByteArray.makeEmptyPacket(protocol: Int, mode: Int, arg1: Int, recipient: Int, sender: Int): ByteArray {
this[0] = protocol.toByte()
this[1] = mode.toByte()
this.writeBigInt16(arg1, 2)
this.writeBigInt32(recipient, 4)
this.writeBigInt32(sender, 8)
return this
}
}

View File

@@ -0,0 +1,89 @@
package net.torvald.terrarum.modulecomputers.gameitems
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
/**
* Created by minjaesong on 2025-03-30.
*/
class ItemComputerConsole(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulecomputers.gameactors.FixtureComputerConsole") {
override var dynamicID: ItemID = originalID
override var baseMass = 80.0
override val canBeDynamic = false
override val materialId = "STAL"
init {
itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_operator_terminal.tga")
}
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_COMPUTER_CONSOLE"
}
/**
* Created by minjaesong on 2025-03-30.
*/
class ItemComputerProcessor(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulecomputers.gameactors.FixtureComputerProcessor") {
override var dynamicID: ItemID = originalID
override var baseMass = 200.0
override val canBeDynamic = false
override val materialId = "STAL"
init {
itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_cpu.tga")
}
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_COMPUTER_PROCESSOR"
}
/**
* Created by minjaesong on 2025-04-01.
*/
class ItemNetworkInterface(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulecomputers.gameactors.FixtureNetworkInterface") {
override var dynamicID: ItemID = originalID
override var baseMass = 200.0
override val canBeDynamic = false
override val materialId = "STAL"
init {
itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_network_interface.tga")
}
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_NETWORK_INTERFACE"
}
/**
* Created by minjaesong on 2025-04-01.
*/
class ItemNetworkBridge(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulecomputers.gameactors.FixtureNetworkBridge") {
override var dynamicID: ItemID = originalID
override var baseMass = 200.0
override val canBeDynamic = false
override val materialId = "STAL"
init {
itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_network_bridge.tga")
}
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_NETWORK_BRIDGE"
}
/**
* Created by minjaesong on 2025-04-01.
*/
class ItemMemoryCabinet(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulecomputers.gameactors.FixtureMemoryCabinet") {
override var dynamicID: ItemID = originalID
override var baseMass = 80.0
override val canBeDynamic = false
override val materialId = "STAL"
init {
itemImage = FixtureItemBase.getItemImageFromSingleImage("dwarventech", "sprites/fixtures/computer_memory_stack_1.tga")
}
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_MEMORY_CABINET"
}

View File

@@ -0,0 +1,79 @@
package net.torvald.terrarum.modulecomputers.gameitems
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.WireCodex
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.FixtureInteractionBlocked
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.gameitems.BlockBase
/**
* Created by minjaesong on 2025-03-30.
*/
class WirePieceNetworkBus(originalID: ItemID, private val atlasID: String, private val sheetX: Int, private val sheetY: Int)
: GameItem(originalID), FixtureInteractionBlocked {
override var dynamicID: ItemID = originalID
override var baseMass = 0.001
override var baseToolSize: Double? = null
override var inventoryCategory = Category.WIRE
override val canBeDynamic = false
override val materialId = ""
init {
itemImage = CommonResourcePool.getAsItemSheet(atlasID).get(sheetX, sheetY)
}
init {
equipPosition = GameItem.EquipPosition.HAND_GRIP
originalName = "ITEM_NETWORK_BUS_WIRE"
tags.addAll(WireCodex[originalID].tags)
}
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long {
return BlockBase.wireStartPrimaryUse(actor,this, delta)
}
override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) {
BlockBase.wireEffectWhenEquipped(this, delta)
}
override fun effectOnUnequip(actor: ActorWithBody) {
BlockBase.wireEffectWhenUnequipped(this)
}
}
/**
* Created by minjaesong on 2025-03-30.
*/
class WirePieceIOBus(originalID: ItemID, private val atlasID: String, private val sheetX: Int, private val sheetY: Int)
: GameItem(originalID), FixtureInteractionBlocked {
override var dynamicID: ItemID = originalID
override var baseMass = 0.001
override var baseToolSize: Double? = null
override var inventoryCategory = Category.WIRE
override val canBeDynamic = false
override val materialId = ""
init {
itemImage = CommonResourcePool.getAsItemSheet(atlasID).get(sheetX, sheetY)
}
init {
equipPosition = GameItem.EquipPosition.HAND_GRIP
originalName = "ITEM_IO_BUS_WIRE"
tags.addAll(WireCodex[originalID].tags)
}
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long {
return BlockBase.wireStartPrimaryUse(actor,this, delta)
}
override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) {
BlockBase.wireEffectWhenEquipped(this, delta)
}
override fun effectOnUnequip(actor: ActorWithBody) {
BlockBase.wireEffectWhenUnequipped(this)
}
}

View File

@@ -0,0 +1,101 @@
package net.torvald.terrarum.modulecomputers.ui
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.ifNaN
import net.torvald.terrarum.modulecomputers.gameactors.FixtureRingBusCore
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemVertSlider
import net.torvald.terrarum.ui.Toolkit
import kotlin.math.roundToInt
class UIRingBusAnalyser(val host: FixtureRingBusCore) : UICanvas() {
override var width = Toolkit.drawWidth
override var height = App.scr.height
private val analyserPosX = 10
private val analyserPosY = 10
private val analyserWidth = width - 20
private val analyserHeight = height - 20
private val TEXT_LINE_HEIGHT = 24
private var analysisTextBuffer = ArrayList<String>()
private val analyserScroll = UIItemVertSlider(this,
analyserPosX - 18,
analyserPosY + 1,
0.0, 0.0, 1.0, analyserHeight - 2, analyserHeight - 2
)
init {
addUIitem(analyserScroll)
refreshAnalysis()
}
private fun refreshAnalysis() {
analysisTextBuffer.clear()
host.msgLog.forEach { frame ->
analysisTextBuffer.add(frame.toString())
}
// update scrollbar
analyserScroll.handleHeight = if (analysisTextBuffer.isEmpty())
analyserHeight
else
(analyserHeight.toFloat() / analysisTextBuffer.size.times(TEXT_LINE_HEIGHT))
.times(analyserHeight)
.roundToInt()
.coerceIn(12, analyserHeight)
}
private fun drawAnalysis(batch: SpriteBatch) {
val scroll = (analyserScroll.value * analysisTextBuffer.size.times(TEXT_LINE_HEIGHT)
.minus(analyserHeight - 3))
.ifNaN(0.0)
.roundToInt()
.coerceAtLeast(0)
analysisTextBuffer.forEachIndexed { index, s ->
App.fontGame.draw(batch, s,
analyserPosX + 6f,
analyserPosY + 3f + index * TEXT_LINE_HEIGHT - scroll
)
}
}
override fun updateImpl(delta: Float) {
refreshAnalysis()
uiItems.forEach { it.update(delta) }
}
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
// Draw background box
batch.color = Color(0x7F)
Toolkit.fillArea(batch, analyserPosX, analyserPosY, analyserWidth, analyserHeight)
batch.color = Toolkit.Theme.COL_INACTIVE
Toolkit.drawBoxBorder(batch, analyserPosX, analyserPosY, analyserWidth, analyserHeight)
// Draw text content
batch.color = Color.WHITE
drawAnalysis(batch)
// Draw UI elements
uiItems.forEach { it.render(frameDelta, batch, camera) }
}
override fun doOpening(delta: Float) {
refreshAnalysis()
}
override fun doClosing(delta: Float) {
// nothing needed
}
override fun dispose() {
}
}

View File

@@ -0,0 +1,101 @@
package net.torvald.terrarum.modulecomputers.ui
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.ifNaN
import net.torvald.terrarum.modulecomputers.gameactors.FixtureRingBusCore
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemVertSlider
import net.torvald.terrarum.ui.Toolkit
import kotlin.math.roundToInt
class UIRingBusExerciser(val host: FixtureRingBusCore) : UICanvas() {
override var width = Toolkit.drawWidth
override var height = App.scr.height
private val analyserPosX = 10
private val analyserPosY = 10
private val analyserWidth = width - 20
private val analyserHeight = height - 20
private val TEXT_LINE_HEIGHT = 24
private var analysisTextBuffer = ArrayList<String>()
private val analyserScroll = UIItemVertSlider(this,
analyserPosX - 18,
analyserPosY + 1,
0.0, 0.0, 1.0, analyserHeight - 2, analyserHeight - 2
)
init {
addUIitem(analyserScroll)
refreshAnalysis()
}
private fun refreshAnalysis() {
analysisTextBuffer.clear()
host.msgLog.forEach { frame ->
analysisTextBuffer.add(frame.toString())
}
// update scrollbar
analyserScroll.handleHeight = if (analysisTextBuffer.isEmpty())
analyserHeight
else
(analyserHeight.toFloat() / analysisTextBuffer.size.times(TEXT_LINE_HEIGHT))
.times(analyserHeight)
.roundToInt()
.coerceIn(12, analyserHeight)
}
private fun drawAnalysis(batch: SpriteBatch) {
val scroll = (analyserScroll.value * analysisTextBuffer.size.times(TEXT_LINE_HEIGHT)
.minus(analyserHeight - 3))
.ifNaN(0.0)
.roundToInt()
.coerceAtLeast(0)
analysisTextBuffer.forEachIndexed { index, s ->
App.fontGame.draw(batch, s,
analyserPosX + 6f,
analyserPosY + 3f + index * TEXT_LINE_HEIGHT - scroll
)
}
}
override fun updateImpl(delta: Float) {
refreshAnalysis()
uiItems.forEach { it.update(delta) }
}
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
// Draw background box
batch.color = Color(0x7F)
Toolkit.fillArea(batch, analyserPosX, analyserPosY, analyserWidth, analyserHeight)
batch.color = Toolkit.Theme.COL_INACTIVE
Toolkit.drawBoxBorder(batch, analyserPosX, analyserPosY, analyserWidth, analyserHeight)
// Draw text content
batch.color = Color.WHITE
drawAnalysis(batch)
// Draw UI elements
uiItems.forEach { it.render(frameDelta, batch, camera) }
}
override fun doOpening(delta: Float) {
refreshAnalysis()
}
override fun doClosing(delta: Float) {
// nothing needed
}
override fun dispose() {
}
}

View File

@@ -1,6 +1,6 @@
## Aperçu ##
This project is to create a modular game engine that accommodates a 2D side-scrolling tilemap platformer, and a game that runs on top of it.
The goal of this project is to create a modular game engine that accommodates a 2D side-scrolling tilemap platformer, and a game that runs on top of it.
The project is divided into two parts: **Terrarum the Game Engine** and **Terrarum the actual game**.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
{"n":"FR Azerty","capslock":"shift","t":[[""],[undefined],
{"n":"FR Azerty","capslock":"shift","l":"iso","t":[[""],[undefined],
[undefined],
["<HOME>"],
[undefined],
@@ -237,7 +237,7 @@
[undefined],
[undefined],
[undefined],
[undefined],
["<",">","≤","≥"],
[undefined],
[undefined],
[undefined],

View File

@@ -254,7 +254,7 @@ let states = {"keylayouts":[[""],[undefined],
[undefined],
[undefined]
],
"dict":IMEProvider.requestDictionary("cj5-sc.han"),
"dict":IMEProvider.requestDictionary("cangjie5_dict/cj5-sc.han"),
"code":0, //0: not composing, 1: composing (has candidates), 2: composing (no candidates)
"buf":"",
"candidates":""/*comma-separated values*/}

View File

@@ -254,7 +254,7 @@ let states = {"keylayouts":[[""],[undefined],
[undefined],
[undefined]
],
"dict":IMEProvider.requestDictionary("cj5-tc.han"),
"dict":IMEProvider.requestDictionary("cangjie5_dict/cj5-tc.han"),
"code":0, //0: not composing, 1: composing (has candidates), 2: composing (no candidates)
"buf":"",
"candidates":""/*comma-separated values*/}

View File

@@ -7,7 +7,9 @@
"CONTEXT_TIME_SECOND_PLURAL": "Seconds",
"COPYRIGHT_ALL_RIGHTS_RESERVED": "All rights reserved",
"COPYRIGHT_GNU_GPL_3": "Distributed under GNU GPL 3",
"GAME_ACTION_CHANGE_COLOR" : "Change color",
"GAME_ACTION_MOVE_VERB" : "Move",
"GAME_ACTION_PUT_DOWN" : "Put down",
"GAME_ACTION_ZOOM" : "Zoom",
"GAME_ACTION_ZOOM_OUT" : "Zoom out",
"MENU_IO_AUTOSAVE": "Autosave",
@@ -54,7 +56,7 @@
"MENU_OPTIONS_SPEAKER_HEADPHONE": "Headphone",
"MENU_OPTIONS_SPEAKER_SETUP": "Speaker Setup",
"MENU_OPTIONS_SPEAKER_STEREO": "Stereo",
"MENU_OPTIONS_STREAMERS_LAYOUT": "Chat Overlay",
"MENU_OPTIONS_STREAMERS_LAYOUT": "Space for Chat Overlay",
"MENU_CREDIT_GPL_DNT" : "GPL",
"MENU_LABEL_JVM_DNT" : "JVM",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -52,7 +52,7 @@
<btex/> abstracts away the meticulous styling and typesetting configurations, so you can focus on
actually writing your texts than debugging the <latex/> macros. This does come with a downside of
not being able to change the given style.</p>
<p><btex/> document is divided up to five parts: the <a href="btexdoc">Style Declaration</a>, the
<p><btex/> document is divided up to the five parts: the <a href="btexdoc">Style Declaration</a>, the
<a href="cover">Cover</a>, the <a href="table of contents">Table of Contents</a>, the
<a href="manuscript">Manuscript</a>, and the <a href="index page">Index Page</a>, of which the
Style Declaration and the Manuscript are the mandatory parts.</p>
@@ -87,7 +87,7 @@
</callout>
<p>Only the <code>title</code> tag is mandatory. Cover texts will be printed using a special font that has wider
gaps between characters. The title text will be printed in a double-size.</p>
<p>The cover can have different colour with the <code>hue</code> attribute, which takes a number between 0 and 360.</p>
<p>The cover can have a different colour with the <code>hue</code> attribute, which takes a number between 0 and 360.</p>
<chapter>The Table of Contents</chapter>
@@ -97,7 +97,7 @@
<callout align="left" class="code"><index id="tocpage (tag)"/>&lt;tocpage title="Custom page name if necessary"&gt;&zwsp;&lt;tableofcontents/&gt;&zwsp;&lt;/tocpage&gt;
</callout>
<p>The optional <code>title</code> attribute allows a custom name can be given to this page.
<p>The optional <code>title</code> attribute allows custom names to a page.
If unspecified, the default name is “Table of Contents”.</p>
<p>The tag <code>&lt;tableofcontents/&gt;</code> is an internal tag used by the typesetter.</p>
@@ -173,8 +173,8 @@
</callout>
<p>The <code>height</code> attribute specifies the height of the image <emph>in the number of lines</emph>,
rather than pixels, the width is calculated automatically; image width wider than the text width
will cause an error. The tag optionally takes caption attribute which prints a text below the image.</p>
rather than the pixels, the width is calculated automatically; image width wider than the text width
will cause an error. The tag optionally takes <code>caption</code> attribute which prints a text below the image.</p>
<p>Supported image formats: JPEG, PNG, BMP or TGA</p>
@@ -201,7 +201,7 @@
<chapter>Conclusion</chapter>
<p>The finished book description using <btex/> can be sent to a publisher, and if there are no errors
<p>The finished book description using <btex/> can be sent to the publisher, and if there are no errors
on your submission, the printed books of specified number of copies will be delivered to your
location within a reasonable amount of business days. Happy writing!</p>
@@ -287,14 +287,14 @@
In other words, <code>veun</code> and <code>vneun</code> are identical.</p>
<p>These tags can be used in the following situation: suppose you have a <btex/> document,</p>
<callout align="left" class="code">[en] Send your &lt;v fromgame="GAME_ITEM_HOLOTAPE"/&gt; that contains the manuscript to the publisher via mail to have your books printed.<br/><!--
<callout align="left" class="code">[en] Send your &lt;v fromgame="GAME_ITEM_HOLOTAPE"/&gt; containing the manuscript to the publisher via post to have your books printed.<br/><!--
-->[koKR] 원고가 담긴 &lt;veul fromgame="GAME_ITEM_HOLOTAPE"/&gt; 출판사로 우편을 통해 보내야 책이 인쇄됩니다.</callout>
<p>The variables will be resolved based on the current ingame language, then the necessary
linguistic processing is performed, which would result in a following paragraph
(text in blue denotes the text is inserted using the tags):</p>
<callout>[en] Send your <itemname>Holotape</itemname> that contains the manuscript to the publisher via mail to have your books printed.<br/><!--
<callout>[en] Send your <itemname>Holotape</itemname> that contains the manuscript to the publisher via post to have your books printed.<br/><!--
-->[koKR] 원고가 담긴 <itemname>홀로테이프를</itemname> 출판사로 우편을 통해 보내야 책이 인쇄됩니다.</callout>
@@ -309,12 +309,12 @@
encounter the freezing every time the book is being printed, and this would be a huge minus towards
the gameplay experience.</p>
<p>If the process exits without any error, the mailing system will be
notified and will send the mail containing finished books to the player; if the process exits
with errors, the mail containing details of the errors will be sent instead.</p>
<p>If the process exits without any error, the post system will be
notified and will send a post containing the finished books to the player; if the process exits
with errors, the post containing the details of the errors will be sent instead.</p>
<p>For this reason, the “printing press” is not exposed to the player, they only get to interact with it
indirectly through the “publisher” via mail.</p>
indirectly through the “publisher” via post.</p>

View File

@@ -0,0 +1,3 @@
id;itemid;tags
1;item@basegame:59;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
2;item@basegame:60;FLUIDSTORAGE,OPENSTORAGE
1 id itemid tags
2 1 item@basegame:59 FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
3 2 item@basegame:60 FLUIDSTORAGE,OPENSTORAGE

View File

@@ -3,6 +3,7 @@ CheatWarnTest
CodexEdictis
ExportAtlas
ExportCodices
ExportFBO
ExportMap
ExportMap2
ExportWorld
@@ -31,6 +32,7 @@ SetSol
SetTurb
SetTime
SetTimeDelta
SpawnMovingPlatform
SpawnPhysTestBall
Teleport
ToggleNoClip
1 CatStdout
3 CodexEdictis
4 ExportAtlas
5 ExportCodices
6 ExportFBO
7 ExportMap
8 ExportMap2
9 ExportWorld
32 SetTurb
33 SetTime
34 SetTimeDelta
35 SpawnMovingPlatform
36 SpawnPhysTestBall
37 Teleport
38 ToggleNoClip

View File

@@ -32,37 +32,37 @@
"wire@basegame:8192": { /* signal wire red */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
[25, 1, "item@basegame:112"] /* 1 copper */
]
},
"wire@basegame:8193": { /* signal wire green */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
[25, 1, "item@basegame:112"] /* 1 copper */
] },
"wire@basegame:8194": { /* signal wire blue */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
[25, 1, "item@basegame:112"] /* 1 copper */
]
},
"wire@basegame:8195": { /* signal wire yellow */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
[25, 1, "item@basegame:112"] /* 1 copper */
]
},
"wire@basegame:8196": { /* signal wire purple */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:112"] /* 1 copper */
[25, 1, "item@basegame:112"] /* 1 copper */
]
},
"item@basegame:50": { /* soldering wire */
"workbench": "wirerollingmill",
"ingredients": [
[10, 1, "item@basegame:181"] /* 1 solder bar */
[25, 1, "item@basegame:181"] /* 1 solder bar */
]
},

View File

@@ -58,6 +58,8 @@ id;classname;tags
57;net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalPushbutton;FIXTURE,SIGNAL
58;net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalPressurePlate;FIXTURE,SIGNAL
59;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden;CONTAINER
60;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron;CONTAINER
# ingots
112;net.torvald.terrarum.modulebasegame.gameitems.IngotCopper;INGOT
@@ -134,9 +136,10 @@ id;classname;tags
# industrial
2048;net.torvald.terrarum.modulebasegame.gameitems.ItemInductionMotor;FIXTURE,POWER,KINETIC
2049;net.torvald.terrarum.modulebasegame.gameitems.ItemGearbox;FIXTURE,POWER,KINETIC
2050;net.torvald.terrarum.modulebasegame.gameitems.ItemConveyorBelt;FIXTURE,KINETIC
# data storage (discs; 256)
# 32768 is a reserved number for a blank disc
# data storage (pre-composed discs; 256)
# 32768 is a reserved number for a BASEOBJECT disc (players can't produce own recordings... yet)
32769;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc01;MUSIC,PHONO
32770;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc02;MUSIC,PHONO
32771;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc03;MUSIC,PHONO
@@ -147,19 +150,39 @@ id;classname;tags
32776;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc08;MUSIC,PHONO
32777;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09;MUSIC,PHONO
# data storage (tapestries; 256)
#33024;net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry;FIXTURE,BASEOBJECT
# data storage (pre-composed tapestries; 256)
33024;net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry;FIXTURE,BASEOBJECT
# data storage (text signs; 256)
# data storage (pre-composed text signs; 256)
33280;net.torvald.terrarum.modulebasegame.gameitems.ItemTextSignCopper;FIXTURE,BASEOBJECT
# data storage (pre-composed typewritten leaflets; 256)
33536;net.torvald.terrarum.modulebasegame.gameitems.ItemPlainDocument;READINGS,BASEOBJECT
# data storage (pre-composed unsealed letters; 256)
33792;net.torvald.terrarum.modulebasegame.gameitems.ItemUnsealedLetter;POST,BASEOBJECT
# data storage (pre-composed sealed letters; 256)
34048;net.torvald.terrarum.modulebasegame.gameitems.ItemSealedLetter;POST,BASEOBJECT
# data storage (pre-composed delivery packets; 256)
34304;net.torvald.terrarum.modulebasegame.gameitems.ItemPostParcel;POST,PARCEL,BASEOBJECT
# give it 65536 or greater ID so it would not be able to be redeemed by a code
65536;net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef;BASEOBJECT
# fluids on storage
# preferably autogenerated
# FUTURE QUEST: autogenerate them using CANISTERS CODEX
# with new ItemID scheme:
# basegame_2<fluid@basegame:1
# stands for a wooden bucket (CANISTERS basegame_2) holding a block of water (fluid@basegame:1)
#
# FLUIDSTORAGE: required tag for buckets/canisters
# OPENSTORAGE: cannot hold gas. Canisters need LIDDEDSTORAGE/SEALEDSTORAGE
# NOEXTREMETHERM: cannot hold cryogenic/molten fluids (can only hold fluid with therm 0 or 1)
#
# BELOW ARE COMPELETY IRRELEVANT AND PENDING FOR REMOVAL
# 100000h..1000FFh : container type 0 x Fluid type 0..255
# 100100h..1001FFh : container type 1 x Fluid type 0..255
# 100200h..1002FFh : container type 2 x Fluid type 0..255
@@ -168,16 +191,20 @@ id;classname;tags
# 100500h..1005FFh : container type 5 x Fluid type 0..255
# ...
# 10FF00h..10FFFFh : container type 255 x Fluid type 0..255
1048576;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden00;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM,FLUIDSTORAGEEMPTY
1048577;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden01;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
#1048578;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden02;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
1048579;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden03;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
1048832;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron00;FLUIDSTORAGE,OPENSTORAGE,FLUIDSTORAGEEMPTY
1048833;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron01;FLUIDSTORAGE,OPENSTORAGE
1048834;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron02;FLUIDSTORAGE,OPENSTORAGE
1048835;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron03;FLUIDSTORAGE,OPENSTORAGE
# reserved for debug items
#1048576;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden00;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM,FLUIDSTORAGEEMPTY
#1048577;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden01;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
##1048578;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden02;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
#1048579;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden03;FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
#
#1048832;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron00;FLUIDSTORAGE,OPENSTORAGE,FLUIDSTORAGEEMPTY
#1048833;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron01;FLUIDSTORAGE,OPENSTORAGE
#1048834;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron02;FLUIDSTORAGE,OPENSTORAGE
#1048835;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron03;FLUIDSTORAGE,OPENSTORAGE
#
## reserved for debug items
#ifdef App.IS_DEVELOPMENT_BUILD
16777216;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessWaterBucket;DEBUG,TOOL
16777217;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessLavaBucket;DEBUG,TOOL
16777472;net.torvald.terrarum.modulebasegame.gameitems.ItemMysteriousATM;DEBUG
16777473;net.torvald.terrarum.modulebasegame.gameitems.ItemDebugInventron;DEBUG
#endif
1 id classname tags
58 58 net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalPressurePlate FIXTURE,SIGNAL
59 # ingots 59 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden CONTAINER
60 112 60 net.torvald.terrarum.modulebasegame.gameitems.IngotCopper net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron INGOT CONTAINER
61 # ingots
62 112 net.torvald.terrarum.modulebasegame.gameitems.IngotCopper INGOT
63 113 net.torvald.terrarum.modulebasegame.gameitems.IngotIron INGOT
64 114 net.torvald.terrarum.modulebasegame.gameitems.ItemCoalCoke COMBUSTIBLE
65 115 net.torvald.terrarum.modulebasegame.gameitems.IngotZinc INGOT
136 32776 32775 net.torvald.terrarum.modulebasegame.gameitems.MusicDisc08 net.torvald.terrarum.modulebasegame.gameitems.MusicDisc07 MUSIC,PHONO
137 32777 32776 net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09 net.torvald.terrarum.modulebasegame.gameitems.MusicDisc08 MUSIC,PHONO
138 # data storage (tapestries 32777 256) net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09 MUSIC,PHONO
139 # data storage (pre-composed tapestries 256)
140 #33024 33024 net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry FIXTURE,BASEOBJECT
141 # data storage (text signs # data storage (pre-composed text signs 256)
142 33280 net.torvald.terrarum.modulebasegame.gameitems.ItemTextSignCopper FIXTURE,BASEOBJECT
143 # fluids on storage # data storage (pre-composed typewritten leaflets 256)
144 # preferably autogenerated 33536 net.torvald.terrarum.modulebasegame.gameitems.ItemPlainDocument READINGS,BASEOBJECT
145 # FLUIDSTORAGE: required tag for buckets/canisters # data storage (pre-composed unsealed letters 256)
150 # 100200h..1002FFh : container type 2 x Fluid type 0..255 34304 net.torvald.terrarum.modulebasegame.gameitems.ItemPostParcel POST,PARCEL,BASEOBJECT
151 # 100300h..1003FFh : container type 3 x Fluid type 0..255 # give it 65536 or greater ID so it would not be able to be redeemed by a code
152 # 100400h..1004FFh : container type 4 x Fluid type 0..255 65536 net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef BASEOBJECT
153 # 100500h..1005FFh : container type 5 x Fluid type 0..255 # fluids on storage
154 # ... # FUTURE QUEST: autogenerate them using CANISTERS CODEX
155 # 10FF00h..10FFFFh : container type 255 x Fluid type 0..255 # with new ItemID scheme:
156 1048576 # basegame_2<fluid@basegame:1
157 1048577 # stands for a wooden bucket (CANISTERS basegame_2) holding a block of water (fluid@basegame:1)
158 #1048578 #
159 # FLUIDSTORAGE: required tag for buckets/canisters
160 # OPENSTORAGE: cannot hold gas. Canisters need LIDDEDSTORAGE/SEALEDSTORAGE
161 1048579 # NOEXTREMETHERM: cannot hold cryogenic/molten fluids (can only hold fluid with therm 0 or 1)
162 #
163 # BELOW ARE COMPELETY IRRELEVANT AND PENDING FOR REMOVAL
164 # 100000h..1000FFh : container type 0 x Fluid type 0..255
165 # 100100h..1001FFh : container type 1 x Fluid type 0..255
166 # 100200h..1002FFh : container type 2 x Fluid type 0..255
167 # 100300h..1003FFh : container type 3 x Fluid type 0..255
168 # 100400h..1004FFh : container type 4 x Fluid type 0..255
169 # 100500h..1005FFh : container type 5 x Fluid type 0..255
170 # ...
171 # 10FF00h..10FFFFh : container type 255 x Fluid type 0..255
172 #1048576 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden00 FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM,FLUIDSTORAGEEMPTY
173 #1048577 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden01 FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
174 1048832 ##1048578 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron00 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden02 FLUIDSTORAGE,OPENSTORAGE,FLUIDSTORAGEEMPTY FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
175 1048833 #1048579 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron01 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketWooden03 FLUIDSTORAGE,OPENSTORAGE FLUIDSTORAGE,OPENSTORAGE,NOEXTREMETHERM
176 1048834 #
177 #1048832 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron00 FLUIDSTORAGE,OPENSTORAGE,FLUIDSTORAGEEMPTY
178 #1048833 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron01 FLUIDSTORAGE,OPENSTORAGE
179 #1048834 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron02 FLUIDSTORAGE,OPENSTORAGE
180 #1048835 net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron03 FLUIDSTORAGE,OPENSTORAGE
181 1048835 #
182 # reserved for debug items ## reserved for debug items
183 16777216 #ifdef App.IS_DEVELOPMENT_BUILD
184 16777216 net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessWaterBucket DEBUG,TOOL
185 16777217 net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessLavaBucket DEBUG,TOOL
186 16777217 16777472 net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessLavaBucket net.torvald.terrarum.modulebasegame.gameitems.ItemMysteriousATM DEBUG,TOOL DEBUG
187 16777473 net.torvald.terrarum.modulebasegame.gameitems.ItemDebugInventron DEBUG
188 #endif
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Binary file not shown.

View File

@@ -1,6 +1,10 @@
{
"MENU_MONITOR_CALI_TITLE": "Check Monitor",
"MENU_OPTIONS_AUDIO_COMP": "Enhance Quiet Sounds",
"MENU_OPTIONS_DISABLE": "Disable",
"MENU_OPTIONS_LIGHT": "Light",
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "Show Ore Tooltip When Mining",
"MENU_OPTIONS_STRONG": "Strong",
"MENU_OPTIONS_MAX_CRAFTING": "Max Number of Items for Crafting",
"MENU_OPTIONS_UNIT_BLOCKS": "Blocks",
"MENU_OPTIONS_UNIT_FEET": "Imperial",

View File

@@ -1,5 +1,6 @@
{
"ITEM_ALLOYING_FURNACE": "Alloying Furnace",
"ITEM_AXLE": "Axle",
"ITEM_BRICK_SINGULAR": "Brick", /* always singular */
"ITEM_BUCKET_IRON": "Iron Bucket %1$s",
"ITEM_BUCKET_WOODEN": "Wooden Bucket %1$s",
@@ -17,6 +18,7 @@
"ITEM_ELECTRIC_WORKBENCH": "Electric Workbench",
"ITEM_ENGRAVING_WORKBENCH": "Engraving Workbench",
"ITEM_FURNACE_AND_ANVIL": "Furnace and Anvil",
"ITEM_GEARBOX": "Gearbox",
"ITEM_GEM_RUBY": "Raw Ruby",
"ITEM_GEM_EMERALD": "Raw Emerald",
"ITEM_GEM_SAPPHIRE": "Raw Sapphire",
@@ -30,6 +32,7 @@
"ITEM_HATCHET_STEEL": "Steel Axe",
"ITEM_HATCHET_STONE": "Stone Axe",
"ITEM_HATCHET_WOODEN": "Wooden Axe",
"ITEM_INDUCTION_MOTOR": "Induction Motor",
"ITEM_INGOT_BRASS": "Brass Ingot",
"ITEM_INGOT_BRONZE": "Bronze Ingot",
"ITEM_INGOT_COPPER": "Copper Ingot",

View File

@@ -1,6 +1,10 @@
{
"MENU_MONITOR_CALI_TITLE": "모니터 확인",
"MENU_OPTIONS_AUDIO_COMP": "조용한 소리 증폭",
"MENU_OPTIONS_DISABLE": "비활성화",
"MENU_OPTIONS_LIGHT": "약하게",
"MENU_OPTIONS_SHOW_ORES_TOOLTIP_WHEN_MINING": "채굴 시 광석 툴팁 보이기",
"MENU_OPTIONS_STRONG": "강하게",
"MENU_OPTIONS_MAX_CRAFTING": "한번에 제작할 최대 아이템 수",
"MENU_OPTIONS_UNIT_BLOCKS": "블록",
"MENU_OPTIONS_UNIT_FEET": "피트",

View File

@@ -1,3 +1,4 @@
## this file is auto-generated using Prebuild.kt ##
# The name that will be displayed in-game
propername=Terrarum
@@ -44,10 +45,10 @@ package=net.torvald.terrarum.modulebasegame
entrypoint=net.torvald.terrarum.modulebasegame.EntryPoint
# Release date in YYYY-MM-DD
releasedate=2024-03-28
releasedate=2025-01-19
# The version, must follow Semver 2.0.0 scheme (https://semver.org/)
version=0.4.2
version=0.5.2
# External JAR that the module is compiled. If your module requires yet another library, the JAR must be compiled as a "Fatjar";
# Due to security reasons, loading an arbitrary JAR is not allowed.

Binary file not shown.

View File

@@ -1,8 +1,8 @@
{
"identifier": "clear01",
"skyboxGradColourMap": "generic_skybox.tga",
"daylightClut": "clut_daylight.tga",
"tags": "generic,clear",
"skyboxGradColourMap": "model:hosek",
"daylightClut": "lut:clut_daylight.tga",
"tags": "terrestrial,generic,clear",
"cloudChance": 12,
"cloudGamma": [1.2, 2.4],
"cloudGammaVariance": [0.111, 0.0],

View File

@@ -1,8 +1,8 @@
{
"identifier": "generic01",
"skyboxGradColourMap": "generic_skybox.tga",
"daylightClut": "clut_daylight.tga",
"tags": "generic",
"skyboxGradColourMap": "model:hosek",
"daylightClut": "lut:clut_daylight.tga",
"tags": "terrestrial,generic",
"cloudChance": 60,
"cloudGamma": [0.9, 2.4],
"cloudGammaVariance": [0.111, 0.0],

View File

@@ -1,8 +1,8 @@
{
"identifier": "generic02",
"skyboxGradColourMap": "generic_skybox.tga",
"daylightClut": "clut_daylight.tga",
"tags": "generic2",
"skyboxGradColourMap": "model:hosek",
"daylightClut": "lut:clut_daylight.tga",
"tags": "terrestrial,generic",
"cloudChance": 150,
"cloudGamma": [0.9, 2.4],
"cloudGammaVariance": [0.111, 0.0],

View File

@@ -1,8 +1,8 @@
{
"identifier": "overcast01",
"skyboxGradColourMap": "generic_skybox.tga",
"daylightClut": "clut_daylight.tga",
"tags": "overcast",
"skyboxGradColourMap": "model:hosek",
"daylightClut": "lut:clut_daylight.tga",
"tags": "terrestrial,overcast",
"cloudChance": 200,
"cloudGamma": [1.45, 1.0],
"cloudGammaVariance": [0.0, 0.0],

View File

@@ -0,0 +1,15 @@
{
"identifier": "space",
"skyboxGradColourMap": "static:#020202,#060604",
"daylightClut": "static:#FFF7",
"tags": "space",
"cloudChance": 0,
"cloudGamma": [1.0, 1.0],
"cloudGammaVariance": [0.0, 0.0],
"windSpeed": 0.0,
"windSpeedVariance": 0.0,
"windSpeedDamping": 0.0,
"clouds": {},
"atmoTurbidity": 1.0,
"shaderVibrancy": [1.0, 1.0]
}

View File

@@ -1,13 +1,12 @@
id;drop;name;renderclass;accept;inputcount;inputtype;outputtype;javaclass;inventoryimg;branching;tags
8192;8192;WIRE_RED;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,4;1;"SIGNALWIRE"
8193;8193;WIRE_GREEN;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,1,4;1;"SIGNALWIRE"
8194;8194;WIRE_BLUE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,2,4;1;"SIGNALWIRE"
8195;8195;WIRE_YELLOW;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,3,4;1;"SIGNALWIRE"
8196;8196;WIRE_PURPLE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,4,4;1;"SIGNALWIRE"
8192;8192;WIRE_RED;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,0,4;3;"SIGNALWIRE"
8193;8193;WIRE_GREEN;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,1,4;3;"SIGNALWIRE"
8194;8194;WIRE_BLUE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,2,4;3;"SIGNALWIRE"
8195;8195;WIRE_YELLOW;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,3,4;3;"SIGNALWIRE"
8196;8196;WIRE_PURPLE;signal;digital_bit;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,4,4;3;"SIGNALWIRE"
1;1;WIRE_POWER_LOW;power;power_low;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,5,4;1;"POWERWIRE_LOW"
2;2;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,6,4;1;"POWERWIRE_HIGH"
16;16;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,7,4;1;"ETHERNETWIRE"
256;256;AXLE;axle;axle;1;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceAxle;basegame.items,1,5;0;"AXLE"
@@ -15,7 +14,8 @@ id;drop;name;renderclass;accept;inputcount;inputtype;outputtype;javaclass;invent
# inputcount: how many sides are input (outputcount is deduced from the inputcount). N/A for wires
# inputtype: which wiretype it accepts. N/A for wires
# outputtype: which wiretype it emits. N/A for wires
# branching: if this wire can have branches. Something like a thicknet can't have branches
# branching: if this wire can have branches. 0: unable, 1: tee-only, 2: cross-only, 3: tee and cross.
# Something like a thicknet can't have branches
#
# comments
# digital_3bits must come right after three wires it bundles
1 id drop name renderclass accept inputcount inputtype outputtype javaclass inventoryimg branching tags
2 8192 8192 WIRE_RED signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,0,4 1 3 SIGNALWIRE
3 8193 8193 WIRE_GREEN signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,1,4 1 3 SIGNALWIRE
4 8194 8194 WIRE_BLUE signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,2,4 1 3 SIGNALWIRE
5 8195 8195 WIRE_YELLOW signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,3,4 1 3 SIGNALWIRE
6 8196 8196 WIRE_PURPLE signal digital_bit 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,4,4 1 3 SIGNALWIRE
7 1 1 WIRE_POWER_LOW power power_low 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,5,4 1 POWERWIRE_LOW
8 2 2 WIRE_POWER_HIGH power power_high 3 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire basegame.items,6,4 1 POWERWIRE_HIGH
9 16 256 16 256 WIRE_ETHERNET AXLE network axle 10base2 axle 3 1 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire net.torvald.terrarum.modulebasegame.gameitems.WirePieceAxle basegame.items,7,4 basegame.items,1,5 1 0 ETHERNETWIRE AXLE
256 256 AXLE axle axle 1 N/A N/A net.torvald.terrarum.modulebasegame.gameitems.WirePieceAxle basegame.items,1,5 0 AXLE
10 # accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka not wires)
11 # inputcount: how many sides are input (outputcount is deduced from the inputcount). N/A for wires
12 # inputtype: which wiretype it accepts. N/A for wires
14 # branching: if this wire can have branches. Something like a thicknet can't have branches # branching: if this wire can have branches. 0: unable, 1: tee-only, 2: cross-only, 3: tee and cross.
15 # # Something like a thicknet can't have branches
16 # comments #
17 # digital_3bits must come right after three wires it bundles # comments
18 # digital_3bits must come right after three wires it bundles
19 # what's the point of WIRE_BUNDLE when you can overlap as many wires as you want? -- Torvald, 2021-08-09
20
21

View File

@@ -0,0 +1,84 @@
"id";"drop";"spawn";"name";"shdr";"shdg";"shdb";"shduv";"str";"dsty";"mate";"solid";"wall";"grav";"dlfn";"fv";"fr";"lumr";"lumg";"lumb";"lumuv";"refl";"tags"
## Notes ##
#
# Every block must have a shade value that is at least as dark as the air block's
#
# Lava/Water props are left for future references, do not delete them until FluidCodex is built #
#
# id: Block ID. ID equal to or greater than 4096 is for fluids, mainly for lighting calculation.
# drop: Which item the DroppedItem actually adds to your inventory
# spawn: Which item the DroppedItem should impersonate when spawned
#
# Drop and World can point to the item from other modules (usually 'basegame')
# To achieve that, specify the full ID, e.g. basegame:32
# When no module ID is specified, the current module will be assumed.
#
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
# valid range: float of 0..4; 1.0 for 255
#
# solid: whether the tile has full collision (affects physics; flowers are not solid, glass is solid)
# clear: [PENDING FOR REMOVAL] whether the tile has trnasparency (affects render; flowers AND glass is clear)
#
# vscs: viscosity, (velocity) / (1 + (n/16)), 16 halves movement speed, can be used to non-fluid tiles (sticky hazard, tarmac road in Terraria)
#
# str: Strength of the block against the mining action. Larger value will make the block take longer time to be mined
#
# dsty: density. As we are putting water an 1000, it is identical to specific gravity. [g/l]
#
# dlfn: dynamic luminosity function.
# 0-static, 1-torch flicker, 2-current global light (sun, star, moon), 3-daylight at noon,
# 4-slow breath, 5-pulsate
#
# mate: material, four-letter code
#
# fv: vertical friction (boolean)
# fr: horizontal friction. 0: frictionless, <16: slippery, 16: regular, >16: sticky
#
# grav: Whether the block should fall through the empty space. N/A to not make it fall;
# 0 to fall immediately (e.g. Sand), nonzero to indicate that number of floating blocks can be supported (e.g. Scaffolding)
#
#
## Illuminators ##
#
# Illuminator white: Mercury Lamp; CIELAB of (94, -5.131, 10.613), which is made out of CIEXYZ of (0.947638, 1.146481, 0.482263), measured with ColorMunki Spectrometer (If you don't want green tinge, collect a daylight!)
# Illuminator orange: Sodium Lamp; CIE xy of (0.5375, 0.4153), CIEXYZ of (352.531139, 272.379377, 30.980339), measured with ColorMunki Spectrometer
# Defalut torch : Y 64 x 0.55183 y 0.40966 (Planckian ~1 770 K); real candlelight colour taken from Spyder5 colorimeter (for I couldn't afford i1DisplayPro/Colormunki -- at least back then!)
# Sunstone: Artificial sunlight, change colour over time in sync with sunlight. The light is set by game's code.
# Sunlight capacitor: daylight at noon. Set by game's code.
#
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
# 1. It has quite a brightness on RGB colour space
# 2. Helmholz-Kohlraush effect
#
#
## Tiles ##
#
# 16 colour palette : games's 16-colour palette
# Magical ice: theoretical __metallic__ ice that might form under super-high pressure (> 5 TPa). Its density is a wild guess.
#
#
## Actorblocks ##
#
# Actorblocks are virtual/placeholder blocks that accompanies actors (usually fixtures).
# Actorblocks are recognised by the "ACTORBLOCK" tag.
#
## Tags ##
#
# Tag(s) to the item which is used by the crafting system and the game's internals. Multiple tags are separated using commas.
# Each tag must be all uppercase and only [0-9A-Z] chars are supported.
#
### Internal Tags ##
##
## Some tags are reserved for internal use, which are:
## - INTERNAL: denotes that the tile is internal-use.
## - DORENDER: this internal tile must go through the standard-issue tile drawing routine.
## - INCONSEQUENTIAL: denotes that this tile can be overwritten without dropping it. Usually used with flower tiles.
#
#
## References ##
#
# * Density of various woods : http://www.engineeringtoolbox.com/wood-density-d_40.html
# * Density of various phases of ice : http://www1.lsbu.ac.uk/water/ice_phases.html
#
Can't render this file because it contains an unexpected character in line 65 and column 37.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 129 B

View File

@@ -1,3 +1,5 @@
id;classname
1;net.torvald.terrarum.modulecomputers.gameitems.ItemWearableWorldRadar
2;net.torvald.terrarum.modulecomputers.gameitems.ItemHomeComputer
id;classname;tags
#1;net.torvald.terrarum.modulecomputers.gameitems.ItemWearableWorldRadar;
#2;net.torvald.terrarum.modulecomputers.gameitems.ItemHomeComputer;
256;net.torvald.terrarum.modulecomputers.gameitems.ItemComputerConsole;
257;net.torvald.terrarum.modulecomputers.gameitems.ItemComputerProcessor;
1 id classname tags
2 1 #1 net.torvald.terrarum.modulecomputers.gameitems.ItemWearableWorldRadar
3 2 #2 net.torvald.terrarum.modulecomputers.gameitems.ItemHomeComputer
4 256 net.torvald.terrarum.modulecomputers.gameitems.ItemComputerConsole
5 257 net.torvald.terrarum.modulecomputers.gameitems.ItemComputerProcessor

Binary file not shown.

View File

@@ -4,7 +4,7 @@ author=CuriousTo\uA75Bvald
package=net.torvald.terrarum.modulecomputers
entrypoint=net.torvald.terrarum.modulecomputers.EntryPoint
releasedate=2021-12-03
version=0.3.0
version=0.5.2
jar=ModuleComputers.jar
jarhash=384E6650960E9D044055C5BAFE4C941398B688C3809FA6733B06DDB92A746CFA
dependency=basegame 0.3.0
dependency=basegame 0.5.2

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