Arbeiten aus dem URlaub

This commit is contained in:
2026-05-19 12:55:05 +02:00
parent b8a0234ad2
commit 4f48834e2c
403 changed files with 23402 additions and 6389 deletions

1
blight-common/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build/

View File

@@ -0,0 +1,20 @@
// Gemeinsames Datenmodell — wird von blight-editor und blight-game eingebunden.
// Selbst-ständig konfiguriert, damit es auch funktioniert wenn blight-editor
// oder blight-game standalone in Eclipse importiert werden (ohne Root-Build).
plugins {
id 'java'
}
group = 'de.blight'
version = '0.1.0'
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
compileJava.options.encoding = 'UTF-8'
repositories {
mavenCentral()
}

View File

@@ -0,0 +1,68 @@
package de.blight.common;
/**
* Serialisierbarer Zustand einer Blight-Weltkarte.
*
* Basis-Terrain : 4097 × 4097 Vertices (= 4096 × 4096 Zellen),
* 8 Welteinheiten pro Zelle → Welt 2048 .. +2048.
* Obere Schicht : 513 × 513 Vertices (= 512 × 512 Zellen), gleiche Weltausdehnung.
* Splatmap : 513 × 513 Pixel (passt auf Spiel-Terrain 1:1).
* Kanäle R/G/B = Gewicht für Tex2/Tex3/Tex4; Tex1 füllt den Rest.
*/
public final class MapData {
// ── Terrain-Konstanten ────────────────────────────────────────────────────
/** Vertices pro Achse des Basis-Terrains (muss 2^n + 1 sein). */
public static final int TERRAIN_VERTS = 4097;
// ── Upper-Layer-Konstanten ────────────────────────────────────────────────
/** Zellen pro Achse der oberen Schicht. */
public static final int UPPER_CELLS = 512;
/** Vertices pro Achse der oberen Schicht (UPPER_CELLS + 1). */
public static final int UPPER_VERTS = 513;
// ── Splatmap-Konstanten ────────────────────────────────────────────────────
/** Pixel pro Achse der Splatmap (entspricht UPPER_VERTS = Spiel-Terrain-Auflösung). */
public static final int SPLAT_SIZE = 513;
// ── Daten ─────────────────────────────────────────────────────────────────
/** Y-Höhe jedes Vertex im Basis-Terrain [TERRAIN_VERTS²]. */
public final float[] terrainHeight;
/** Y der oberen Oberfläche der Bergschicht [UPPER_VERTS²]. */
public final float[] upperTop;
/** Y der Höhlendecke [UPPER_VERTS²]. */
public final float[] upperBottom;
/** 1 = Loch (offen), 0 = massiv [UPPER_CELLS²]. */
public final byte[] upperHole;
/** Splatmap Rot-Kanal: Tex1-Helligkeit (Alpha.R), immer 255 [SPLAT_SIZE²]. */
public final byte[] splatR;
/** Splatmap Grün-Kanal: Tex2 (Fels) mix-Faktor (Alpha.G) [SPLAT_SIZE²], Bytes 0255. */
public final byte[] splatG;
/** Splatmap Blau-Kanal: Tex3 (Erde) mix-Faktor (Alpha.B) [SPLAT_SIZE²], Bytes 0255. */
public final byte[] splatB;
/** Gras-Dichte [SPLAT_SIZE²], Bytes 0255 (0=kein Gras, 255=max Dichte). */
public final byte[] grassDensity;
public MapData() {
terrainHeight = new float[TERRAIN_VERTS * TERRAIN_VERTS];
upperTop = new float[UPPER_VERTS * UPPER_VERTS];
upperBottom = new float[UPPER_VERTS * UPPER_VERTS];
upperHole = new byte [UPPER_CELLS * UPPER_CELLS];
splatR = new byte [SPLAT_SIZE * SPLAT_SIZE];
splatG = new byte [SPLAT_SIZE * SPLAT_SIZE];
splatB = new byte [SPLAT_SIZE * SPLAT_SIZE];
grassDensity = new byte [SPLAT_SIZE * SPLAT_SIZE];
}
}

View File

@@ -0,0 +1,102 @@
package de.blight.common;
import java.io.*;
import java.nio.*;
import java.nio.file.*;
import java.util.zip.*;
/**
* Liest und schreibt {@link MapData} als komprimierte Binärdatei.
*
* Speicherort: {@code world/blight_map.blm} relativ zum Arbeitsverzeichnis.
* Beide Projekte setzen {@code workingDir = rootDir} im Gradle-Run-Task,
* zeigen also auf dasselbe Verzeichnis.
*
* Versionen:
* 1 Basis-Terrain + Obere Schicht (kein Splatmap)
* 2 wie 1 + Splatmap (R/G/B je 513×513 Bytes)
* 3 wie 2 + Gras-Dichte (513×513 Bytes)
*/
public final class MapIO {
private static final Path MAP_PATH = Paths.get("world", "blight_map.blm");
private static final int MAGIC = 0x424C4947; // "BLIG"
private static final int VERSION = 3;
private MapIO() {}
// ── Public API ────────────────────────────────────────────────────────────
public static boolean exists() {
return Files.exists(MAP_PATH);
}
public static Path getMapPath() {
return MAP_PATH.toAbsolutePath();
}
public static void save(MapData data) throws IOException {
Files.createDirectories(MAP_PATH.getParent());
try (DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new GZIPOutputStream(Files.newOutputStream(MAP_PATH))))) {
out.writeInt(MAGIC);
out.writeInt(VERSION);
writeFloats(out, data.terrainHeight);
writeFloats(out, data.upperTop);
writeFloats(out, data.upperBottom);
out.write(data.upperHole);
// v2: splatmap
out.write(data.splatR);
out.write(data.splatG);
out.write(data.splatB);
// v3: gras-dichte
out.write(data.grassDensity);
}
}
public static MapData load() throws IOException {
MapData data = new MapData();
try (DataInputStream in = new DataInputStream(
new BufferedInputStream(
new GZIPInputStream(Files.newInputStream(MAP_PATH))))) {
int magic = in.readInt();
int version = in.readInt();
if (magic != MAGIC) throw new IOException("Ungültige Map-Datei (falscher Magic)");
if (version < 1 || version > VERSION)
throw new IOException("Unbekannte Map-Version: " + version);
readFloats(in, data.terrainHeight);
readFloats(in, data.upperTop);
readFloats(in, data.upperBottom);
in.readFully(data.upperHole);
if (version >= 2) {
in.readFully(data.splatR);
in.readFully(data.splatG);
in.readFully(data.splatB);
}
if (version >= 3) {
in.readFully(data.grassDensity);
}
// version 1/2: grassDensity stays all-zeros (= kein Gras)
}
return data;
}
// ── Hilfsmethoden ─────────────────────────────────────────────────────────
private static void writeFloats(DataOutputStream out, float[] arr) throws IOException {
ByteBuffer buf = ByteBuffer.allocate(arr.length * Float.BYTES)
.order(ByteOrder.BIG_ENDIAN);
buf.asFloatBuffer().put(arr);
out.write(buf.array());
}
private static void readFloats(DataInputStream in, float[] arr) throws IOException {
byte[] bytes = new byte[arr.length * Float.BYTES];
in.readFully(bytes);
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asFloatBuffer().get(arr);
}
}