Objekte können jetzt Sounds haben (z.B. Lagerfeuer). Sound System optimiert
This commit is contained in:
@@ -28,6 +28,7 @@ public record ModelMeta(
|
||||
float cullDistance,
|
||||
List<AttachedLight> attachedLights,
|
||||
List<AttachedEmitter> attachedEmitters,
|
||||
List<AttachedSound> attachedSounds,
|
||||
de.blight.common.model.InteractableType interactableType,
|
||||
float interactableOffsetX,
|
||||
float interactableOffsetY,
|
||||
@@ -42,17 +43,51 @@ public record ModelMeta(
|
||||
float r, float g, float b,
|
||||
float intensity, float radius) {}
|
||||
|
||||
/** Partikel-Emitter relativ zum Modell-Ursprung. Preset: 0=Feuer, 1=Rauch, 2=Funken. */
|
||||
/** Sound-Quelle relativ zum Modell-Ursprung. */
|
||||
public record AttachedSound(
|
||||
float offsetX, float offsetY, float offsetZ,
|
||||
String soundPath,
|
||||
float volume,
|
||||
float radius) {}
|
||||
|
||||
/** Partikel-Emitter relativ zum Modell-Ursprung — vollständige Parameter wie PlacedEmitter. */
|
||||
public record AttachedEmitter(
|
||||
float offsetX, float offsetY, float offsetZ,
|
||||
int preset) {}
|
||||
String texturePath, int imagesX, int imagesY,
|
||||
float startR, float startG, float startB, float startA,
|
||||
float endR, float endG, float endB, float endA,
|
||||
float startSize, float endSize,
|
||||
float velX, float velY, float velZ, float velocityVariation,
|
||||
float gravX, float gravY, float gravZ,
|
||||
float lowLife, float highLife,
|
||||
int maxParticles, float emitRate) {
|
||||
|
||||
public static AttachedEmitter fire(float ox, float oy, float oz) {
|
||||
return new AttachedEmitter(ox, oy, oz,
|
||||
"Effects/Explosion/flame.png", 2, 2,
|
||||
1f, 0.7f, 0.1f, 1f, 1f, 0.1f, 0f, 0f,
|
||||
0.5f, 1.2f, 0f, 2.5f, 0f, 0.5f, 0f, -0.1f, 0f, 1f, 3f, 60, 25f);
|
||||
}
|
||||
public static AttachedEmitter smoke(float ox, float oy, float oz) {
|
||||
return new AttachedEmitter(ox, oy, oz,
|
||||
"Effects/Smoke/Smoke.png", 1, 1,
|
||||
0.5f, 0.5f, 0.5f, 0.4f, 0.2f, 0.2f, 0.2f, 0f,
|
||||
0.8f, 2.5f, 0f, 1.2f, 0f, 0.3f, 0f, 0.05f, 0f, 3f, 6f, 24, 6f);
|
||||
}
|
||||
public static AttachedEmitter sparks(float ox, float oy, float oz) {
|
||||
return new AttachedEmitter(ox, oy, oz,
|
||||
"Effects/Explosion/spark.png", 1, 1,
|
||||
1f, 0.9f, 0.2f, 1f, 1f, 0.3f, 0f, 0f,
|
||||
0.05f, 0.02f, 0f, 4f, 0f, 1.0f, 0f, -5f, 0f, 0.5f, 2f, 50, 20f);
|
||||
}
|
||||
}
|
||||
|
||||
public static ModelMeta defaults(String j3oFileName) {
|
||||
String name = j3oFileName.replaceFirst("\\.j3o$", "");
|
||||
return new ModelMeta(name, "", "", 1f, 1f, 1f, true, 0f, 0f,
|
||||
false, true, true, 1f, 1f,
|
||||
"", "", 30f, 80f, 120f,
|
||||
List.of(), List.of(),
|
||||
List.of(), List.of(), List.of(),
|
||||
de.blight.common.model.InteractableType.NONE,
|
||||
0f, 0.5f, 0f, 0f, "",
|
||||
de.blight.common.ModelCategory.NONE);
|
||||
|
||||
@@ -59,8 +59,27 @@ public final class ModelMetaIO {
|
||||
for (int i = 0; i < emitters.size(); i++) {
|
||||
ModelMeta.AttachedEmitter e = emitters.get(i);
|
||||
p.setProperty("attachedEmitter." + i, String.format(Locale.ROOT,
|
||||
"%.5f|%.5f|%.5f|%d",
|
||||
e.offsetX(), e.offsetY(), e.offsetZ(), e.preset()));
|
||||
"%.5f|%.5f|%.5f|%s|%d|%d|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%.4f|%d|%.4f",
|
||||
e.offsetX(), e.offsetY(), e.offsetZ(),
|
||||
e.texturePath(), e.imagesX(), e.imagesY(),
|
||||
e.startR(), e.startG(), e.startB(), e.startA(),
|
||||
e.endR(), e.endG(), e.endB(), e.endA(),
|
||||
e.startSize(), e.endSize(),
|
||||
e.velX(), e.velY(), e.velZ(), e.velocityVariation(),
|
||||
e.gravX(), e.gravY(), e.gravZ(),
|
||||
e.lowLife(), e.highLife(),
|
||||
e.maxParticles(), e.emitRate()));
|
||||
}
|
||||
|
||||
// Anhänge: Sounds
|
||||
List<ModelMeta.AttachedSound> sounds = m.attachedSounds();
|
||||
p.setProperty("attachedSounds.count", String.valueOf(sounds.size()));
|
||||
for (int i = 0; i < sounds.size(); i++) {
|
||||
ModelMeta.AttachedSound s = sounds.get(i);
|
||||
p.setProperty("attachedSound." + i, String.format(Locale.ROOT,
|
||||
"%.5f|%.5f|%.5f|%s|%.4f|%.4f",
|
||||
s.offsetX(), s.offsetY(), s.offsetZ(),
|
||||
s.soundPath(), s.volume(), s.radius()));
|
||||
}
|
||||
|
||||
try (Writer w = Files.newBufferedWriter(metaPath(j3oPath))) {
|
||||
@@ -103,11 +122,48 @@ public final class ModelMetaIO {
|
||||
String v = p.getProperty("attachedEmitter." + i, "");
|
||||
if (!v.isEmpty()) {
|
||||
String[] f = v.split("\\|", -1);
|
||||
if (f.length >= 4) {
|
||||
try {
|
||||
try {
|
||||
if (f.length >= 27) {
|
||||
// Neues Format mit vollständigen Parametern
|
||||
emitters.add(new ModelMeta.AttachedEmitter(
|
||||
Float.parseFloat(f[0]), Float.parseFloat(f[1]), Float.parseFloat(f[2]),
|
||||
Integer.parseInt(f[3])));
|
||||
f[3], Integer.parseInt(f[4]), Integer.parseInt(f[5]),
|
||||
Float.parseFloat(f[6]), Float.parseFloat(f[7]), Float.parseFloat(f[8]), Float.parseFloat(f[9]),
|
||||
Float.parseFloat(f[10]), Float.parseFloat(f[11]), Float.parseFloat(f[12]), Float.parseFloat(f[13]),
|
||||
Float.parseFloat(f[14]), Float.parseFloat(f[15]),
|
||||
Float.parseFloat(f[16]), Float.parseFloat(f[17]), Float.parseFloat(f[18]), Float.parseFloat(f[19]),
|
||||
Float.parseFloat(f[20]), Float.parseFloat(f[21]), Float.parseFloat(f[22]),
|
||||
Float.parseFloat(f[23]), Float.parseFloat(f[24]),
|
||||
Integer.parseInt(f[25]), Float.parseFloat(f[26])));
|
||||
} else if (f.length >= 4) {
|
||||
// Altes Format (offsetX|offsetY|offsetZ|preset) → Preset-Defaults übernehmen
|
||||
float ox = Float.parseFloat(f[0]);
|
||||
float oy = Float.parseFloat(f[1]);
|
||||
float oz = Float.parseFloat(f[2]);
|
||||
int preset = Integer.parseInt(f[3]);
|
||||
emitters.add(switch (preset) {
|
||||
case 1 -> ModelMeta.AttachedEmitter.smoke(ox, oy, oz);
|
||||
case 2 -> ModelMeta.AttachedEmitter.sparks(ox, oy, oz);
|
||||
default -> ModelMeta.AttachedEmitter.fire(ox, oy, oz);
|
||||
});
|
||||
}
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
// Anhänge: Sounds
|
||||
int soundCount = parseInt(p, "attachedSounds.count", 0);
|
||||
List<ModelMeta.AttachedSound> sounds = new ArrayList<>(soundCount);
|
||||
for (int i = 0; i < soundCount; i++) {
|
||||
String v = p.getProperty("attachedSound." + i, "");
|
||||
if (!v.isEmpty()) {
|
||||
String[] f = v.split("\\|", -1);
|
||||
if (f.length >= 6) {
|
||||
try {
|
||||
sounds.add(new ModelMeta.AttachedSound(
|
||||
Float.parseFloat(f[0]), Float.parseFloat(f[1]), Float.parseFloat(f[2]),
|
||||
f[3],
|
||||
Float.parseFloat(f[4]), Float.parseFloat(f[5])));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
}
|
||||
@@ -135,6 +191,7 @@ public final class ModelMetaIO {
|
||||
parseFloat(p, "cullDistance", 120f),
|
||||
Collections.unmodifiableList(lights),
|
||||
Collections.unmodifiableList(emitters),
|
||||
Collections.unmodifiableList(sounds),
|
||||
de.blight.common.model.InteractableType.fromString(
|
||||
p.getProperty("interactableType", "NONE")),
|
||||
parseFloat(p, "interactableOffsetX", 0f),
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.blight.common;
|
||||
|
||||
public record PlacedSound(
|
||||
float x, float y, float z,
|
||||
String soundPath,
|
||||
float volume,
|
||||
float radius
|
||||
) {}
|
||||
58
blight-common/src/main/java/de/blight/common/SoundIO.java
Normal file
58
blight-common/src/main/java/de/blight/common/SoundIO.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package de.blight.common;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Liest und schreibt platzierte Sound-Quellen als tab-separierte Textdatei
|
||||
* ({@code blight_sounds.bls}) neben der Kartendatei.
|
||||
*
|
||||
* Spalten: x y z soundPath volume radius
|
||||
*/
|
||||
public final class SoundIO {
|
||||
|
||||
private SoundIO() {}
|
||||
|
||||
public static Path getPath() {
|
||||
return MapIO.getMapPath().resolveSibling("blight_sounds.bls");
|
||||
}
|
||||
|
||||
public static void save(List<PlacedSound> sounds) throws IOException {
|
||||
Path p = getPath();
|
||||
Files.createDirectories(p.getParent());
|
||||
try (BufferedWriter w = Files.newBufferedWriter(p)) {
|
||||
w.write("# x\ty\tz\tsoundPath\tvolume\tradius");
|
||||
w.newLine();
|
||||
for (PlacedSound s : sounds) {
|
||||
w.write(String.format(Locale.ROOT,
|
||||
"%.5f\t%.5f\t%.5f\t%s\t%.4f\t%.4f%n",
|
||||
s.x(), s.y(), s.z(),
|
||||
s.soundPath(),
|
||||
s.volume(), s.radius()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<PlacedSound> load() throws IOException {
|
||||
Path p = getPath();
|
||||
if (!Files.exists(p)) return List.of();
|
||||
List<PlacedSound> list = new ArrayList<>();
|
||||
for (String line : Files.readAllLines(p)) {
|
||||
line = line.strip();
|
||||
if (line.isEmpty() || line.startsWith("#")) continue;
|
||||
String[] f = line.split("\t", -1);
|
||||
if (f.length < 6) continue;
|
||||
try {
|
||||
list.add(new PlacedSound(
|
||||
Float.parseFloat(f[0]),
|
||||
Float.parseFloat(f[1]),
|
||||
Float.parseFloat(f[2]),
|
||||
f[3],
|
||||
Float.parseFloat(f[4]),
|
||||
Float.parseFloat(f[5])));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user