mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-09 18:14:06 +09:00
asset archiving wip, font update
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
assets/mods/dwarventech/wires/decayconsts.csv
Normal file
10
assets/mods/dwarventech/wires/decayconsts.csv
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
wireItemID;const
|
||||||
|
wire@dwarventech:1;0.995
|
||||||
|
wire@dwarventech:2;0.995
|
||||||
|
wire@dwarventech:3;0.995
|
||||||
|
wire@dwarventech:4;0.995
|
||||||
|
wire@dwarventech:5;0.995
|
||||||
|
wire@dwarventech:6;0.999
|
||||||
|
wire@dwarventech:7;0.999
|
||||||
|
wire@dwarventech:8;0.999
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@ what:
|
|||||||
|
|
||||||
assets:
|
assets:
|
||||||
./make_assets_release.sh || true
|
./make_assets_release.sh || true
|
||||||
|
./make_assets_archive.sh
|
||||||
|
|
||||||
linux_x86:
|
linux_x86:
|
||||||
./build_app_linux_x86.sh
|
./build_app_linux_x86.sh
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-linux-arm"
|
|||||||
DESKTOPFILE="../out/build_autogen_linux.desktop"
|
DESKTOPFILE="../out/build_autogen_linux.desktop"
|
||||||
JARNAME="TerrarumBuild.jar"
|
JARNAME="TerrarumBuild.jar"
|
||||||
|
|
||||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
if [ ! -f "out/assets.tevd" ]; then
|
||||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -29,9 +29,8 @@ mkdir $DESTDIR/out
|
|||||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||||
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/java
|
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/java
|
||||||
|
|
||||||
# Copy over the asset archive, manifest, and jarfile
|
# Copy over the asset archive and jarfile
|
||||||
cp "out/assets.tar.zst" $DESTDIR/
|
cp "out/assets.tevd" $DESTDIR/
|
||||||
cp "out/assets.manifest" $DESTDIR/
|
|
||||||
cp "../out/$JARNAME" $DESTDIR/out/
|
cp "../out/$JARNAME" $DESTDIR/out/
|
||||||
|
|
||||||
# Pack everything to AppImage
|
# Pack everything to AppImage
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-linux-x86"
|
|||||||
DESKTOPFILE="../out/build_autogen_linux.desktop"
|
DESKTOPFILE="../out/build_autogen_linux.desktop"
|
||||||
JARNAME="TerrarumBuild.jar"
|
JARNAME="TerrarumBuild.jar"
|
||||||
|
|
||||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
if [ ! -f "out/assets.tevd" ]; then
|
||||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -29,9 +29,8 @@ mkdir $DESTDIR/out
|
|||||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||||
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/java
|
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/java
|
||||||
|
|
||||||
# Copy over the asset archive, manifest, and jarfile
|
# Copy over the asset archive and jarfile
|
||||||
cp "out/assets.tar.zst" $DESTDIR/
|
cp "out/assets.tevd" $DESTDIR/
|
||||||
cp "out/assets.manifest" $DESTDIR/
|
|
||||||
cp "../out/$JARNAME" $DESTDIR/out/
|
cp "../out/$JARNAME" $DESTDIR/out/
|
||||||
|
|
||||||
# Pack everything to AppImage
|
# Pack everything to AppImage
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-osx-arm"
|
|||||||
PLISTFILE="../out/build_autogen_macos_Info.plist"
|
PLISTFILE="../out/build_autogen_macos_Info.plist"
|
||||||
JARNAME="TerrarumBuild.jar"
|
JARNAME="TerrarumBuild.jar"
|
||||||
|
|
||||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
if [ ! -f "out/assets.tevd" ]; then
|
||||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -32,9 +32,8 @@ mkdir $DESTDIR/Contents/MacOS/out
|
|||||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
||||||
mv $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java
|
mv $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java
|
||||||
|
|
||||||
# Copy over the asset archive, manifest, and jarfile
|
# Copy over the asset archive and jarfile
|
||||||
cp "out/assets.tar.zst" $DESTDIR/Contents/MacOS/
|
cp "out/assets.tevd" $DESTDIR/Contents/MacOS/
|
||||||
cp "out/assets.manifest" $DESTDIR/Contents/MacOS/
|
|
||||||
cp "../out/$JARNAME" $DESTDIR/Contents/MacOS/out/
|
cp "../out/$JARNAME" $DESTDIR/Contents/MacOS/out/
|
||||||
|
|
||||||
# zip everything
|
# zip everything
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-osx-x86"
|
|||||||
PLISTFILE="../out/build_autogen_macos_Info.plist"
|
PLISTFILE="../out/build_autogen_macos_Info.plist"
|
||||||
JARNAME="TerrarumBuild.jar"
|
JARNAME="TerrarumBuild.jar"
|
||||||
|
|
||||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
if [ ! -f "out/assets.tevd" ]; then
|
||||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -32,9 +32,8 @@ mkdir $DESTDIR/Contents/MacOS/out
|
|||||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
||||||
mv $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java
|
mv $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java
|
||||||
|
|
||||||
# Copy over the asset archive, manifest, and jarfile
|
# Copy over the asset archive and jarfile
|
||||||
cp "out/assets.tar.zst" $DESTDIR/Contents/MacOS/
|
cp "out/assets.tevd" $DESTDIR/Contents/MacOS/
|
||||||
cp "out/assets.manifest" $DESTDIR/Contents/MacOS/
|
|
||||||
cp "../out/$JARNAME" $DESTDIR/Contents/MacOS/out/
|
cp "../out/$JARNAME" $DESTDIR/Contents/MacOS/out/
|
||||||
|
|
||||||
# zip everything
|
# zip everything
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ RUNTIME="runtime-windows-x86"
|
|||||||
RCFILE="../out/build_autogen_windows.rc"
|
RCFILE="../out/build_autogen_windows.rc"
|
||||||
JARNAME="TerrarumBuild.jar"
|
JARNAME="TerrarumBuild.jar"
|
||||||
|
|
||||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
if [ ! -f "out/assets.tevd" ]; then
|
||||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -34,9 +34,8 @@ mkdir $DESTDIR/out
|
|||||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||||
mv $DESTDIR/out/$RUNTIME/bin/java.exe $DESTDIR/out/$RUNTIME/bin/java.exe
|
mv $DESTDIR/out/$RUNTIME/bin/java.exe $DESTDIR/out/$RUNTIME/bin/java.exe
|
||||||
|
|
||||||
# Copy over the asset archive, manifest, and jarfile
|
# Copy over the asset archive and jarfile
|
||||||
cp "out/assets.tar.zst" $DESTDIR/
|
cp "out/assets.tevd" $DESTDIR/
|
||||||
cp "out/assets.manifest" $DESTDIR/
|
|
||||||
cp "../out/$JARNAME" $DESTDIR/out/
|
cp "../out/$JARNAME" $DESTDIR/out/
|
||||||
|
|
||||||
# zip everything
|
# zip everything
|
||||||
|
|||||||
43
buildapp/make_assets_archive.sh
Normal file
43
buildapp/make_assets_archive.sh
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if (( $EUID == 0 )); then echo "The build process is not meant to be run with root privilege, exiting now." >&2; exit 1; fi
|
||||||
|
|
||||||
|
cd "${0%/*}"
|
||||||
|
SRCDIR="../assets_release"
|
||||||
|
OUTDIR="out"
|
||||||
|
JARNAME="TerrarumBuild.jar"
|
||||||
|
TVDJAR="../lib/TerranVirtualDisk.jar"
|
||||||
|
|
||||||
|
if [ ! -d "$SRCDIR" ]; then
|
||||||
|
echo "Error: $SRCDIR does not exist. Run make_assets_release.sh first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "../out/$JARNAME" ]; then
|
||||||
|
echo "Error: ../out/$JARNAME not found. Build the project first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$TVDJAR" ]; then
|
||||||
|
echo "Error: $TVDJAR not found." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
echo "Creating assets.tevd from $SRCDIR..."
|
||||||
|
|
||||||
|
# Build classpath from project JAR and all library JARs
|
||||||
|
CP="../out/$JARNAME"
|
||||||
|
for jar in ../lib/*.jar; do
|
||||||
|
CP="$CP:$jar"
|
||||||
|
done
|
||||||
|
|
||||||
|
java -cp "$CP" net.torvald.terrarum.AssetArchiveBuilderKt "$SRCDIR" "$OUTDIR/assets.tevd"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Error: Failed to create assets.tevd" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Done. Output:"
|
||||||
|
echo " $OUTDIR/assets.tevd ($(du -h "$OUTDIR/assets.tevd" | cut -f1))"
|
||||||
BIN
lib/TerranVirtualDisk-src.jar
LFS
BIN
lib/TerranVirtualDisk-src.jar
LFS
Binary file not shown.
BIN
lib/TerranVirtualDisk.jar
LFS
BIN
lib/TerranVirtualDisk.jar
LFS
Binary file not shown.
BIN
lib/TerrarumSansBitmap.jar
LFS
BIN
lib/TerrarumSansBitmap.jar
LFS
Binary file not shown.
@@ -2017,15 +2017,15 @@ object BTeXParser {
|
|||||||
private lateinit var subtitleFont: TerrarumSansBitmap
|
private lateinit var subtitleFont: TerrarumSansBitmap
|
||||||
|
|
||||||
fun preloadFonts() {
|
fun preloadFonts() {
|
||||||
testFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha, textCacheSize = 4096)
|
testFont = TerrarumSansBitmap(shadowAlpha = bodyTextShadowAlpha, textCacheSize = 4096)
|
||||||
partTitleFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha).also {
|
partTitleFont = TerrarumSansBitmap(shadowAlpha = bodyTextShadowAlpha).also {
|
||||||
it.interchar = 1
|
it.interchar = 1
|
||||||
}
|
}
|
||||||
titleFont = TerrarumSansBitmap(App.FONT_DIR).also {
|
titleFont = TerrarumSansBitmap().also {
|
||||||
it.interchar = 1
|
it.interchar = 1
|
||||||
it.scale = 2
|
it.scale = 2
|
||||||
}
|
}
|
||||||
subtitleFont = TerrarumSansBitmap(App.FONT_DIR).also {
|
subtitleFont = TerrarumSansBitmap().also {
|
||||||
it.interchar = 1
|
it.interchar = 1
|
||||||
}
|
}
|
||||||
fontInit = true
|
fontInit = true
|
||||||
|
|||||||
@@ -255,10 +255,6 @@ public class App implements ApplicationListener {
|
|||||||
public static DebugTimers debugTimers = new DebugTimers();
|
public static DebugTimers debugTimers = new DebugTimers();
|
||||||
|
|
||||||
|
|
||||||
public static final String FONT_DIR = "assets/graphics/fonts/terrarum-sans-bitmap";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static Texture[] ditherPatterns = new Texture[4];
|
public static Texture[] ditherPatterns = new Texture[4];
|
||||||
// public static ShaderProgram shaderHicolour;
|
// public static ShaderProgram shaderHicolour;
|
||||||
public static ShaderProgram shaderDebugDiff;
|
public static ShaderProgram shaderDebugDiff;
|
||||||
@@ -445,6 +441,7 @@ public class App implements ApplicationListener {
|
|||||||
// load configs
|
// load configs
|
||||||
getDefaultDirectory();
|
getDefaultDirectory();
|
||||||
createDirs();
|
createDirs();
|
||||||
|
AssetCache.INSTANCE.init();
|
||||||
initialiseConfig();
|
initialiseConfig();
|
||||||
readConfigJson();
|
readConfigJson();
|
||||||
|
|
||||||
@@ -582,13 +579,13 @@ public class App implements ApplicationListener {
|
|||||||
if (!loadOrder.isEmpty()) {
|
if (!loadOrder.isEmpty()) {
|
||||||
var modname = loadOrder.get(0).get(0);
|
var modname = loadOrder.get(0).get(0);
|
||||||
|
|
||||||
var textureFile = Gdx.files.internal("assets/mods/"+modname+"/splashback.png");
|
var textureFile = AssetCache.INSTANCE.getFileHandle("mods/"+modname+"/splashback.png");
|
||||||
if (textureFile.exists()) {
|
if (textureFile.exists()) {
|
||||||
splashBackdrop = new TextureRegion(new Texture(textureFile));
|
splashBackdrop = new TextureRegion(new Texture(textureFile));
|
||||||
splashTextCol = new Color(0xeeeeeeff);
|
splashTextCol = new Color(0xeeeeeeff);
|
||||||
}
|
}
|
||||||
|
|
||||||
var logoFile = Gdx.files.internal("assets/mods/"+modname+"/splashlogo.png");
|
var logoFile = AssetCache.INSTANCE.getFileHandle("mods/"+modname+"/splashlogo.png");
|
||||||
if (logoFile.exists()) {
|
if (logoFile.exists()) {
|
||||||
splashScreenLogo = new TextureRegion(new Texture(logoFile));
|
splashScreenLogo = new TextureRegion(new Texture(logoFile));
|
||||||
}
|
}
|
||||||
@@ -604,10 +601,10 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (splashBackdrop == null) {
|
if (splashBackdrop == null) {
|
||||||
splashBackdrop = new TextureRegion(new Texture("assets/graphics/background_white.png"));
|
splashBackdrop = new TextureRegion(new Texture(AssetCache.INSTANCE.getFileHandle("graphics/background_white.png")));
|
||||||
}
|
}
|
||||||
if (splashScreenLogo == null) {
|
if (splashScreenLogo == null) {
|
||||||
splashScreenLogo = new TextureRegion(new Texture("assets/graphics/logo.png"));
|
splashScreenLogo = new TextureRegion(new Texture(AssetCache.INSTANCE.getFileHandle("graphics/logo.png")));
|
||||||
}
|
}
|
||||||
|
|
||||||
Gdx.graphics.setContinuousRendering(true);
|
Gdx.graphics.setContinuousRendering(true);
|
||||||
@@ -622,13 +619,13 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
ShaderMgr.INSTANCE.compile(Gdx.files.classpath("shaders/shaders.csv"));
|
ShaderMgr.INSTANCE.compile(Gdx.files.classpath("shaders/shaders.csv"));
|
||||||
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("title_health1", () -> new Texture(Gdx.files.internal("./assets/graphics/gui/health_take_a_break.tga")));
|
CommonResourcePool.INSTANCE.addToLoadingList("title_health1", () -> new Texture(AssetCache.INSTANCE.getFileHandle("graphics/gui/health_take_a_break.tga")));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("title_health2", () -> new Texture(Gdx.files.internal("./assets/graphics/gui/health_distance.tga")));
|
CommonResourcePool.INSTANCE.addToLoadingList("title_health2", () -> new Texture(AssetCache.INSTANCE.getFileHandle("graphics/gui/health_distance.tga")));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bup", () -> new MusicContainer("haptic_bup", Gdx.files.internal("./assets/audio/effects/haptic_bup.ogg").file(), false, true, (AudioBank m) -> { return null; }));
|
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bup", () -> new MusicContainer("haptic_bup", AssetCache.INSTANCE.getFileHandle("audio/effects/haptic_bup.ogg"), false, true, null, (AudioBank m) -> { return null; }));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bap", () -> new MusicContainer("haptic_bap", Gdx.files.internal("./assets/audio/effects/haptic_bap.ogg").file(), false, true, (AudioBank m) -> { return null; }));
|
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bap", () -> new MusicContainer("haptic_bap", AssetCache.INSTANCE.getFileHandle("audio/effects/haptic_bap.ogg"), false, true, null, (AudioBank m) -> { return null; }));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bop", () -> new MusicContainer("haptic_bop", Gdx.files.internal("./assets/audio/effects/haptic_bop.ogg").file(), false, true, (AudioBank m) -> { return null; }));
|
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bop", () -> new MusicContainer("haptic_bop", AssetCache.INSTANCE.getFileHandle("audio/effects/haptic_bop.ogg"), false, true, null, (AudioBank m) -> { return null; }));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bep", () -> new MusicContainer("haptic_bep", Gdx.files.internal("./assets/audio/effects/haptic_bep.ogg").file(), false, true, (AudioBank m) -> { return null; }));
|
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bep", () -> new MusicContainer("haptic_bep", AssetCache.INSTANCE.getFileHandle("audio/effects/haptic_bep.ogg"), false, true, null, (AudioBank m) -> { return null; }));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bip", () -> new MusicContainer("haptic_bip", Gdx.files.internal("./assets/audio/effects/haptic_bip.ogg").file(), false, true, (AudioBank m) -> { highPrioritySoundPlaying = false; return null; }));
|
CommonResourcePool.INSTANCE.addToLoadingList("sound:haptic_bip", () -> new MusicContainer("haptic_bip", AssetCache.INSTANCE.getFileHandle("audio/effects/haptic_bip.ogg"), false, true, null, (AudioBank m) -> { highPrioritySoundPlaying = false; return null; }));
|
||||||
// make loading list
|
// make loading list
|
||||||
CommonResourcePool.INSTANCE.loadAll();
|
CommonResourcePool.INSTANCE.loadAll();
|
||||||
|
|
||||||
@@ -669,7 +666,7 @@ public class App implements ApplicationListener {
|
|||||||
rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
|
rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
|
||||||
|
|
||||||
|
|
||||||
fontGame = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
fontGame = new TerrarumSansBitmap(false, false, false,
|
||||||
false,
|
false,
|
||||||
256, false, 0.5f, false
|
256, false, 0.5f, false
|
||||||
);
|
);
|
||||||
@@ -1062,6 +1059,8 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
deleteTempfiles();
|
deleteTempfiles();
|
||||||
|
|
||||||
|
AssetCache.INSTANCE.dispose();
|
||||||
|
|
||||||
Toolkit.INSTANCE.dispose();
|
Toolkit.INSTANCE.dispose();
|
||||||
BlurMgr.INSTANCE.dispose();
|
BlurMgr.INSTANCE.dispose();
|
||||||
|
|
||||||
@@ -1157,11 +1156,11 @@ public class App implements ApplicationListener {
|
|||||||
long t1 = System.nanoTime();
|
long t1 = System.nanoTime();
|
||||||
|
|
||||||
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("blockmarkings_common", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16, 0, 0, 0, 0, false, false, false));
|
CommonResourcePool.INSTANCE.addToLoadingList("blockmarkings_common", () -> new TextureRegionPack(AssetCache.INSTANCE.getFileHandle("graphics/blocks/block_markings_common.tga"), 16, 16, 0, 0, 0, 0, false, false, false));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("blockmarking_actor", () -> new BlockMarkerActor());
|
CommonResourcePool.INSTANCE.addToLoadingList("blockmarking_actor", () -> new BlockMarkerActor());
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("loading_circle_64", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/loading_circle_64.tga"), 64, 64, 0, 0, 0, 0, false, false, false));
|
CommonResourcePool.INSTANCE.addToLoadingList("loading_circle_64", () -> new TextureRegionPack(AssetCache.INSTANCE.getFileHandle("graphics/gui/loading_circle_64.tga"), 64, 64, 0, 0, 0, 0, false, false, false));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("inline_loading_spinner", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/inline_loading_spinner.tga"), 20, 20, 0, 0, 0, 0, false, false, false));
|
CommonResourcePool.INSTANCE.addToLoadingList("inline_loading_spinner", () -> new TextureRegionPack(AssetCache.INSTANCE.getFileHandle("graphics/gui/inline_loading_spinner.tga"), 20, 20, 0, 0, 0, 0, false, false, false));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("inventory_category", () -> new TextureRegionPack("./assets/graphics/gui/inventory/category.tga", 20, 20, 0, 0, 0, 0, false, false, false));
|
CommonResourcePool.INSTANCE.addToLoadingList("inventory_category", () -> new TextureRegionPack(AssetCache.INSTANCE.getFileHandle("graphics/gui/inventory/category.tga"), 20, 20, 0, 0, 0, 0, false, false, false));
|
||||||
CommonResourcePool.INSTANCE.loadAll();
|
CommonResourcePool.INSTANCE.loadAll();
|
||||||
|
|
||||||
// shaderHicolour = loadShaderFromClasspath("shaders/default.vert", "shaders/hicolour.frag");
|
// shaderHicolour = loadShaderFromClasspath("shaders/default.vert", "shaders/hicolour.frag");
|
||||||
@@ -1226,12 +1225,12 @@ public class App implements ApplicationListener {
|
|||||||
else {
|
else {
|
||||||
environment = RunningEnvironment.PC;
|
environment = RunningEnvironment.PC;
|
||||||
}*/
|
}*/
|
||||||
fontUITitle = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
fontUITitle = new TerrarumSansBitmap(false, false, false,
|
||||||
false,
|
false,
|
||||||
64, false, 0.5f, false
|
64, false, 0.5f, false
|
||||||
);
|
);
|
||||||
fontUITitle.setInterchar(1);
|
fontUITitle.setInterchar(1);
|
||||||
fontGameFBO = new TerrarumSansBitmap(FONT_DIR, false, true, false,
|
fontGameFBO = new TerrarumSansBitmap(false, true, false,
|
||||||
false,
|
false,
|
||||||
64, false, 203f/255f, false
|
64, false, 203f/255f, false
|
||||||
);
|
);
|
||||||
@@ -1514,6 +1513,8 @@ public class App implements ApplicationListener {
|
|||||||
/** defaultDir + "/Custom/Music" */
|
/** defaultDir + "/Custom/Music" */
|
||||||
public static String customMusicDir;
|
public static String customMusicDir;
|
||||||
public static String customAmbientDir;
|
public static String customAmbientDir;
|
||||||
|
/** defaultDir + "/Caches" */
|
||||||
|
public static String cachesDir;
|
||||||
|
|
||||||
private static void getDefaultDirectory() {
|
private static void getDefaultDirectory() {
|
||||||
String OS = OSName.toUpperCase();
|
String OS = OSName.toUpperCase();
|
||||||
@@ -1551,6 +1552,7 @@ public class App implements ApplicationListener {
|
|||||||
customDir = defaultDir + "/Custom";
|
customDir = defaultDir + "/Custom";
|
||||||
customMusicDir = customDir + "/Music";
|
customMusicDir = customDir + "/Music";
|
||||||
customAmbientDir = customDir + "/Ambient";
|
customAmbientDir = customDir + "/Ambient";
|
||||||
|
cachesDir = defaultDir + "/Caches";
|
||||||
|
|
||||||
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
||||||
System.out.println(String.format("os.version = %s", OSVersion));
|
System.out.println(String.format("os.version = %s", OSVersion));
|
||||||
|
|||||||
59
src/net/torvald/terrarum/AssetArchiveBuilder.kt
Normal file
59
src/net/torvald/terrarum/AssetArchiveBuilder.kt
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustfile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build-time tool that creates assets.tevd from assets_release/ directory.
|
||||||
|
*
|
||||||
|
* Usage: java -cp <classpath> net.torvald.terrarum.AssetArchiveBuilderKt [assets_release_dir] [output_file]
|
||||||
|
*/
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val srcDir = File(if (args.isNotEmpty()) args[0] else "assets_release")
|
||||||
|
val outFile = File(if (args.size > 1) args[1] else "out/assets.tevd")
|
||||||
|
|
||||||
|
if (!srcDir.exists() || !srcDir.isDirectory) {
|
||||||
|
System.err.println("Error: Source directory '${srcDir.path}' does not exist or is not a directory.")
|
||||||
|
System.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile.parentFile?.mkdirs()
|
||||||
|
if (outFile.exists()) outFile.delete()
|
||||||
|
|
||||||
|
println("Scanning $srcDir...")
|
||||||
|
var totalSize = 0L
|
||||||
|
var fileCount = 0
|
||||||
|
srcDir.walkTopDown().filter { it.isFile }.forEach {
|
||||||
|
totalSize += it.length()
|
||||||
|
fileCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate capacity in sectors (4096 bytes per sector/cluster)
|
||||||
|
// Add overhead for FAT entries and directory structures
|
||||||
|
val clusterSize = ClusteredFormatDOM.CLUSTER_SIZE
|
||||||
|
val sectorsForData = (totalSize + clusterSize - 1) / clusterSize
|
||||||
|
// Add ~25% overhead for FAT, directory entries, and slack space
|
||||||
|
val capacityInSectors = ((sectorsForData * 1.25) + fileCount + 256).toLong()
|
||||||
|
.coerceAtMost(ClusteredFormatDOM.MAX_CAPA_IN_SECTORS.toLong())
|
||||||
|
.toInt()
|
||||||
|
|
||||||
|
println(" Files: $fileCount")
|
||||||
|
println(" Total size: ${totalSize / 1024} KB")
|
||||||
|
println(" Allocating $capacityInSectors sectors...")
|
||||||
|
|
||||||
|
println("Creating archive: ${outFile.path}")
|
||||||
|
val diskArchive = ClusteredFormatDOM.createNewArchive(outFile, Charsets.UTF_8, "Terrarum Assets", capacityInSectors)
|
||||||
|
val dom = ClusteredFormatDOM(diskArchive)
|
||||||
|
|
||||||
|
println("Importing files from ${srcDir.path}...")
|
||||||
|
val root = Clustfile(dom, "/")
|
||||||
|
root.importFrom(srcDir)
|
||||||
|
|
||||||
|
println("Trimming archive...")
|
||||||
|
dom.trimArchive()
|
||||||
|
dom.dispose()
|
||||||
|
|
||||||
|
println("Done. Output:")
|
||||||
|
println(" ${outFile.path} (${outFile.length() / 1024} KB, $fileCount files)")
|
||||||
|
}
|
||||||
68
src/net/torvald/terrarum/AssetCache.kt
Normal file
68
src/net/torvald/terrarum/AssetCache.kt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustfile
|
||||||
|
import java.io.File
|
||||||
|
import java.io.RandomAccessFile
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Central accessor for the TerranVirtualDisk asset archive.
|
||||||
|
* In distribution mode, assets are read directly from assets.tevd.
|
||||||
|
* In development mode, assets are read from the local ./assets/ directory.
|
||||||
|
*/
|
||||||
|
object AssetCache {
|
||||||
|
|
||||||
|
private val archivePath = File("./assets.tevd")
|
||||||
|
|
||||||
|
/** Whether we're running from a distribution archive */
|
||||||
|
val isDistribution: Boolean get() = archivePath.exists()
|
||||||
|
|
||||||
|
private var dom: ClusteredFormatDOM? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the archive on startup. Call early, after defaultDir is set.
|
||||||
|
*/
|
||||||
|
fun init() {
|
||||||
|
if (isDistribution) {
|
||||||
|
println("[AssetCache] Distribution mode: opening ${archivePath.path}")
|
||||||
|
dom = ClusteredFormatDOM(RandomAccessFile(archivePath, "r"))
|
||||||
|
println("[AssetCache] Archive opened successfully")
|
||||||
|
} else {
|
||||||
|
println("[AssetCache] No archive found, using loose assets (development mode)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a Clustfile for a path relative to the assets root.
|
||||||
|
*/
|
||||||
|
fun getClustfile(relativePath: String): Clustfile {
|
||||||
|
val path = if (relativePath.startsWith("/")) relativePath else "/$relativePath"
|
||||||
|
return Clustfile(dom!!, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a GDX FileHandle — returns ClustfileHandle in distribution, Gdx.files.internal in dev.
|
||||||
|
*/
|
||||||
|
fun getFileHandle(relativePath: String): FileHandle {
|
||||||
|
return if (isDistribution) ClustfileHandle(getClustfile(relativePath))
|
||||||
|
else Gdx.files.internal("./assets/$relativePath")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a path string. In dev mode returns local path; in distribution mode throws
|
||||||
|
* as callers should use getFileHandle() instead.
|
||||||
|
*/
|
||||||
|
fun resolve(relativePath: String): String {
|
||||||
|
return if (isDistribution) throw UnsupportedOperationException(
|
||||||
|
"Use AssetCache.getFileHandle(\"$relativePath\") in distribution mode"
|
||||||
|
)
|
||||||
|
else "./assets/$relativePath"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
dom?.dispose()
|
||||||
|
dom = null
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/net/torvald/terrarum/ClustfileHandle.kt
Normal file
64
src/net/torvald/terrarum/ClustfileHandle.kt
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustfile
|
||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClustfileInputStream
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GDX FileHandle backed by a Clustfile from TerranVirtualDisk.
|
||||||
|
* Allows transparent asset loading from .tevd archives using all standard GDX APIs.
|
||||||
|
*/
|
||||||
|
class ClustfileHandle(private val clustfile: Clustfile) : FileHandle() {
|
||||||
|
|
||||||
|
override fun read(): InputStream = ClustfileInputStream(clustfile)
|
||||||
|
|
||||||
|
override fun readBytes(): ByteArray = clustfile.readBytes()
|
||||||
|
|
||||||
|
override fun readString(charset: String?): String = String(readBytes(), charset(charset ?: "UTF-8"))
|
||||||
|
|
||||||
|
override fun exists(): Boolean = clustfile.exists()
|
||||||
|
|
||||||
|
override fun length(): Long = clustfile.length()
|
||||||
|
|
||||||
|
override fun isDirectory(): Boolean = clustfile.isDirectory
|
||||||
|
|
||||||
|
override fun name(): String = clustfile.name
|
||||||
|
|
||||||
|
override fun path(): String = clustfile.path
|
||||||
|
|
||||||
|
override fun extension(): String {
|
||||||
|
val n = name()
|
||||||
|
val dotIndex = n.lastIndexOf('.')
|
||||||
|
return if (dotIndex == -1) "" else n.substring(dotIndex + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun nameWithoutExtension(): String {
|
||||||
|
val n = name()
|
||||||
|
val dotIndex = n.lastIndexOf('.')
|
||||||
|
return if (dotIndex == -1) n else n.substring(0, dotIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun list(): Array<FileHandle> {
|
||||||
|
return clustfile.listFiles()?.map { ClustfileHandle(it) }?.toTypedArray() ?: arrayOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun child(name: String): FileHandle {
|
||||||
|
val childPath = if (clustfile.path.endsWith("/")) "${clustfile.path}$name" else "${clustfile.path}/$name"
|
||||||
|
return ClustfileHandle(Clustfile(clustfile.DOM, childPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parent(): FileHandle {
|
||||||
|
val parentFile = clustfile.parentFile
|
||||||
|
return if (parentFile != null) ClustfileHandle(parentFile)
|
||||||
|
else ClustfileHandle(Clustfile(clustfile.DOM, "/"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun file(): File {
|
||||||
|
// Return a dummy File for logging/toString purposes only
|
||||||
|
return File(clustfile.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = clustfile.path
|
||||||
|
}
|
||||||
@@ -103,7 +103,7 @@ object ModMgr {
|
|||||||
NOT_EVEN_THERE
|
NOT_EVEN_THERE
|
||||||
}
|
}
|
||||||
|
|
||||||
const val modDirInternal = "./assets/mods"
|
val modDirInternal: String get() = "./assets/mods"
|
||||||
val modDirExternal = "${App.defaultDir}/Modules"
|
val modDirExternal = "${App.defaultDir}/Modules"
|
||||||
|
|
||||||
/** Module name (directory name), ModuleMetadata */
|
/** Module name (directory name), ModuleMetadata */
|
||||||
@@ -161,21 +161,46 @@ object ModMgr {
|
|||||||
try {
|
try {
|
||||||
val modMetadata = Properties()
|
val modMetadata = Properties()
|
||||||
|
|
||||||
val _internalFile = File("$modDirInternal/$moduleName/$metaFilename")
|
|
||||||
val _externalFile = File("$modDirExternal/$moduleName/$metaFilename")
|
val _externalFile = File("$modDirExternal/$moduleName/$metaFilename")
|
||||||
|
|
||||||
// external mod has precedence over the internal
|
// external mod has precedence over the internal
|
||||||
val isInternal = if (_externalFile.exists()) false else if (_internalFile.exists()) true else throw FileNotFoundException()
|
val internalExists = if (AssetCache.isDistribution)
|
||||||
val file = if (isInternal) _internalFile else _externalFile
|
AssetCache.getFileHandle("mods/$moduleName/$metaFilename").exists()
|
||||||
|
else
|
||||||
|
File("$modDirInternal/$moduleName/$metaFilename").exists()
|
||||||
|
val isInternal = if (_externalFile.exists()) false else if (internalExists) true else throw FileNotFoundException()
|
||||||
val modDir = if (isInternal) modDirInternal else modDirExternal
|
val modDir = if (isInternal) modDirInternal else modDirExternal
|
||||||
|
|
||||||
fun getGdxFile(path: String) = if (isInternal) Gdx.files.internal(path) else Gdx.files.absolute(path)
|
fun getGdxFileLocal(path: String) = if (isInternal) {
|
||||||
|
if (AssetCache.isDistribution) AssetCache.getFileHandle(path.removePrefix("./assets/"))
|
||||||
|
else Gdx.files.internal(path)
|
||||||
|
} else Gdx.files.absolute(path)
|
||||||
|
|
||||||
modMetadata.load(FileInputStream(file))
|
// Load metadata
|
||||||
|
if (isInternal && AssetCache.isDistribution) {
|
||||||
|
val metaHandle = AssetCache.getFileHandle("mods/$moduleName/$metaFilename")
|
||||||
|
modMetadata.load(metaHandle.read())
|
||||||
|
} else {
|
||||||
|
val file = if (isInternal) File("$modDirInternal/$moduleName/$metaFilename") else _externalFile
|
||||||
|
modMetadata.load(FileInputStream(file))
|
||||||
|
}
|
||||||
|
|
||||||
if (File("$modDir/$moduleName/$defaultConfigFilename").exists()) {
|
// Load default config
|
||||||
|
val defaultConfigHandle = if (isInternal && AssetCache.isDistribution)
|
||||||
|
AssetCache.getFileHandle("mods/$moduleName/$defaultConfigFilename")
|
||||||
|
else
|
||||||
|
null
|
||||||
|
val defaultConfigExists = if (defaultConfigHandle != null)
|
||||||
|
defaultConfigHandle.exists()
|
||||||
|
else
|
||||||
|
File("$modDir/$moduleName/$defaultConfigFilename").exists()
|
||||||
|
|
||||||
|
if (defaultConfigExists) {
|
||||||
try {
|
try {
|
||||||
val defaultConfig = JsonFetcher("$modDir/$moduleName/$defaultConfigFilename")
|
val defaultConfig = if (defaultConfigHandle != null)
|
||||||
|
JsonFetcher.invoke(defaultConfigHandle)
|
||||||
|
else
|
||||||
|
JsonFetcher("$modDir/$moduleName/$defaultConfigFilename")
|
||||||
|
|
||||||
// read config and store it to the game
|
// read config and store it to the game
|
||||||
var entry: JsonValue? = defaultConfig.child
|
var entry: JsonValue? = defaultConfig.child
|
||||||
@@ -208,16 +233,29 @@ object ModMgr {
|
|||||||
val jar = modMetadata.getProperty("jar")
|
val jar = modMetadata.getProperty("jar")
|
||||||
val jarHash = modMetadata.getProperty("jarhash").uppercase()
|
val jarHash = modMetadata.getProperty("jarhash").uppercase()
|
||||||
val dependency = modMetadata.getProperty("dependency").split(Regex(""";[ ]*""")).filter { it.isNotEmpty() }.toTypedArray()
|
val dependency = modMetadata.getProperty("dependency").split(Regex(""";[ ]*""")).filter { it.isNotEmpty() }.toTypedArray()
|
||||||
val isDir = FileSystems.getDefault().getPath("$modDir/$moduleName").toFile().isDirectory
|
val isDir = if (isInternal && AssetCache.isDistribution)
|
||||||
|
true // internal mods in archive are always "directories"
|
||||||
|
else
|
||||||
|
FileSystems.getDefault().getPath("$modDir/$moduleName").toFile().isDirectory
|
||||||
|
|
||||||
val configPlan = ArrayList<String>()
|
val configPlan = ArrayList<String>()
|
||||||
File("$modDir/$moduleName/configplan.csv").let {
|
val configPlanHandle = if (isInternal && AssetCache.isDistribution)
|
||||||
if (it.exists() && it.isFile) {
|
AssetCache.getFileHandle("mods/$moduleName/configplan.csv")
|
||||||
configPlan.addAll(it.readLines(Common.CHARSET).filter { it.isNotBlank() })
|
else
|
||||||
|
null
|
||||||
|
if (configPlanHandle != null) {
|
||||||
|
if (configPlanHandle.exists()) {
|
||||||
|
configPlan.addAll(configPlanHandle.readString("UTF-8").lines().filter { it.isNotBlank() })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
File("$modDir/$moduleName/configplan.csv").let {
|
||||||
|
if (it.exists() && it.isFile) {
|
||||||
|
configPlan.addAll(it.readLines(Common.CHARSET).filter { it.isNotBlank() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module = ModuleMetadata(index, isDir, getGdxFile("$modDir/$moduleName/icon.png"), properName, description, descTranslations, author, packageName, entryPoint, releaseDate, version, jar, dependency, isInternal, configPlan)
|
module = ModuleMetadata(index, isDir, getGdxFileLocal("$modDir/$moduleName/icon.png"), properName, description, descTranslations, author, packageName, entryPoint, releaseDate, version, jar, dependency, isInternal, configPlan)
|
||||||
|
|
||||||
val versionNumeral = version.split('.')
|
val versionNumeral = version.split('.')
|
||||||
val versionNumber = versionNumeral.toVersionNumber()
|
val versionNumber = versionNumeral.toVersionNumber()
|
||||||
@@ -447,24 +485,36 @@ object ModMgr {
|
|||||||
/** Returning files are read-only */
|
/** Returning files are read-only */
|
||||||
fun getGdxFile(module: String, path: String): FileHandle {
|
fun getGdxFile(module: String, path: String): FileHandle {
|
||||||
checkExistence(module)
|
checkExistence(module)
|
||||||
return if (moduleInfo[module]!!.isInternal)
|
return if (moduleInfo[module]!!.isInternal) {
|
||||||
Gdx.files.internal("$modDirInternal/$module/$path")
|
if (AssetCache.isDistribution)
|
||||||
|
ClustfileHandle(AssetCache.getClustfile("mods/$module/$path"))
|
||||||
|
else
|
||||||
|
Gdx.files.internal("$modDirInternal/$module/$path")
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Gdx.files.absolute("$modDirExternal/$module/$path")
|
Gdx.files.absolute("$modDirExternal/$module/$path")
|
||||||
}
|
}
|
||||||
fun getFile(module: String, path: String): File {
|
// getGdxFile is preferred due to asset archiving
|
||||||
|
/*fun getFile(module: String, path: String): File {
|
||||||
checkExistence(module)
|
checkExistence(module)
|
||||||
return if (moduleInfo[module]!!.isInternal)
|
return if (moduleInfo[module]!!.isInternal) {
|
||||||
FileSystems.getDefault().getPath("$modDirInternal/$module/$path").toFile()
|
if (AssetCache.isDistribution)
|
||||||
|
throw UnsupportedOperationException("Use getGdxFile() for internal mod files in distribution mode (module=$module, path=$path)")
|
||||||
|
else
|
||||||
|
FileSystems.getDefault().getPath("$modDirInternal/$module/$path").toFile()
|
||||||
|
}
|
||||||
else
|
else
|
||||||
FileSystems.getDefault().getPath("$modDirExternal/$module/$path").toFile()
|
FileSystems.getDefault().getPath("$modDirExternal/$module/$path").toFile()
|
||||||
}
|
}*/
|
||||||
fun hasFile(module: String, path: String): Boolean {
|
fun hasFile(module: String, path: String): Boolean {
|
||||||
if (!moduleInfo.containsKey(module)) return false
|
if (!moduleInfo.containsKey(module)) return false
|
||||||
return getFile(module, path).exists()
|
return getGdxFile(module, path).exists()
|
||||||
}
|
}
|
||||||
fun getFiles(module: String, path: String): Array<File> {
|
// getGdxFile is preferred due to asset archiving
|
||||||
|
/*fun getFiles(module: String, path: String): Array<File> {
|
||||||
checkExistence(module)
|
checkExistence(module)
|
||||||
|
if (moduleInfo[module]!!.isInternal && AssetCache.isDistribution)
|
||||||
|
throw UnsupportedOperationException("Use getGdxFiles() for internal mod files in distribution mode (module=$module, path=$path)")
|
||||||
val dir = getFile(module, path)
|
val dir = getFile(module, path)
|
||||||
if (!dir.isDirectory) {
|
if (!dir.isDirectory) {
|
||||||
throw FileNotFoundException("The path is not a directory")
|
throw FileNotFoundException("The path is not a directory")
|
||||||
@@ -472,7 +522,7 @@ object ModMgr {
|
|||||||
else {
|
else {
|
||||||
return dir.listFiles()
|
return dir.listFiles()
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
fun getGdxFiles(module: String, path: String): Array<FileHandle> {
|
fun getGdxFiles(module: String, path: String): Array<FileHandle> {
|
||||||
checkExistence(module)
|
checkExistence(module)
|
||||||
val dir = getGdxFile(module, path)
|
val dir = getGdxFile(module, path)
|
||||||
@@ -487,20 +537,21 @@ object ModMgr {
|
|||||||
/** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not
|
/** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not
|
||||||
* contain the file, the mod will be skipped.
|
* contain the file, the mod will be skipped.
|
||||||
*
|
*
|
||||||
* @return List of pairs<modname, file>
|
* @return List of pairs<modname, filehandle>
|
||||||
*/
|
*/
|
||||||
fun getFilesFromEveryMod(path: String): List<Pair<String, File>> {
|
// getGdxFile is preferred due to asset archiving
|
||||||
|
/*fun getFilesFromEveryMod(path: String): List<Pair<String, FileHandle>> {
|
||||||
val path = path.sanitisePath()
|
val path = path.sanitisePath()
|
||||||
val moduleNames = moduleInfo.keys.toList()
|
val moduleNames = moduleInfo.keys.toList()
|
||||||
|
|
||||||
val filesList = ArrayList<Pair<String, File>>()
|
val filesList = ArrayList<Pair<String, FileHandle>>()
|
||||||
moduleNames.forEach {
|
moduleNames.forEach {
|
||||||
val file = getFile(it, path)
|
val file = getGdxFile(it, path)
|
||||||
if (file.exists()) filesList.add(it to file)
|
if (file.exists()) filesList.add(it to file)
|
||||||
}
|
}
|
||||||
|
|
||||||
return filesList.toList()
|
return filesList.toList()
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not
|
/** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not
|
||||||
* contain the file, the mod will be skipped.
|
* contain the file, the mod will be skipped.
|
||||||
@@ -739,7 +790,7 @@ object ModMgr {
|
|||||||
const val langPath = "locales/"
|
const val langPath = "locales/"
|
||||||
|
|
||||||
@JvmStatic operator fun invoke(module: String) {
|
@JvmStatic operator fun invoke(module: String) {
|
||||||
Lang.load(getFile(module, langPath))
|
Lang.load(getGdxFile(module, langPath))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,25 +798,25 @@ object ModMgr {
|
|||||||
const val keebPath = "keylayout/"
|
const val keebPath = "keylayout/"
|
||||||
|
|
||||||
@JvmStatic operator fun invoke(module: String) {
|
@JvmStatic operator fun invoke(module: String) {
|
||||||
val FILE = getFile(module, keebPath)
|
val DIR = getGdxFile(module, keebPath)
|
||||||
|
|
||||||
FILE.listFiles { file, s -> s.endsWith(".${IME.KEYLAYOUT_EXTENSION}") }.sortedBy { it.name }.forEach {
|
DIR.list().filter { it.extension().equals(IME.KEYLAYOUT_EXTENSION, ignoreCase = true) }.sortedBy { it.name() }.forEach {
|
||||||
printdbg(this, "Registering Low layer ${it.nameWithoutExtension.lowercase()}")
|
printdbg(this, "Registering Low layer ${it.nameWithoutExtension().lowercase()}")
|
||||||
IME.registerLowLayer(it.nameWithoutExtension.lowercase(), IME.parseKeylayoutFile(it))
|
IME.registerLowLayer(it.nameWithoutExtension().lowercase(), IME.parseKeylayoutFile(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE.listFiles { file, s -> s.endsWith(".${IME.IME_EXTENSION}") }.sortedBy { it.name }.forEach {
|
DIR.list().filter { it.extension().equals(IME.IME_EXTENSION, ignoreCase = true) }.sortedBy { it.name() }.forEach {
|
||||||
printdbg(this, "Registering High layer ${it.nameWithoutExtension.lowercase()}")
|
printdbg(this, "Registering High layer ${it.nameWithoutExtension().lowercase()}")
|
||||||
IME.registerHighLayer(it.nameWithoutExtension.lowercase(), IME.parseImeFile(it))
|
IME.registerHighLayer(it.nameWithoutExtension().lowercase(), IME.parseImeFile(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
val iconFile = getFile(module, keebPath + "icons.tga").let {
|
val iconFile = getGdxFile(module, keebPath + "icons.tga").let {
|
||||||
if (it.exists()) it else getFile(module, keebPath + "icons.png")
|
if (it.exists()) it else getGdxFile(module, keebPath + "icons.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iconFile.exists()) {
|
if (iconFile.exists()) {
|
||||||
val iconSheet = TextureRegionPack(iconFile.path, 20, 20)
|
val iconSheet = TextureRegionPack(iconFile, 20, 20)
|
||||||
val iconPixmap = Pixmap(Gdx.files.absolute(iconFile.path))
|
val iconPixmap = Pixmap(iconFile)
|
||||||
for (k in 0 until iconPixmap.height step 20) {
|
for (k in 0 until iconPixmap.height step 20) {
|
||||||
val langCode = StringBuilder()
|
val langCode = StringBuilder()
|
||||||
for (c in 0 until 20) {
|
for (c in 0 until 20) {
|
||||||
@@ -855,7 +906,7 @@ object ModMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic operator fun invoke(module: String) {
|
@JvmStatic operator fun invoke(module: String) {
|
||||||
getFiles(module, weatherPath).filter { it.isFile && it.name.lowercase().endsWith(".json") }.forEach {
|
getGdxFile(module, weatherPath).list().filter { !it.isDirectory && it.name().lowercase().endsWith(".json") }.forEach {
|
||||||
Terrarum.weatherCodex.readFromJson(module, it)
|
Terrarum.weatherCodex.readFromJson(module, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -878,32 +929,21 @@ object ModMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic operator fun invoke(module: String) {
|
@JvmStatic operator fun invoke(module: String) {
|
||||||
val targetModNames = getFiles(module, retexturesPath).filter { it.isDirectory }
|
val targetModNames = getGdxFile(module, retexturesPath).list().filter { it.isDirectory }
|
||||||
targetModNames.forEach { baseTargetModDir ->
|
targetModNames.forEach { baseTargetModDir ->
|
||||||
// modules/<module>/retextures/basegame
|
|
||||||
// printdbg(this, "baseTargetModDir = $baseTargetModDir")
|
|
||||||
|
|
||||||
retexables.forEach { category ->
|
retexables.forEach { category ->
|
||||||
val dir = File(baseTargetModDir, category)
|
val dir = baseTargetModDir.child(category)
|
||||||
// modules/<module>/retextures/basegame/blocks
|
|
||||||
|
|
||||||
// printdbg(this, "cats: ${dir.path}")
|
|
||||||
|
|
||||||
if (dir.isDirectory && dir.exists()) {
|
if (dir.isDirectory && dir.exists()) {
|
||||||
dir.listFiles { it: File ->
|
dir.list().filter { it.name().contains('-') }.forEach {
|
||||||
it.name.contains('-')
|
val tokens = it.name().split('-')
|
||||||
}?.forEach {
|
|
||||||
// <other modname>-<hopefully a number>.tga or .png
|
|
||||||
val tokens = it.name.split('-')
|
|
||||||
if (tokens.size > 1) {
|
if (tokens.size > 1) {
|
||||||
val modname = tokens[0]
|
val modname = tokens[0]
|
||||||
val filename = tokens.tail().joinToString("-")
|
val filename = tokens.tail().joinToString("-")
|
||||||
altFilePaths["$modDirInternal/$modname/$category/$filename"] = getGdxFile(module, "$retexturesPath${baseTargetModDir.name}/$category/${it.name}")
|
altFilePaths["$modDirInternal/$modname/$category/$filename"] = getGdxFile(module, "$retexturesPath${baseTargetModDir.name()}/$category/${it.name()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// retexableCallbacks[category]?.invoke()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -917,12 +957,12 @@ object ModMgr {
|
|||||||
const val smeltingPath = "smelting/"
|
const val smeltingPath = "smelting/"
|
||||||
|
|
||||||
@JvmStatic operator fun invoke(module: String) {
|
@JvmStatic operator fun invoke(module: String) {
|
||||||
getFile(module, recipePath).listFiles { it: File -> it.name.lowercase().endsWith(".json") }?.forEach { jsonFile ->
|
getGdxFile(module, recipePath).list().filter { !it.isDirectory && it.name().lowercase().endsWith(".json") }.forEach { jsonHandle ->
|
||||||
Terrarum.craftingCodex.addFromJson(JsonFetcher(jsonFile), module, jsonFile.name)
|
Terrarum.craftingCodex.addFromJson(JsonFetcher.invoke(jsonHandle), module, jsonHandle.name())
|
||||||
}
|
}
|
||||||
|
|
||||||
getFile(module, smeltingPath).listFiles { it: File -> it.name.lowercase().endsWith(".json") }?.forEach { jsonFile ->
|
getGdxFile(module, smeltingPath).list().filter { !it.isDirectory && it.name().lowercase().endsWith(".json") }.forEach { jsonHandle ->
|
||||||
Terrarum.craftingCodex.addSmeltingFromJson(JsonFetcher(jsonFile), module, jsonFile.name)
|
Terrarum.craftingCodex.addSmeltingFromJson(JsonFetcher.invoke(jsonHandle), module, jsonHandle.name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package net.torvald.terrarum.audio
|
package net.torvald.terrarum.audio
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.reflection.forceInvoke
|
import net.torvald.reflection.forceInvoke
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.CommonResourcePool
|
import net.torvald.terrarum.CommonResourcePool
|
||||||
import net.torvald.terrarum.ModMgr
|
import net.torvald.terrarum.ModMgr
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2024-01-24.
|
* Created by minjaesong on 2024-01-24.
|
||||||
@@ -26,7 +26,7 @@ object AudioHelper {
|
|||||||
return fft
|
return fft
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val ir = ModMgr.getFile(module, path)
|
val ir = ModMgr.getGdxFile(module, path)
|
||||||
val fft = createIR(ir)
|
val fft = createIR(ir)
|
||||||
|
|
||||||
CommonResourcePool.addToLoadingList(id) { fft }
|
CommonResourcePool.addToLoadingList(id) { fft }
|
||||||
@@ -36,19 +36,20 @@ object AudioHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createIR(ir: File): Array<ComplexArray> {
|
private fun createIR(ir: FileHandle): Array<ComplexArray> {
|
||||||
if (!ir.exists()) {
|
if (!ir.exists()) {
|
||||||
throw IllegalArgumentException("Impulse Response file '${ir.path}' does not exist.")
|
throw IllegalArgumentException("Impulse Response file '${ir.path()}' does not exist.")
|
||||||
}
|
}
|
||||||
|
|
||||||
val sampleCount = (ir.length().toInt() / 8)//.coerceAtMost(65536)
|
val irBytes = ir.readBytes()
|
||||||
|
val sampleCount = (irBytes.size / 8)//.coerceAtMost(65536)
|
||||||
val fftLen = FastMath.nextPowerOfTwo(sampleCount)
|
val fftLen = FastMath.nextPowerOfTwo(sampleCount)
|
||||||
|
|
||||||
printdbg(this, "IR '${ir.path}' Sample Count = $sampleCount; FFT Length = $fftLen")
|
printdbg(this, "IR '${ir.path()}' Sample Count = $sampleCount; FFT Length = $fftLen")
|
||||||
|
|
||||||
val conv = Array(2) { FloatArray(fftLen) }
|
val conv = Array(2) { FloatArray(fftLen) }
|
||||||
|
|
||||||
ir.inputStream().let {
|
java.io.ByteArrayInputStream(irBytes).let {
|
||||||
for (i in 0 until sampleCount) {
|
for (i in 0 until sampleCount) {
|
||||||
val f1 = Float.fromBits(it.read().and(255) or
|
val f1 = Float.fromBits(it.read().and(255) or
|
||||||
it.read().and(255).shl(8) or
|
it.read().and(255).shl(8) or
|
||||||
@@ -79,7 +80,7 @@ object AudioHelper {
|
|||||||
return CommonResourcePool.getAs<Array<FloatArray>>(id)
|
return CommonResourcePool.getAs<Array<FloatArray>>(id)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val file = ModMgr.getFile(module, path)
|
val file = ModMgr.getGdxFile(module, path)
|
||||||
val samples = createAudioInSamples(file)
|
val samples = createAudioInSamples(file)
|
||||||
|
|
||||||
CommonResourcePool.addToLoadingList(id) { samples }
|
CommonResourcePool.addToLoadingList(id) { samples }
|
||||||
@@ -89,8 +90,8 @@ object AudioHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createAudioInSamples(static: File): Array<FloatArray> {
|
private fun createAudioInSamples(static: FileHandle): Array<FloatArray> {
|
||||||
val music = Gdx.audio.newMusic(Gdx.files.absolute(static.absolutePath))
|
val music = Gdx.audio.newMusic(static)
|
||||||
val readbuf = ByteArray(AudioProcessBuf.MP3_CHUNK_SIZE * 4)
|
val readbuf = ByteArray(AudioProcessBuf.MP3_CHUNK_SIZE * 4)
|
||||||
val OUTBUF_BLOCK_SIZE_IN_BYTES = (48000 * 60) * 2 * 2
|
val OUTBUF_BLOCK_SIZE_IN_BYTES = (48000 * 60) * 2 * 2
|
||||||
var outbuf = ByteArray(OUTBUF_BLOCK_SIZE_IN_BYTES)
|
var outbuf = ByteArray(OUTBUF_BLOCK_SIZE_IN_BYTES)
|
||||||
|
|||||||
@@ -18,13 +18,15 @@ import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RAT
|
|||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
import net.torvald.unsafe.UnsafePtr
|
import net.torvald.unsafe.UnsafePtr
|
||||||
|
import java.io.BufferedInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import javax.sound.sampled.AudioSystem
|
import javax.sound.sampled.AudioSystem
|
||||||
|
|
||||||
class MusicContainer(
|
class MusicContainer(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
val file: File,
|
val file: File?,
|
||||||
|
val fileHandle: FileHandle?,
|
||||||
val looping: Boolean = false,
|
val looping: Boolean = false,
|
||||||
val toRAM: Boolean = false,
|
val toRAM: Boolean = false,
|
||||||
val samplingRateOverride: Float?, // this is FIXED sampling rate
|
val samplingRateOverride: Float?, // this is FIXED sampling rate
|
||||||
@@ -34,6 +36,15 @@ class MusicContainer(
|
|||||||
override var channels: Int
|
override var channels: Int
|
||||||
val codec: String
|
val codec: String
|
||||||
|
|
||||||
|
// File-based constructors (existing API)
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
file: File,
|
||||||
|
looping: Boolean = false,
|
||||||
|
toRAM: Boolean = false,
|
||||||
|
samplingRateOverride: Float?,
|
||||||
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
|
) : this(name, file, null, looping, toRAM, samplingRateOverride, songFinishedHook)
|
||||||
// make Java code shorter
|
// make Java code shorter
|
||||||
constructor(
|
constructor(
|
||||||
name: String,
|
name: String,
|
||||||
@@ -41,27 +52,37 @@ class MusicContainer(
|
|||||||
looping: Boolean = false,
|
looping: Boolean = false,
|
||||||
toRAM: Boolean = false,
|
toRAM: Boolean = false,
|
||||||
songFinishedHook: (AudioBank) -> Unit = {}
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
) : this(name, file, looping, toRAM, null, songFinishedHook)
|
) : this(name, file, null, looping, toRAM, null, songFinishedHook)
|
||||||
// make Java code shorter
|
// make Java code shorter
|
||||||
constructor(
|
constructor(
|
||||||
name: String,
|
name: String,
|
||||||
file: File,
|
file: File,
|
||||||
looping: Boolean = false,
|
looping: Boolean = false,
|
||||||
songFinishedHook: (AudioBank) -> Unit = {}
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
) : this(name, file, looping, false, null, songFinishedHook)
|
) : this(name, file, null, looping, false, null, songFinishedHook)
|
||||||
// make Java code shorter
|
// make Java code shorter
|
||||||
constructor(
|
constructor(
|
||||||
name: String,
|
name: String,
|
||||||
file: File,
|
file: File,
|
||||||
songFinishedHook: (AudioBank) -> Unit = {}
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
) : this(name, file, false, false, null, songFinishedHook)
|
) : this(name, file, null, false, false, null, songFinishedHook)
|
||||||
|
|
||||||
|
// FileHandle-based constructor (for TEVD archive support)
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
fileHandle: FileHandle,
|
||||||
|
looping: Boolean = false,
|
||||||
|
toRAM: Boolean = false,
|
||||||
|
samplingRateOverride: Float? = null,
|
||||||
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
|
) : this(name, null, fileHandle, looping, toRAM, samplingRateOverride, songFinishedHook)
|
||||||
|
|
||||||
|
|
||||||
var samplesReadCount = 0L; internal set
|
var samplesReadCount = 0L; internal set
|
||||||
override var totalSizeInSamples: Long
|
override var totalSizeInSamples: Long
|
||||||
private val totalSizeInBytes: Long
|
private val totalSizeInBytes: Long
|
||||||
|
|
||||||
private val gdxMusic: Music = Gdx.audio.newMusic(FileHandle(file))
|
private val gdxMusic: Music = if (file != null) Gdx.audio.newMusic(FileHandle(file)) else Gdx.audio.newMusic(fileHandle!!)
|
||||||
|
|
||||||
private var soundBuf: UnsafePtr? = null; private set
|
private var soundBuf: UnsafePtr? = null; private set
|
||||||
|
|
||||||
@@ -94,7 +115,10 @@ class MusicContainer(
|
|||||||
rate.toFloat()
|
rate.toFloat()
|
||||||
}
|
}
|
||||||
is Mp3.Music -> {
|
is Mp3.Music -> {
|
||||||
val tempMusic = Gdx.audio.newMusic(Gdx.files.absolute(file.absolutePath))
|
val tempMusic = if (file == null)
|
||||||
|
Gdx.audio.newMusic(fileHandle)
|
||||||
|
else
|
||||||
|
Gdx.audio.newMusic(Gdx.files.absolute(file.absolutePath))
|
||||||
val bitstream = tempMusic.extortField<Bitstream>("bitstream")!!
|
val bitstream = tempMusic.extortField<Bitstream>("bitstream")!!
|
||||||
val header = bitstream.readFrame()
|
val header = bitstream.readFrame()
|
||||||
val rate = header.sampleRate
|
val rate = header.sampleRate
|
||||||
@@ -118,11 +142,22 @@ class MusicContainer(
|
|||||||
if (it.last() == "Music") it.dropLast(1).last() else it.last()
|
if (it.last() == "Music") it.dropLast(1).last() else it.last()
|
||||||
}
|
}
|
||||||
|
|
||||||
totalSizeInSamples = when (gdxMusic) {
|
totalSizeInSamples = if (file != null) {
|
||||||
is Wav.Music -> getWavFileSampleCount(file)
|
when (gdxMusic) {
|
||||||
is Ogg.Music -> getOggFileSampleCount(file)
|
is Wav.Music -> getWavFileSampleCount(file)
|
||||||
is Mp3.Music -> getMp3FileSampleCount(file)
|
is Ogg.Music -> getOggFileSampleCount(file)
|
||||||
else -> Long.MAX_VALUE
|
is Mp3.Music -> getMp3FileSampleCount(file)
|
||||||
|
else -> Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
} else if (fileHandle != null) {
|
||||||
|
when (gdxMusic) {
|
||||||
|
is Wav.Music -> getWavFileSampleCountFromHandle(fileHandle)
|
||||||
|
is Ogg.Music -> getOggFileSampleCountFromHandle(fileHandle)
|
||||||
|
is Mp3.Music -> getMp3FileSampleCountFromHandle(fileHandle)
|
||||||
|
else -> Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
totalSizeInBytes = totalSizeInSamples * 2 * channels
|
totalSizeInBytes = totalSizeInSamples * 2 * channels
|
||||||
|
|
||||||
@@ -329,10 +364,65 @@ class MusicContainer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() = if (name.isEmpty()) file.nameWithoutExtension else name
|
private fun getWavFileSampleCountFromHandle(fh: FileHandle): Long {
|
||||||
|
return try {
|
||||||
|
val ais = AudioSystem.getAudioInputStream(BufferedInputStream(fh.read()))
|
||||||
|
val r = ais.frameLength
|
||||||
|
ais.close()
|
||||||
|
r
|
||||||
|
}
|
||||||
|
catch (_: Throwable) {
|
||||||
|
Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?) = this.file.path == (other as MusicContainer).file.path
|
private fun getOggFileSampleCountFromHandle(fh: FileHandle): Long {
|
||||||
fun equalInstance(other: Any?) = this.file.path == (other as MusicContainer).file.path && this.hash == (other as MusicContainer).hash
|
return try {
|
||||||
|
// VorbisFile requires a file path; use a temp file
|
||||||
|
val tempFile = java.io.File.createTempFile("terrarum_ogg_", ".ogg")
|
||||||
|
tempFile.deleteOnExit()
|
||||||
|
tempFile.writeBytes(fh.readBytes())
|
||||||
|
val vorbisFile = VorbisFile(tempFile.absolutePath)
|
||||||
|
val r = vorbisFile.pcm_total(0)
|
||||||
|
tempFile.delete()
|
||||||
|
r
|
||||||
|
}
|
||||||
|
catch (_: Throwable) {
|
||||||
|
Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMp3FileSampleCountFromHandle(fh: FileHandle): Long {
|
||||||
|
return try {
|
||||||
|
val input = BufferedInputStream(fh.read())
|
||||||
|
val bs = Bitstream(input)
|
||||||
|
|
||||||
|
var header = bs.readFrame()
|
||||||
|
val rate = header.frequency()
|
||||||
|
var totalSamples = 0L
|
||||||
|
|
||||||
|
while (header != null) {
|
||||||
|
totalSamples += (header.ms_per_frame() * rate / 1000).toLong()
|
||||||
|
bs.closeFrame()
|
||||||
|
header = bs.readFrame()
|
||||||
|
}
|
||||||
|
|
||||||
|
bs.close()
|
||||||
|
input.close()
|
||||||
|
|
||||||
|
totalSamples
|
||||||
|
}
|
||||||
|
catch (_: Throwable) {
|
||||||
|
Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val identPath: String get() = file?.path ?: fileHandle?.path() ?: name
|
||||||
|
|
||||||
|
override fun toString() = if (name.isEmpty()) (file?.nameWithoutExtension ?: fileHandle?.nameWithoutExtension() ?: "") else name
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = this.identPath == (other as MusicContainer).identPath
|
||||||
|
fun equalInstance(other: Any?) = this.identPath == (other as MusicContainer).identPath && this.hash == (other as MusicContainer).hash
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
gdxMusic.dispose()
|
gdxMusic.dispose()
|
||||||
@@ -340,7 +430,10 @@ class MusicContainer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun makeCopy(): AudioBank {
|
override fun makeCopy(): AudioBank {
|
||||||
val new = MusicContainer(name, file, looping, false, samplingRateOverride, songFinishedHook)
|
val new = if (file != null)
|
||||||
|
MusicContainer(name, file, looping, false, samplingRateOverride, songFinishedHook)
|
||||||
|
else
|
||||||
|
MusicContainer(name, fileHandle!!, looping, false, samplingRateOverride, songFinishedHook)
|
||||||
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if (this.toRAM) {
|
if (this.toRAM) {
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ object CommandDict {
|
|||||||
|
|
||||||
((listOf("$" to "net.torvald.terrarum")) + ModMgr.loadOrder.reversed().map { it to ModMgr.moduleInfo[it]?.packageName }).forEach { (modName, packageRoot) ->
|
((listOf("$" to "net.torvald.terrarum")) + ModMgr.loadOrder.reversed().map { it to ModMgr.moduleInfo[it]?.packageName }).forEach { (modName, packageRoot) ->
|
||||||
if (modName == "$" || modName != "$" && ModMgr.hasFile(modName, "commands.csv")) {
|
if (modName == "$" || modName != "$" && ModMgr.hasFile(modName, "commands.csv")) {
|
||||||
val commandsList = if (modName == "$") engineCommandList else ModMgr.getFile(modName, "commands.csv").readLines()
|
val commandsList = if (modName == "$") engineCommandList else ModMgr.getGdxFile(modName, "commands.csv").readString("UTF-8").lines()
|
||||||
val packageConsole = "$packageRoot.console"
|
val packageConsole = "$packageRoot.console"
|
||||||
|
|
||||||
printdbg(this, "Loading console commands from '${packageConsole}'")
|
printdbg(this, "Loading console commands from '${packageConsole}'")
|
||||||
// printdbg(this, commandsList.joinToString())
|
// printdbg(this, commandsList.joinToString())
|
||||||
|
|
||||||
commandsList.forEach { commandName ->
|
commandsList.filter { it.isNotBlank() }.forEach { commandName ->
|
||||||
val canonicalName = "$packageConsole.$commandName"
|
val canonicalName = "$packageConsole.$commandName"
|
||||||
val it = ModMgr.moduleClassloader[modName].let {
|
val it = ModMgr.moduleClassloader[modName].let {
|
||||||
if (it != null)
|
if (it != null)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ object FactionFactory {
|
|||||||
*/
|
*/
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun create(module: String, path: String): Faction {
|
fun create(module: String, path: String): Faction {
|
||||||
val jsonObj = JsonFetcher(ModMgr.getFile(module, path))
|
val jsonObj = JsonFetcher(ModMgr.getGdxFile(module, path))
|
||||||
val factionObj = Faction(jsonObj.getString("factionname"))
|
val factionObj = Faction(jsonObj.getString("factionname"))
|
||||||
|
|
||||||
jsonObj.get("factionamicable").asStringArray().forEach { factionObj.addFactionAmicable(it) }
|
jsonObj.get("factionamicable").asStringArray().forEach { factionObj.addFactionAmicable(it) }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.torvald.terrarum.gamecontroller
|
package net.torvald.terrarum.gamecontroller
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.badlogic.gdx.graphics.Pixmap
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
@@ -173,8 +174,13 @@ object IME {
|
|||||||
else -> throw IllegalArgumentException("Unknown candidates mode: $this")
|
else -> throw IllegalArgumentException("Unknown candidates mode: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseKeylayoutFile(file: File): TerrarumKeyLayout {
|
fun parseKeylayoutFile(fileHandle: FileHandle): TerrarumKeyLayout =
|
||||||
val src = file.readText(Charsets.UTF_8)
|
parseKeylayoutFromString(fileHandle.readString("UTF-8"))
|
||||||
|
|
||||||
|
fun parseKeylayoutFile(file: File): TerrarumKeyLayout =
|
||||||
|
parseKeylayoutFromString(file.readText(Charsets.UTF_8))
|
||||||
|
|
||||||
|
private fun parseKeylayoutFromString(src: String): TerrarumKeyLayout {
|
||||||
val jsval = context.eval("js", "'use strict';Object.freeze($src)")
|
val jsval = context.eval("js", "'use strict';Object.freeze($src)")
|
||||||
val name = jsval.getMember("n").asString()
|
val name = jsval.getMember("n").asString()
|
||||||
val capsmode = jsval.getMember("capslock").asString().toCapsMode()
|
val capsmode = jsval.getMember("capslock").asString().toCapsMode()
|
||||||
@@ -201,8 +207,6 @@ object IME {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// println("[IME] Test Keymap print for $name:"); for (keycode in 0 until 256) { print("$keycode:\t"); println(out[keycode].joinToString("\t")) }
|
|
||||||
|
|
||||||
return TerrarumKeyLayout(name, capsmode, out, physicalLayout)
|
return TerrarumKeyLayout(name, capsmode, out, physicalLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,8 +219,13 @@ object IME {
|
|||||||
else -> throw IllegalArgumentException("Unknown operation mode: $this")
|
else -> throw IllegalArgumentException("Unknown operation mode: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseImeFile(file: File): TerrarumIME {
|
fun parseImeFile(fileHandle: FileHandle): TerrarumIME =
|
||||||
val code = file.readText(Charsets.UTF_8)
|
parseImeFromString(fileHandle.readString("UTF-8"))
|
||||||
|
|
||||||
|
fun parseImeFile(file: File): TerrarumIME =
|
||||||
|
parseImeFromString(file.readText(Charsets.UTF_8))
|
||||||
|
|
||||||
|
private fun parseImeFromString(code: String): TerrarumIME {
|
||||||
val jsval = context.eval("js", "\"use strict\";(function(){$code})()")
|
val jsval = context.eval("js", "\"use strict\";(function(){$code})()")
|
||||||
val name = jsval.getMember("n").asString()
|
val name = jsval.getMember("n").asString()
|
||||||
val candidatesCount = jsval.getMember("v").asString().toViewCount()
|
val candidatesCount = jsval.getMember("v").asString().toViewCount()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.terrarum.langpack
|
package net.torvald.terrarum.langpack
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.tail
|
import net.torvald.terrarum.tail
|
||||||
@@ -82,47 +83,62 @@ object Lang {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun load(localesHandle: FileHandle) {
|
||||||
|
printdbg(this, "Loading languages from ${localesHandle.path()}")
|
||||||
|
|
||||||
|
localesHandle.list().filter { it.isDirectory }.forEach { languageList.add(it.name()) }
|
||||||
|
|
||||||
|
// temporary filter
|
||||||
|
languageList.remove("jaJPysi")
|
||||||
|
|
||||||
|
for (lang in languageList) {
|
||||||
|
printdbg(this, "Loading langpack from ${localesHandle.path()}/$lang/")
|
||||||
|
|
||||||
|
val langFiles = localesHandle.child(lang).list()
|
||||||
|
|
||||||
|
langFiles.forEach {
|
||||||
|
if (!it.name().startsWith("Polyglot") && it.name().endsWith(".json")) {
|
||||||
|
processRegularLangfile(it, lang)
|
||||||
|
}
|
||||||
|
else if (it.name().startsWith("Polyglot") && it.name().endsWith(".json")) {
|
||||||
|
processPolyglotLangFile(it, lang)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun processRegularLangfile(file: File, lang: String) {
|
private fun processRegularLangfile(file: File, lang: String) {
|
||||||
val json = JsonFetcher(file)
|
val json = JsonFetcher(file)
|
||||||
/*
|
|
||||||
* Terrarum langpack JSON structure is:
|
|
||||||
*
|
|
||||||
* (root object)
|
|
||||||
* "<<STRING ID>>" = "<<LOCALISED TEXT>>"
|
|
||||||
*/
|
|
||||||
//println(json.entrySet())
|
|
||||||
JsonFetcher.forEachSiblings(json) { key, value ->
|
JsonFetcher.forEachSiblings(json) { key, value ->
|
||||||
langpack.put("${key}_$lang", value.asString().trim())
|
langpack.put("${key}_$lang", value.asString().trim())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processRegularLangfile(fileHandle: FileHandle, lang: String) {
|
||||||
|
val json = JsonFetcher(fileHandle)
|
||||||
|
JsonFetcher.forEachSiblings(json) { key, value ->
|
||||||
|
langpack.put("${key}_$lang", value.asString().trim())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processPolyglotLangFile(file: File, lang: String) {
|
private fun processPolyglotLangFile(file: File, lang: String) {
|
||||||
val json = JsonFetcher(file)
|
val json = JsonFetcher(file)
|
||||||
/*
|
|
||||||
* Polyglot JSON structure is:
|
|
||||||
*
|
|
||||||
* (root object)
|
|
||||||
* "resources": object
|
|
||||||
* "polyglot": object
|
|
||||||
* (polyglot meta)
|
|
||||||
* "data": array
|
|
||||||
* [0]: object
|
|
||||||
* n = "CONTEXT_CHARACTER_CLASS"
|
|
||||||
* s = "Class"
|
|
||||||
* [1]: object
|
|
||||||
* n = "CONTEXT_CHARACTER_DELETE"
|
|
||||||
* s = "Delecte Character"
|
|
||||||
* (the array continues)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
JsonFetcher.forEachSiblings(json.get("resources").get("data")) { _, entry ->
|
JsonFetcher.forEachSiblings(json.get("resources").get("data")) { _, entry ->
|
||||||
langpack.put(
|
langpack.put(
|
||||||
"${entry.getString("n")}_$lang",
|
"${entry.getString("n")}_$lang",
|
||||||
entry.getString("s").trim()
|
entry.getString("s").trim()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processPolyglotLangFile(fileHandle: FileHandle, lang: String) {
|
||||||
|
val json = JsonFetcher(fileHandle)
|
||||||
|
JsonFetcher.forEachSiblings(json.get("resources").get("data")) { _, entry ->
|
||||||
|
langpack.put(
|
||||||
|
"${entry.getString("n")}_$lang",
|
||||||
|
entry.getString("s").trim()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val bindOp = ">>="
|
private val bindOp = ">>="
|
||||||
|
|||||||
@@ -161,10 +161,10 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val file = ModMgr.getFile("basegame", "demoworld")
|
val fileHandle = ModMgr.getGdxFile("basegame", "demoworld")
|
||||||
val reader = java.io.FileReader(file)
|
val reader = fileHandle.reader("UTF-8")
|
||||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||||
val world = ReadSimpleWorld(reader, file)
|
val world = ReadSimpleWorld(reader, fileHandle.file())
|
||||||
demoWorld = world
|
demoWorld = world
|
||||||
demoWorld.worldTime.timeDelta = 30
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world loaded")
|
printdbg(this, "Demo world loaded")
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ object InstrumentLoader {
|
|||||||
CommonResourcePool.getAs<Pair<FloatArray, FloatArray>>("${baseResourceName}_$it")
|
CommonResourcePool.getAs<Pair<FloatArray, FloatArray>>("${baseResourceName}_$it")
|
||||||
}
|
}
|
||||||
|
|
||||||
val masterFile = MusicContainer("${idBase}_${initialNote}", ModMgr.getFile(module, path))
|
val masterFile = MusicContainer("${idBase}_${initialNote}", ModMgr.getGdxFile(module, path))
|
||||||
val masterSamplesL = FloatArray(masterFile.totalSizeInSamples.toInt())
|
val masterSamplesL = FloatArray(masterFile.totalSizeInSamples.toInt())
|
||||||
val masterSamplesR = FloatArray(masterFile.totalSizeInSamples.toInt())
|
val masterSamplesR = FloatArray(masterFile.totalSizeInSamples.toInt())
|
||||||
masterFile.readSamples(masterSamplesL, masterSamplesR)
|
masterFile.readSamples(masterSamplesL, masterSamplesR)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ open class ActorLobbed(throwPitch: Float) : ActorWithBody() {
|
|||||||
|
|
||||||
@Transient private val pitch = throwPitch.coerceIn(0.5f, 2f)
|
@Transient private val pitch = throwPitch.coerceIn(0.5f, 2f)
|
||||||
@Transient private val whooshSound = MusicContainer(
|
@Transient private val whooshSound = MusicContainer(
|
||||||
"throw_low_short", ModMgr.getFile("basegame", "audio/effects/throwing/throw_low_short.wav"),
|
"throw_low_short", ModMgr.getGdxFile("basegame", "audio/effects/throwing/throw_low_short.wav"),
|
||||||
toRAM = true,
|
toRAM = true,
|
||||||
samplingRateOverride = 48000f * pitch
|
samplingRateOverride = 48000f * pitch
|
||||||
)
|
)
|
||||||
@@ -63,17 +63,17 @@ open class ActorPrimedBomb(
|
|||||||
private var explosionCalled = false
|
private var explosionCalled = false
|
||||||
|
|
||||||
@Transient private val boomSound = MusicContainer(
|
@Transient private val boomSound = MusicContainer(
|
||||||
"boom", ModMgr.getFile("basegame", "audio/effects/explosion/bang_bomb.wav"), toRAM = true
|
"boom", ModMgr.getGdxFile("basegame", "audio/effects/explosion/bang_bomb.wav"), toRAM = true
|
||||||
) {
|
) {
|
||||||
this.flagDespawn()
|
this.flagDespawn()
|
||||||
}
|
}
|
||||||
@Transient private val fuseSound = MusicContainer(
|
@Transient private val fuseSound = MusicContainer(
|
||||||
"fuse", ModMgr.getFile("basegame", "audio/effects/explosion/fuse.wav"), toRAM = true
|
"fuse", ModMgr.getGdxFile("basegame", "audio/effects/explosion/fuse.wav"), toRAM = true
|
||||||
) {
|
) {
|
||||||
this.flagDespawn()
|
this.flagDespawn()
|
||||||
}
|
}
|
||||||
@Transient private val fuseSoundCont = MusicContainer(
|
@Transient private val fuseSoundCont = MusicContainer(
|
||||||
"fuse_continue", ModMgr.getFile("basegame", "audio/effects/explosion/fuse_continue.wav"), toRAM = true
|
"fuse_continue", ModMgr.getGdxFile("basegame", "audio/effects/explosion/fuse_continue.wav"), toRAM = true
|
||||||
) {
|
) {
|
||||||
this.flagDespawn()
|
this.flagDespawn()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ class FixtureAlloyingFurnace : FixtureBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Transient val static = MusicContainer("bonfire", ModMgr.getFile("basegame", "audio/effects/static/bonfire.ogg"), true)
|
@Transient val static = MusicContainer("bonfire", ModMgr.getGdxFile("basegame", "audio/effects/static/bonfire.ogg"), true)
|
||||||
@Transient val light = Cvec(0.5f, 0.18f, 0f, 0f)
|
@Transient val light = Cvec(0.5f, 0.18f, 0f, 0f)
|
||||||
|
|
||||||
@Transient override var lightBoxList = arrayListOf(Lightbox(Hitbox(0.0, 0.0, TILE_SIZED * 2, TILE_SIZED * 2), light))
|
@Transient override var lightBoxList = arrayListOf(Lightbox(Hitbox(0.0, 0.0, TILE_SIZED * 2, TILE_SIZED * 2), light))
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient val static = MusicContainer("bonfire", ModMgr.getFile("basegame", "audio/effects/static/bonfire.ogg"), true)
|
@Transient val static = MusicContainer("bonfire", ModMgr.getGdxFile("basegame", "audio/effects/static/bonfire.ogg"), true)
|
||||||
|
|
||||||
@Transient override var lightBoxList = arrayListOf(Lightbox(Hitbox(0.0, 0.0, TerrarumAppConfiguration.TILE_SIZED * 2, TerrarumAppConfiguration.TILE_SIZED * 2), Cvec(0.5f, 0.18f, 0f, 0f)))
|
@Transient override var lightBoxList = arrayListOf(Lightbox(Hitbox(0.0, 0.0, TerrarumAppConfiguration.TILE_SIZED * 2, TerrarumAppConfiguration.TILE_SIZED * 2), Cvec(0.5f, 0.18f, 0f, 0f)))
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ class FixtureSmelterBasic : FixtureBase {
|
|||||||
this.mainUI = UISmelterBasic(this)
|
this.mainUI = UISmelterBasic(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient val static = MusicContainer("bonfire", ModMgr.getFile("basegame", "audio/effects/static/bonfire.ogg"), true)
|
@Transient val static = MusicContainer("bonfire", ModMgr.getGdxFile("basegame", "audio/effects/static/bonfire.ogg"), true)
|
||||||
@Transient val light = Cvec(0.5f, 0.18f, 0f, 0f)
|
@Transient val light = Cvec(0.5f, 0.18f, 0f, 0f)
|
||||||
|
|
||||||
@Transient override var lightBoxList = arrayListOf(Lightbox(Hitbox(0.0, 2*TILE_SIZED, TILE_SIZED * 2, TILE_SIZED * 2), light))
|
@Transient override var lightBoxList = arrayListOf(Lightbox(Hitbox(0.0, 2*TILE_SIZED, TILE_SIZED * 2, TILE_SIZED * 2), light))
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class FixtureTypewriter : FixtureBase {
|
|||||||
|
|
||||||
internal class TestLeafletPrimaryUseHandler : FileRefItemPrimaryUseHandler {
|
internal class TestLeafletPrimaryUseHandler : FileRefItemPrimaryUseHandler {
|
||||||
override fun use(item: ItemFileRef): Long {
|
override fun use(item: ItemFileRef): Long {
|
||||||
println(item.getAsFile().readText(Common.CHARSET))
|
println(item.getAsGdxFile().readString(Common.CHARSET.displayName()))
|
||||||
return 0L
|
return 0L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ object InjectCreatureRaw {
|
|||||||
* @param jsonFileName with extension
|
* @param jsonFileName with extension
|
||||||
*/
|
*/
|
||||||
operator fun invoke(actorValueRef: ActorValue, module: String, jsonFileName: String) {
|
operator fun invoke(actorValueRef: ActorValue, module: String, jsonFileName: String) {
|
||||||
val jsonObj = JsonFetcher(ModMgr.getFile(module, "creatures/$jsonFileName"))
|
val jsonObj = JsonFetcher(ModMgr.getGdxFile(module, "creatures/$jsonFileName"))
|
||||||
|
|
||||||
|
|
||||||
JsonFetcher.forEachSiblings(jsonObj) { key, value -> if (!key.startsWith("_")) {
|
JsonFetcher.forEachSiblings(jsonObj) { key, value -> if (!key.startsWith("_")) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import net.torvald.terrarum.ModMgr
|
|||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ open class ItemFileRef(originalID: ItemID) : GameItem(originalID) {
|
|||||||
*/
|
*/
|
||||||
open var refIsShared: Boolean = false
|
open var refIsShared: Boolean = false
|
||||||
|
|
||||||
@Transient open lateinit var ref: File
|
@Transient open lateinit var ref: FileHandle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application-defined.
|
* Application-defined.
|
||||||
@@ -101,10 +102,10 @@ open class ItemFileRef(originalID: ItemID) : GameItem(originalID) {
|
|||||||
else
|
else
|
||||||
ModMgr.getGdxFile(refModuleName, refPath)
|
ModMgr.getGdxFile(refModuleName, refPath)
|
||||||
|
|
||||||
fun getAsFile() = if (refIsShared)
|
/*fun getAsFile() = if (refIsShared)
|
||||||
File(App.saveSharedDir + "/$refPath")
|
File(App.saveSharedDir + "/$refPath")
|
||||||
else
|
else
|
||||||
ModMgr.getFile(refModuleName, refPath)
|
ModMgr.getFile(refModuleName, refPath)*/
|
||||||
|
|
||||||
@Transient private var classCache: FileRefItemPrimaryUseHandler? = null
|
@Transient private var classCache: FileRefItemPrimaryUseHandler? = null
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ data class MusicDiscMetadata(val title: String, val author: String, val album: S
|
|||||||
object MusicDiscHelper {
|
object MusicDiscHelper {
|
||||||
fun getMetadata(musicFile: FileHandle): MusicDiscMetadata {
|
fun getMetadata(musicFile: FileHandle): MusicDiscMetadata {
|
||||||
val musicdbFile = musicFile.sibling("_musicdb.json")
|
val musicdbFile = musicFile.sibling("_musicdb.json")
|
||||||
val musicdb = JsonFetcher.invoke(musicdbFile.file())
|
val musicdb = JsonFetcher.invoke(musicdbFile)
|
||||||
val propForThisFile = musicdb.get(musicFile.name())
|
val propForThisFile = musicdb.get(musicFile.name())
|
||||||
|
|
||||||
val artist = propForThisFile.get("artist").asString()
|
val artist = propForThisFile.get("artist").asString()
|
||||||
@@ -37,7 +37,7 @@ open class MusicDiscPrototype(originalID: ItemID, module: String, path: String)
|
|||||||
override var refPath = path
|
override var refPath = path
|
||||||
override var refModuleName = module
|
override var refModuleName = module
|
||||||
override val canBeDynamic = false
|
override val canBeDynamic = false
|
||||||
@Transient override var ref = ModMgr.getFile(refModuleName, refPath)
|
@Transient override var ref = ModMgr.getGdxFile(refModuleName, refPath)
|
||||||
override var mediumIdentifier = "music_disc"
|
override var mediumIdentifier = "music_disc"
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ object PickaxeCore : TooltipListener() {
|
|||||||
|
|
||||||
private val soundCue = MusicContainer(
|
private val soundCue = MusicContainer(
|
||||||
"pickaxe_sound_cue",
|
"pickaxe_sound_cue",
|
||||||
ModMgr.getFile("basegame", "audio/effects/accessibility/pickaxe_valuable.ogg"),
|
ModMgr.getGdxFile("basegame", "audio/effects/accessibility/pickaxe_valuable.ogg"),
|
||||||
toRAM = false
|
toRAM = false
|
||||||
).also {
|
).also {
|
||||||
App.disposables.add(it)
|
App.disposables.add(it)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class UIElemTest : ApplicationAdapter() {
|
|||||||
private lateinit var ui: UICanvas
|
private lateinit var ui: UICanvas
|
||||||
|
|
||||||
override fun create() {
|
override fun create() {
|
||||||
App.fontGame = TerrarumSansBitmap(App.FONT_DIR, false, true, false,
|
App.fontGame = TerrarumSansBitmap(false, true, false,
|
||||||
false,
|
false,
|
||||||
256, false, 0.5f, false
|
256, false, 0.5f, false
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ object CSVFetcher {
|
|||||||
return csvRecordList
|
return csvRecordList
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readFromModule(module: String, path: String) = net.torvald.terrarum.utils.CSVFetcher.readFromFile(ModMgr.getGdxFile(module, path).path())
|
fun readFromModule(module: String, path: String): List<org.apache.commons.csv.CSVRecord> {
|
||||||
|
val content = ModMgr.getGdxFile(module, path).readString("UTF-8")
|
||||||
|
return readFromString(content)
|
||||||
|
}
|
||||||
|
|
||||||
fun readFromString(csv: String): List<org.apache.commons.csv.CSVRecord> {
|
fun readFromString(csv: String): List<org.apache.commons.csv.CSVRecord> {
|
||||||
val preprocessed = preprocessCSV(csv)
|
val preprocessed = preprocessCSV(csv)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.terrarum.utils
|
package net.torvald.terrarum.utils
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.badlogic.gdx.utils.JsonReader
|
import com.badlogic.gdx.utils.JsonReader
|
||||||
import com.badlogic.gdx.utils.JsonValue
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
@@ -36,6 +37,13 @@ object JsonFetcher {
|
|||||||
return JsonReader().parse(jsonString.toString())
|
return JsonReader().parse(jsonString.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(java.io.IOException::class)
|
||||||
|
operator fun invoke(fileHandle: FileHandle): JsonValue {
|
||||||
|
val content = fileHandle.readString("UTF-8")
|
||||||
|
printdbg(this, "Reading JSON ${fileHandle.path()}")
|
||||||
|
return JsonReader().parse(content)
|
||||||
|
}
|
||||||
|
|
||||||
fun readFromJsonString(stringReader: Reader): JsonValue {
|
fun readFromJsonString(stringReader: Reader): JsonValue {
|
||||||
return JsonReader().parse(stringReader.readText())
|
return JsonReader().parse(stringReader.readText())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.terrarum.weather
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
@@ -40,24 +41,17 @@ class WeatherCodex : Disposable {
|
|||||||
|
|
||||||
fun readFromJson(modname: String, file: File) = readFromJson(modname, file.path)
|
fun readFromJson(modname: String, file: File) = readFromJson(modname, file.path)
|
||||||
|
|
||||||
|
fun readFromJson(modname: String, fileHandle: FileHandle) {
|
||||||
|
readFromJsonValue(modname, JsonFetcher.invoke(fileHandle))
|
||||||
|
}
|
||||||
|
|
||||||
private val pathToImage = "weathers"
|
private val pathToImage = "weathers"
|
||||||
|
|
||||||
fun readFromJson(modname: String, path: String) {
|
fun readFromJson(modname: String, path: String) {
|
||||||
/* JSON structure:
|
readFromJsonValue(modname, JsonFetcher(path))
|
||||||
{
|
}
|
||||||
"skyboxGradColourMap": "colourmap/sky_colour.tga", // string (path to image) for dynamic. Image must be RGBA8888 or RGB888
|
|
||||||
"extraImages": [
|
|
||||||
// if any, it will be like:
|
|
||||||
sun01.tga,
|
|
||||||
clouds01.tga,
|
|
||||||
clouds02.tga,
|
|
||||||
auroraBlueViolet.tga
|
|
||||||
]
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
val JSON = JsonFetcher(path)
|
|
||||||
|
|
||||||
|
private fun readFromJsonValue(modname: String, JSON: com.badlogic.gdx.utils.JsonValue) {
|
||||||
val skyboxModel = JSON.getString("skyboxGradColourMap")
|
val skyboxModel = JSON.getString("skyboxGradColourMap")
|
||||||
val lightboxModel = JSON.getString("daylightClut")
|
val lightboxModel = JSON.getString("daylightClut")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user