mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +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:
|
||||
./make_assets_release.sh || true
|
||||
./make_assets_archive.sh
|
||||
|
||||
linux_x86:
|
||||
./build_app_linux_x86.sh
|
||||
|
||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-linux-arm"
|
||||
DESKTOPFILE="../out/build_autogen_linux.desktop"
|
||||
JARNAME="TerrarumBuild.jar"
|
||||
|
||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
||||
if [ ! -f "out/assets.tevd" ]; then
|
||||
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -29,9 +29,8 @@ mkdir $DESTDIR/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/java
|
||||
|
||||
# Copy over the asset archive, manifest, and jarfile
|
||||
cp "out/assets.tar.zst" $DESTDIR/
|
||||
cp "out/assets.manifest" $DESTDIR/
|
||||
# Copy over the asset archive and jarfile
|
||||
cp "out/assets.tevd" $DESTDIR/
|
||||
cp "../out/$JARNAME" $DESTDIR/out/
|
||||
|
||||
# Pack everything to AppImage
|
||||
|
||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-linux-x86"
|
||||
DESKTOPFILE="../out/build_autogen_linux.desktop"
|
||||
JARNAME="TerrarumBuild.jar"
|
||||
|
||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
||||
if [ ! -f "out/assets.tevd" ]; then
|
||||
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -29,9 +29,8 @@ mkdir $DESTDIR/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/java
|
||||
|
||||
# Copy over the asset archive, manifest, and jarfile
|
||||
cp "out/assets.tar.zst" $DESTDIR/
|
||||
cp "out/assets.manifest" $DESTDIR/
|
||||
# Copy over the asset archive and jarfile
|
||||
cp "out/assets.tevd" $DESTDIR/
|
||||
cp "../out/$JARNAME" $DESTDIR/out/
|
||||
|
||||
# Pack everything to AppImage
|
||||
|
||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-osx-arm"
|
||||
PLISTFILE="../out/build_autogen_macos_Info.plist"
|
||||
JARNAME="TerrarumBuild.jar"
|
||||
|
||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
||||
if [ ! -f "out/assets.tevd" ]; then
|
||||
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -32,9 +32,8 @@ mkdir $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
|
||||
|
||||
# Copy over the asset archive, manifest, and jarfile
|
||||
cp "out/assets.tar.zst" $DESTDIR/Contents/MacOS/
|
||||
cp "out/assets.manifest" $DESTDIR/Contents/MacOS/
|
||||
# Copy over the asset archive and jarfile
|
||||
cp "out/assets.tevd" $DESTDIR/Contents/MacOS/
|
||||
cp "../out/$JARNAME" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
# zip everything
|
||||
|
||||
@@ -9,8 +9,8 @@ RUNTIME="runtime-osx-x86"
|
||||
PLISTFILE="../out/build_autogen_macos_Info.plist"
|
||||
JARNAME="TerrarumBuild.jar"
|
||||
|
||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
||||
if [ ! -f "out/assets.tevd" ]; then
|
||||
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -32,9 +32,8 @@ mkdir $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
|
||||
|
||||
# Copy over the asset archive, manifest, and jarfile
|
||||
cp "out/assets.tar.zst" $DESTDIR/Contents/MacOS/
|
||||
cp "out/assets.manifest" $DESTDIR/Contents/MacOS/
|
||||
# Copy over the asset archive and jarfile
|
||||
cp "out/assets.tevd" $DESTDIR/Contents/MacOS/
|
||||
cp "../out/$JARNAME" $DESTDIR/Contents/MacOS/out/
|
||||
|
||||
# zip everything
|
||||
|
||||
@@ -8,8 +8,8 @@ RUNTIME="runtime-windows-x86"
|
||||
RCFILE="../out/build_autogen_windows.rc"
|
||||
JARNAME="TerrarumBuild.jar"
|
||||
|
||||
if [ ! -f "out/assets.tar.zst" ] || [ ! -f "out/assets.manifest" ]; then
|
||||
echo "'assets.tar.zst' or 'assets.manifest' not found in out/; run 'make assets' first." >&2
|
||||
if [ ! -f "out/assets.tevd" ]; then
|
||||
echo "'assets.tevd' not found in out/; run 'make assets' first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -34,9 +34,8 @@ mkdir $DESTDIR/out
|
||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||
mv $DESTDIR/out/$RUNTIME/bin/java.exe $DESTDIR/out/$RUNTIME/bin/java.exe
|
||||
|
||||
# Copy over the asset archive, manifest, and jarfile
|
||||
cp "out/assets.tar.zst" $DESTDIR/
|
||||
cp "out/assets.manifest" $DESTDIR/
|
||||
# Copy over the asset archive and jarfile
|
||||
cp "out/assets.tevd" $DESTDIR/
|
||||
cp "../out/$JARNAME" $DESTDIR/out/
|
||||
|
||||
# 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
|
||||
|
||||
fun preloadFonts() {
|
||||
testFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha, textCacheSize = 4096)
|
||||
partTitleFont = TerrarumSansBitmap(App.FONT_DIR, shadowAlpha = bodyTextShadowAlpha).also {
|
||||
testFont = TerrarumSansBitmap(shadowAlpha = bodyTextShadowAlpha, textCacheSize = 4096)
|
||||
partTitleFont = TerrarumSansBitmap(shadowAlpha = bodyTextShadowAlpha).also {
|
||||
it.interchar = 1
|
||||
}
|
||||
titleFont = TerrarumSansBitmap(App.FONT_DIR).also {
|
||||
titleFont = TerrarumSansBitmap().also {
|
||||
it.interchar = 1
|
||||
it.scale = 2
|
||||
}
|
||||
subtitleFont = TerrarumSansBitmap(App.FONT_DIR).also {
|
||||
subtitleFont = TerrarumSansBitmap().also {
|
||||
it.interchar = 1
|
||||
}
|
||||
fontInit = true
|
||||
|
||||
@@ -255,10 +255,6 @@ public class App implements ApplicationListener {
|
||||
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 ShaderProgram shaderHicolour;
|
||||
public static ShaderProgram shaderDebugDiff;
|
||||
@@ -445,6 +441,7 @@ public class App implements ApplicationListener {
|
||||
// load configs
|
||||
getDefaultDirectory();
|
||||
createDirs();
|
||||
AssetCache.INSTANCE.init();
|
||||
initialiseConfig();
|
||||
readConfigJson();
|
||||
|
||||
@@ -582,13 +579,13 @@ public class App implements ApplicationListener {
|
||||
if (!loadOrder.isEmpty()) {
|
||||
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()) {
|
||||
splashBackdrop = new TextureRegion(new Texture(textureFile));
|
||||
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()) {
|
||||
splashScreenLogo = new TextureRegion(new Texture(logoFile));
|
||||
}
|
||||
@@ -604,10 +601,10 @@ public class App implements ApplicationListener {
|
||||
}
|
||||
|
||||
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) {
|
||||
splashScreenLogo = new TextureRegion(new Texture("assets/graphics/logo.png"));
|
||||
splashScreenLogo = new TextureRegion(new Texture(AssetCache.INSTANCE.getFileHandle("graphics/logo.png")));
|
||||
}
|
||||
|
||||
Gdx.graphics.setContinuousRendering(true);
|
||||
@@ -622,13 +619,13 @@ public class App implements ApplicationListener {
|
||||
|
||||
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_health2", () -> new Texture(Gdx.files.internal("./assets/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_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_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_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_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("title_health1", () -> new Texture(AssetCache.INSTANCE.getFileHandle("graphics/gui/health_take_a_break.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", 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", 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", 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", 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", AssetCache.INSTANCE.getFileHandle("audio/effects/haptic_bip.ogg"), false, true, null, (AudioBank m) -> { highPrioritySoundPlaying = false; return null; }));
|
||||
// make loading list
|
||||
CommonResourcePool.INSTANCE.loadAll();
|
||||
|
||||
@@ -669,7 +666,7 @@ public class App implements ApplicationListener {
|
||||
rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
|
||||
|
||||
|
||||
fontGame = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
||||
fontGame = new TerrarumSansBitmap(false, false, false,
|
||||
false,
|
||||
256, false, 0.5f, false
|
||||
);
|
||||
@@ -1062,6 +1059,8 @@ public class App implements ApplicationListener {
|
||||
|
||||
deleteTempfiles();
|
||||
|
||||
AssetCache.INSTANCE.dispose();
|
||||
|
||||
Toolkit.INSTANCE.dispose();
|
||||
BlurMgr.INSTANCE.dispose();
|
||||
|
||||
@@ -1157,11 +1156,11 @@ public class App implements ApplicationListener {
|
||||
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("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("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("inventory_category", () -> new TextureRegionPack("./assets/graphics/gui/inventory/category.tga", 20, 20, 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(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(AssetCache.INSTANCE.getFileHandle("graphics/gui/inventory/category.tga"), 20, 20, 0, 0, 0, 0, false, false, false));
|
||||
CommonResourcePool.INSTANCE.loadAll();
|
||||
|
||||
// shaderHicolour = loadShaderFromClasspath("shaders/default.vert", "shaders/hicolour.frag");
|
||||
@@ -1226,12 +1225,12 @@ public class App implements ApplicationListener {
|
||||
else {
|
||||
environment = RunningEnvironment.PC;
|
||||
}*/
|
||||
fontUITitle = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
||||
fontUITitle = new TerrarumSansBitmap(false, false, false,
|
||||
false,
|
||||
64, false, 0.5f, false
|
||||
);
|
||||
fontUITitle.setInterchar(1);
|
||||
fontGameFBO = new TerrarumSansBitmap(FONT_DIR, false, true, false,
|
||||
fontGameFBO = new TerrarumSansBitmap(false, true, false,
|
||||
false,
|
||||
64, false, 203f/255f, false
|
||||
);
|
||||
@@ -1514,6 +1513,8 @@ public class App implements ApplicationListener {
|
||||
/** defaultDir + "/Custom/Music" */
|
||||
public static String customMusicDir;
|
||||
public static String customAmbientDir;
|
||||
/** defaultDir + "/Caches" */
|
||||
public static String cachesDir;
|
||||
|
||||
private static void getDefaultDirectory() {
|
||||
String OS = OSName.toUpperCase();
|
||||
@@ -1551,6 +1552,7 @@ public class App implements ApplicationListener {
|
||||
customDir = defaultDir + "/Custom";
|
||||
customMusicDir = customDir + "/Music";
|
||||
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.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
|
||||
}
|
||||
|
||||
const val modDirInternal = "./assets/mods"
|
||||
val modDirInternal: String get() = "./assets/mods"
|
||||
val modDirExternal = "${App.defaultDir}/Modules"
|
||||
|
||||
/** Module name (directory name), ModuleMetadata */
|
||||
@@ -161,21 +161,46 @@ object ModMgr {
|
||||
try {
|
||||
val modMetadata = Properties()
|
||||
|
||||
val _internalFile = File("$modDirInternal/$moduleName/$metaFilename")
|
||||
val _externalFile = File("$modDirExternal/$moduleName/$metaFilename")
|
||||
|
||||
// external mod has precedence over the internal
|
||||
val isInternal = if (_externalFile.exists()) false else if (_internalFile.exists()) true else throw FileNotFoundException()
|
||||
val file = if (isInternal) _internalFile else _externalFile
|
||||
val internalExists = if (AssetCache.isDistribution)
|
||||
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
|
||||
|
||||
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 {
|
||||
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
|
||||
var entry: JsonValue? = defaultConfig.child
|
||||
@@ -208,16 +233,29 @@ object ModMgr {
|
||||
val jar = modMetadata.getProperty("jar")
|
||||
val jarHash = modMetadata.getProperty("jarhash").uppercase()
|
||||
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>()
|
||||
File("$modDir/$moduleName/configplan.csv").let {
|
||||
if (it.exists() && it.isFile) {
|
||||
configPlan.addAll(it.readLines(Common.CHARSET).filter { it.isNotBlank() })
|
||||
val configPlanHandle = if (isInternal && AssetCache.isDistribution)
|
||||
AssetCache.getFileHandle("mods/$moduleName/configplan.csv")
|
||||
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 versionNumber = versionNumeral.toVersionNumber()
|
||||
@@ -447,24 +485,36 @@ object ModMgr {
|
||||
/** Returning files are read-only */
|
||||
fun getGdxFile(module: String, path: String): FileHandle {
|
||||
checkExistence(module)
|
||||
return if (moduleInfo[module]!!.isInternal)
|
||||
Gdx.files.internal("$modDirInternal/$module/$path")
|
||||
return if (moduleInfo[module]!!.isInternal) {
|
||||
if (AssetCache.isDistribution)
|
||||
ClustfileHandle(AssetCache.getClustfile("mods/$module/$path"))
|
||||
else
|
||||
Gdx.files.internal("$modDirInternal/$module/$path")
|
||||
}
|
||||
else
|
||||
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)
|
||||
return if (moduleInfo[module]!!.isInternal)
|
||||
FileSystems.getDefault().getPath("$modDirInternal/$module/$path").toFile()
|
||||
return if (moduleInfo[module]!!.isInternal) {
|
||||
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
|
||||
FileSystems.getDefault().getPath("$modDirExternal/$module/$path").toFile()
|
||||
}
|
||||
}*/
|
||||
fun hasFile(module: String, path: String): Boolean {
|
||||
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)
|
||||
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)
|
||||
if (!dir.isDirectory) {
|
||||
throw FileNotFoundException("The path is not a directory")
|
||||
@@ -472,7 +522,7 @@ object ModMgr {
|
||||
else {
|
||||
return dir.listFiles()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
fun getGdxFiles(module: String, path: String): Array<FileHandle> {
|
||||
checkExistence(module)
|
||||
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
|
||||
* 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 moduleNames = moduleInfo.keys.toList()
|
||||
|
||||
val filesList = ArrayList<Pair<String, File>>()
|
||||
val filesList = ArrayList<Pair<String, FileHandle>>()
|
||||
moduleNames.forEach {
|
||||
val file = getFile(it, path)
|
||||
val file = getGdxFile(it, path)
|
||||
if (file.exists()) filesList.add(it to file)
|
||||
}
|
||||
|
||||
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
|
||||
* contain the file, the mod will be skipped.
|
||||
@@ -739,7 +790,7 @@ object ModMgr {
|
||||
const val langPath = "locales/"
|
||||
|
||||
@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/"
|
||||
|
||||
@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 {
|
||||
printdbg(this, "Registering Low layer ${it.nameWithoutExtension.lowercase()}")
|
||||
IME.registerLowLayer(it.nameWithoutExtension.lowercase(), IME.parseKeylayoutFile(it))
|
||||
DIR.list().filter { it.extension().equals(IME.KEYLAYOUT_EXTENSION, ignoreCase = true) }.sortedBy { it.name() }.forEach {
|
||||
printdbg(this, "Registering Low layer ${it.nameWithoutExtension().lowercase()}")
|
||||
IME.registerLowLayer(it.nameWithoutExtension().lowercase(), IME.parseKeylayoutFile(it))
|
||||
}
|
||||
|
||||
FILE.listFiles { file, s -> s.endsWith(".${IME.IME_EXTENSION}") }.sortedBy { it.name }.forEach {
|
||||
printdbg(this, "Registering High layer ${it.nameWithoutExtension.lowercase()}")
|
||||
IME.registerHighLayer(it.nameWithoutExtension.lowercase(), IME.parseImeFile(it))
|
||||
DIR.list().filter { it.extension().equals(IME.IME_EXTENSION, ignoreCase = true) }.sortedBy { it.name() }.forEach {
|
||||
printdbg(this, "Registering High layer ${it.nameWithoutExtension().lowercase()}")
|
||||
IME.registerHighLayer(it.nameWithoutExtension().lowercase(), IME.parseImeFile(it))
|
||||
}
|
||||
|
||||
val iconFile = getFile(module, keebPath + "icons.tga").let {
|
||||
if (it.exists()) it else getFile(module, keebPath + "icons.png")
|
||||
val iconFile = getGdxFile(module, keebPath + "icons.tga").let {
|
||||
if (it.exists()) it else getGdxFile(module, keebPath + "icons.png")
|
||||
}
|
||||
|
||||
if (iconFile.exists()) {
|
||||
val iconSheet = TextureRegionPack(iconFile.path, 20, 20)
|
||||
val iconPixmap = Pixmap(Gdx.files.absolute(iconFile.path))
|
||||
val iconSheet = TextureRegionPack(iconFile, 20, 20)
|
||||
val iconPixmap = Pixmap(iconFile)
|
||||
for (k in 0 until iconPixmap.height step 20) {
|
||||
val langCode = StringBuilder()
|
||||
for (c in 0 until 20) {
|
||||
@@ -855,7 +906,7 @@ object ModMgr {
|
||||
}
|
||||
|
||||
@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)
|
||||
}
|
||||
}
|
||||
@@ -878,32 +929,21 @@ object ModMgr {
|
||||
}
|
||||
|
||||
@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 ->
|
||||
// modules/<module>/retextures/basegame
|
||||
// printdbg(this, "baseTargetModDir = $baseTargetModDir")
|
||||
|
||||
retexables.forEach { category ->
|
||||
val dir = File(baseTargetModDir, category)
|
||||
// modules/<module>/retextures/basegame/blocks
|
||||
|
||||
// printdbg(this, "cats: ${dir.path}")
|
||||
val dir = baseTargetModDir.child(category)
|
||||
|
||||
if (dir.isDirectory && dir.exists()) {
|
||||
dir.listFiles { it: File ->
|
||||
it.name.contains('-')
|
||||
}?.forEach {
|
||||
// <other modname>-<hopefully a number>.tga or .png
|
||||
val tokens = it.name.split('-')
|
||||
dir.list().filter { it.name().contains('-') }.forEach {
|
||||
val tokens = it.name().split('-')
|
||||
if (tokens.size > 1) {
|
||||
val modname = tokens[0]
|
||||
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/"
|
||||
|
||||
@JvmStatic operator fun invoke(module: String) {
|
||||
getFile(module, recipePath).listFiles { it: File -> it.name.lowercase().endsWith(".json") }?.forEach { jsonFile ->
|
||||
Terrarum.craftingCodex.addFromJson(JsonFetcher(jsonFile), module, jsonFile.name)
|
||||
getGdxFile(module, recipePath).list().filter { !it.isDirectory && it.name().lowercase().endsWith(".json") }.forEach { jsonHandle ->
|
||||
Terrarum.craftingCodex.addFromJson(JsonFetcher.invoke(jsonHandle), module, jsonHandle.name())
|
||||
}
|
||||
|
||||
getFile(module, smeltingPath).listFiles { it: File -> it.name.lowercase().endsWith(".json") }?.forEach { jsonFile ->
|
||||
Terrarum.craftingCodex.addSmeltingFromJson(JsonFetcher(jsonFile), module, jsonFile.name)
|
||||
getGdxFile(module, smeltingPath).list().filter { !it.isDirectory && it.name().lowercase().endsWith(".json") }.forEach { jsonHandle ->
|
||||
Terrarum.craftingCodex.addSmeltingFromJson(JsonFetcher.invoke(jsonHandle), module, jsonHandle.name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package net.torvald.terrarum.audio
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.reflection.forceInvoke
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.CommonResourcePool
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.serialise.toUint
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2024-01-24.
|
||||
@@ -26,7 +26,7 @@ object AudioHelper {
|
||||
return fft
|
||||
}
|
||||
else {
|
||||
val ir = ModMgr.getFile(module, path)
|
||||
val ir = ModMgr.getGdxFile(module, path)
|
||||
val fft = createIR(ir)
|
||||
|
||||
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()) {
|
||||
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)
|
||||
|
||||
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) }
|
||||
|
||||
ir.inputStream().let {
|
||||
java.io.ByteArrayInputStream(irBytes).let {
|
||||
for (i in 0 until sampleCount) {
|
||||
val f1 = Float.fromBits(it.read().and(255) or
|
||||
it.read().and(255).shl(8) or
|
||||
@@ -79,7 +80,7 @@ object AudioHelper {
|
||||
return CommonResourcePool.getAs<Array<FloatArray>>(id)
|
||||
}
|
||||
else {
|
||||
val file = ModMgr.getFile(module, path)
|
||||
val file = ModMgr.getGdxFile(module, path)
|
||||
val samples = createAudioInSamples(file)
|
||||
|
||||
CommonResourcePool.addToLoadingList(id) { samples }
|
||||
@@ -89,8 +90,8 @@ object AudioHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAudioInSamples(static: File): Array<FloatArray> {
|
||||
val music = Gdx.audio.newMusic(Gdx.files.absolute(static.absolutePath))
|
||||
private fun createAudioInSamples(static: FileHandle): Array<FloatArray> {
|
||||
val music = Gdx.audio.newMusic(static)
|
||||
val readbuf = ByteArray(AudioProcessBuf.MP3_CHUNK_SIZE * 4)
|
||||
val OUTBUF_BLOCK_SIZE_IN_BYTES = (48000 * 60) * 2 * 2
|
||||
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.unsafe.UnsafeHelper
|
||||
import net.torvald.unsafe.UnsafePtr
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import javax.sound.sampled.AudioSystem
|
||||
|
||||
class MusicContainer(
|
||||
override val name: String,
|
||||
val file: File,
|
||||
val file: File?,
|
||||
val fileHandle: FileHandle?,
|
||||
val looping: Boolean = false,
|
||||
val toRAM: Boolean = false,
|
||||
val samplingRateOverride: Float?, // this is FIXED sampling rate
|
||||
@@ -34,6 +36,15 @@ class MusicContainer(
|
||||
override var channels: Int
|
||||
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
|
||||
constructor(
|
||||
name: String,
|
||||
@@ -41,27 +52,37 @@ class MusicContainer(
|
||||
looping: Boolean = false,
|
||||
toRAM: Boolean = false,
|
||||
songFinishedHook: (AudioBank) -> Unit = {}
|
||||
) : this(name, file, looping, toRAM, null, songFinishedHook)
|
||||
) : this(name, file, null, looping, toRAM, null, songFinishedHook)
|
||||
// make Java code shorter
|
||||
constructor(
|
||||
name: String,
|
||||
file: File,
|
||||
looping: Boolean = false,
|
||||
songFinishedHook: (AudioBank) -> Unit = {}
|
||||
) : this(name, file, looping, false, null, songFinishedHook)
|
||||
) : this(name, file, null, looping, false, null, songFinishedHook)
|
||||
// make Java code shorter
|
||||
constructor(
|
||||
name: String,
|
||||
file: File,
|
||||
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
|
||||
override var totalSizeInSamples: 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
|
||||
|
||||
@@ -94,7 +115,10 @@ class MusicContainer(
|
||||
rate.toFloat()
|
||||
}
|
||||
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 header = bitstream.readFrame()
|
||||
val rate = header.sampleRate
|
||||
@@ -118,11 +142,22 @@ class MusicContainer(
|
||||
if (it.last() == "Music") it.dropLast(1).last() else it.last()
|
||||
}
|
||||
|
||||
totalSizeInSamples = when (gdxMusic) {
|
||||
is Wav.Music -> getWavFileSampleCount(file)
|
||||
is Ogg.Music -> getOggFileSampleCount(file)
|
||||
is Mp3.Music -> getMp3FileSampleCount(file)
|
||||
else -> Long.MAX_VALUE
|
||||
totalSizeInSamples = if (file != null) {
|
||||
when (gdxMusic) {
|
||||
is Wav.Music -> getWavFileSampleCount(file)
|
||||
is Ogg.Music -> getOggFileSampleCount(file)
|
||||
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
|
||||
|
||||
@@ -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
|
||||
fun equalInstance(other: Any?) = this.file.path == (other as MusicContainer).file.path && this.hash == (other as MusicContainer).hash
|
||||
private fun getOggFileSampleCountFromHandle(fh: FileHandle): Long {
|
||||
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() {
|
||||
gdxMusic.dispose()
|
||||
@@ -340,7 +430,10 @@ class MusicContainer(
|
||||
}
|
||||
|
||||
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) {
|
||||
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) ->
|
||||
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"
|
||||
|
||||
printdbg(this, "Loading console commands from '${packageConsole}'")
|
||||
// printdbg(this, commandsList.joinToString())
|
||||
|
||||
commandsList.forEach { commandName ->
|
||||
commandsList.filter { it.isNotBlank() }.forEach { commandName ->
|
||||
val canonicalName = "$packageConsole.$commandName"
|
||||
val it = ModMgr.moduleClassloader[modName].let {
|
||||
if (it != null)
|
||||
|
||||
@@ -15,7 +15,7 @@ object FactionFactory {
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
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"))
|
||||
|
||||
jsonObj.get("factionamicable").asStringArray().forEach { factionObj.addFactionAmicable(it) }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum.gamecontroller
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import net.torvald.terrarum.App
|
||||
@@ -173,8 +174,13 @@ object IME {
|
||||
else -> throw IllegalArgumentException("Unknown candidates mode: $this")
|
||||
}
|
||||
|
||||
fun parseKeylayoutFile(file: File): TerrarumKeyLayout {
|
||||
val src = file.readText(Charsets.UTF_8)
|
||||
fun parseKeylayoutFile(fileHandle: FileHandle): TerrarumKeyLayout =
|
||||
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 name = jsval.getMember("n").asString()
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -215,8 +219,13 @@ object IME {
|
||||
else -> throw IllegalArgumentException("Unknown operation mode: $this")
|
||||
}
|
||||
|
||||
fun parseImeFile(file: File): TerrarumIME {
|
||||
val code = file.readText(Charsets.UTF_8)
|
||||
fun parseImeFile(fileHandle: FileHandle): TerrarumIME =
|
||||
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 name = jsval.getMember("n").asString()
|
||||
val candidatesCount = jsval.getMember("v").asString().toViewCount()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.langpack
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
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) {
|
||||
val json = JsonFetcher(file)
|
||||
/*
|
||||
* Terrarum langpack JSON structure is:
|
||||
*
|
||||
* (root object)
|
||||
* "<<STRING ID>>" = "<<LOCALISED TEXT>>"
|
||||
*/
|
||||
//println(json.entrySet())
|
||||
JsonFetcher.forEachSiblings(json) { key, value ->
|
||||
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) {
|
||||
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 ->
|
||||
langpack.put(
|
||||
"${entry.getString("n")}_$lang",
|
||||
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 = ">>="
|
||||
|
||||
@@ -161,10 +161,10 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
|
||||
try {
|
||||
val file = ModMgr.getFile("basegame", "demoworld")
|
||||
val reader = java.io.FileReader(file)
|
||||
val fileHandle = ModMgr.getGdxFile("basegame", "demoworld")
|
||||
val reader = fileHandle.reader("UTF-8")
|
||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||
val world = ReadSimpleWorld(reader, file)
|
||||
val world = ReadSimpleWorld(reader, fileHandle.file())
|
||||
demoWorld = world
|
||||
demoWorld.worldTime.timeDelta = 30
|
||||
printdbg(this, "Demo world loaded")
|
||||
|
||||
@@ -46,7 +46,7 @@ object InstrumentLoader {
|
||||
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 masterSamplesR = FloatArray(masterFile.totalSizeInSamples.toInt())
|
||||
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 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,
|
||||
samplingRateOverride = 48000f * pitch
|
||||
)
|
||||
@@ -63,17 +63,17 @@ open class ActorPrimedBomb(
|
||||
private var explosionCalled = false
|
||||
|
||||
@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()
|
||||
}
|
||||
@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()
|
||||
}
|
||||
@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()
|
||||
}
|
||||
|
||||
@@ -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 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)))
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ class FixtureSmelterBasic : FixtureBase {
|
||||
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 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 {
|
||||
override fun use(item: ItemFileRef): Long {
|
||||
println(item.getAsFile().readText(Common.CHARSET))
|
||||
println(item.getAsGdxFile().readString(Common.CHARSET.displayName()))
|
||||
return 0L
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ object InjectCreatureRaw {
|
||||
* @param jsonFileName with extension
|
||||
*/
|
||||
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("_")) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.gameitems.GameItem
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
|
||||
@@ -42,7 +43,7 @@ open class ItemFileRef(originalID: ItemID) : GameItem(originalID) {
|
||||
*/
|
||||
open var refIsShared: Boolean = false
|
||||
|
||||
@Transient open lateinit var ref: File
|
||||
@Transient open lateinit var ref: FileHandle
|
||||
|
||||
/**
|
||||
* Application-defined.
|
||||
@@ -101,10 +102,10 @@ open class ItemFileRef(originalID: ItemID) : GameItem(originalID) {
|
||||
else
|
||||
ModMgr.getGdxFile(refModuleName, refPath)
|
||||
|
||||
fun getAsFile() = if (refIsShared)
|
||||
/*fun getAsFile() = if (refIsShared)
|
||||
File(App.saveSharedDir + "/$refPath")
|
||||
else
|
||||
ModMgr.getFile(refModuleName, refPath)
|
||||
ModMgr.getFile(refModuleName, refPath)*/
|
||||
|
||||
@Transient private var classCache: FileRefItemPrimaryUseHandler? = null
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ data class MusicDiscMetadata(val title: String, val author: String, val album: S
|
||||
object MusicDiscHelper {
|
||||
fun getMetadata(musicFile: FileHandle): MusicDiscMetadata {
|
||||
val musicdbFile = musicFile.sibling("_musicdb.json")
|
||||
val musicdb = JsonFetcher.invoke(musicdbFile.file())
|
||||
val musicdb = JsonFetcher.invoke(musicdbFile)
|
||||
val propForThisFile = musicdb.get(musicFile.name())
|
||||
|
||||
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 refModuleName = module
|
||||
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"
|
||||
|
||||
init {
|
||||
|
||||
@@ -273,7 +273,7 @@ object PickaxeCore : TooltipListener() {
|
||||
|
||||
private val soundCue = MusicContainer(
|
||||
"pickaxe_sound_cue",
|
||||
ModMgr.getFile("basegame", "audio/effects/accessibility/pickaxe_valuable.ogg"),
|
||||
ModMgr.getGdxFile("basegame", "audio/effects/accessibility/pickaxe_valuable.ogg"),
|
||||
toRAM = false
|
||||
).also {
|
||||
App.disposables.add(it)
|
||||
|
||||
@@ -30,7 +30,7 @@ class UIElemTest : ApplicationAdapter() {
|
||||
private lateinit var ui: UICanvas
|
||||
|
||||
override fun create() {
|
||||
App.fontGame = TerrarumSansBitmap(App.FONT_DIR, false, true, false,
|
||||
App.fontGame = TerrarumSansBitmap(false, true, false,
|
||||
false,
|
||||
256, false, 0.5f, false
|
||||
)
|
||||
|
||||
@@ -40,7 +40,10 @@ object CSVFetcher {
|
||||
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> {
|
||||
val preprocessed = preprocessCSV(csv)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.utils
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.utils.JsonReader
|
||||
import com.badlogic.gdx.utils.JsonValue
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
@@ -36,6 +37,13 @@ object JsonFetcher {
|
||||
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 {
|
||||
return JsonReader().parse(stringReader.readText())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.weather
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
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, fileHandle: FileHandle) {
|
||||
readFromJsonValue(modname, JsonFetcher.invoke(fileHandle))
|
||||
}
|
||||
|
||||
private val pathToImage = "weathers"
|
||||
|
||||
fun readFromJson(modname: String, path: String) {
|
||||
/* JSON structure:
|
||||
{
|
||||
"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)
|
||||
readFromJsonValue(modname, JsonFetcher(path))
|
||||
}
|
||||
|
||||
private fun readFromJsonValue(modname: String, JSON: com.badlogic.gdx.utils.JsonValue) {
|
||||
val skyboxModel = JSON.getString("skyboxGradColourMap")
|
||||
val lightboxModel = JSON.getString("daylightClut")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user