Weitere Anpassungen bezüglich der Voxel und des Zoning Systems
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package de.blight.common;
|
||||
|
||||
public record AreaDefinition(
|
||||
String id,
|
||||
String dayTrack,
|
||||
String nightTrack,
|
||||
String combatTrack
|
||||
) {
|
||||
public String nameKey() { return id.isBlank() ? "" : id + ".name"; }
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package de.blight.common;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
|
||||
public final class AreaDefinitionIO {
|
||||
|
||||
private AreaDefinitionIO() {}
|
||||
|
||||
public static Path getPath() {
|
||||
return MapIO.getMapPath().resolveSibling("blight_area_definitions.bad");
|
||||
}
|
||||
|
||||
public static void save(List<AreaDefinition> defs) throws IOException {
|
||||
Path p = getPath();
|
||||
Files.createDirectories(p.getParent());
|
||||
try (BufferedWriter w = Files.newBufferedWriter(p)) {
|
||||
w.write("# id\tdayTrack\tnightTrack\tcombatTrack");
|
||||
w.newLine();
|
||||
for (AreaDefinition d : defs) {
|
||||
w.write(d.id());
|
||||
w.write('\t');
|
||||
w.write(d.dayTrack());
|
||||
w.write('\t');
|
||||
w.write(d.nightTrack());
|
||||
w.write('\t');
|
||||
w.write(d.combatTrack());
|
||||
w.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<AreaDefinition> load() throws IOException {
|
||||
Path p = getPath();
|
||||
if (!Files.exists(p)) return List.of();
|
||||
List<AreaDefinition> list = new ArrayList<>();
|
||||
for (String line : Files.readAllLines(p)) {
|
||||
line = line.stripLeading();
|
||||
if (line.isEmpty() || line.startsWith("#")) continue;
|
||||
String[] f = line.split("\t", -1);
|
||||
if (f.length < 4) continue;
|
||||
list.add(new AreaDefinition(f[0].strip(), f[1].strip(), f[2].strip(), f[3].strip()));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package de.blight.common;
|
||||
|
||||
import de.blight.common.model.trigger.Trigger;
|
||||
import de.blight.common.model.trigger.TriggerIO;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
@@ -16,18 +19,14 @@ public final class AreaIO {
|
||||
Path p = getPath();
|
||||
Files.createDirectories(p.getParent());
|
||||
try (BufferedWriter w = Files.newBufferedWriter(p)) {
|
||||
w.write("# polygon\tnameId\tdayTrack\tnightTrack\tcombatTrack");
|
||||
w.write("# polygon\tareaId\ttriggersJson");
|
||||
w.newLine();
|
||||
for (PlacedArea a : areas) {
|
||||
w.write(SoundAreaIO.encodePolygon(a.pointsX(), a.pointsZ()));
|
||||
w.write('\t');
|
||||
w.write(a.nameId());
|
||||
w.write(a.areaId());
|
||||
w.write('\t');
|
||||
w.write(a.dayTrack());
|
||||
w.write('\t');
|
||||
w.write(a.nightTrack());
|
||||
w.write('\t');
|
||||
w.write(a.combatTrack());
|
||||
w.write(TriggerIO.serializeList(a.triggers()));
|
||||
w.newLine();
|
||||
}
|
||||
}
|
||||
@@ -38,14 +37,16 @@ public final class AreaIO {
|
||||
if (!Files.exists(p)) return List.of();
|
||||
List<PlacedArea> list = new ArrayList<>();
|
||||
for (String line : Files.readAllLines(p)) {
|
||||
line = line.strip();
|
||||
line = line.stripLeading();
|
||||
if (line.isEmpty() || line.startsWith("#")) continue;
|
||||
String[] f = line.split("\t", -1);
|
||||
if (f.length < 5) continue;
|
||||
if (f.length < 1) continue;
|
||||
try {
|
||||
float[][] pts = SoundAreaIO.decodePolygon(f[0]);
|
||||
if (pts[0].length < 3) continue;
|
||||
list.add(new PlacedArea(pts[0], pts[1], f[1], f[2], f[3], f[4]));
|
||||
String areaId = f.length > 1 ? f[1].strip() : "";
|
||||
List<Trigger> triggers = f.length > 2 ? TriggerIO.deserializeList(f[2]) : new ArrayList<>();
|
||||
list.add(new PlacedArea(pts[0], pts[1], areaId, triggers));
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
return list;
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package de.blight.common;
|
||||
|
||||
import de.blight.common.model.trigger.Trigger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record PlacedArea(
|
||||
float[] pointsX,
|
||||
float[] pointsZ,
|
||||
String nameId,
|
||||
String dayTrack,
|
||||
String nightTrack,
|
||||
String combatTrack
|
||||
) {}
|
||||
String areaId,
|
||||
List<Trigger> triggers
|
||||
) {
|
||||
public PlacedArea(float[] pointsX, float[] pointsZ, String areaId) {
|
||||
this(pointsX, pointsZ, areaId, List.of());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,6 @@ public class Location {
|
||||
public void entered(MainCharacter character) {
|
||||
triggers.stream()
|
||||
.filter(t -> t.isTriggarable(character))
|
||||
.forEach(t -> t.trigger(character));
|
||||
.forEach(t -> t.fire(character));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@ package de.blight.common.model;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.blight.common.model.quests.Quest;
|
||||
import lombok.AccessLevel;
|
||||
@@ -44,6 +47,18 @@ public class MainCharacter extends GameCharacter {
|
||||
/** Gespielte Monolog-IDs – wird serialisiert, damit jeder Monolog nur einmal abgespielt wird. */
|
||||
private Set<String> playedMonologueIds = new HashSet<>();
|
||||
|
||||
/** IDs bereits gefeuerter Trigger – verhindert Mehrfach-Auslösung. */
|
||||
private Set<String> firedTriggerIds = new HashSet<>();
|
||||
|
||||
/** Bereits betretene Zonen (für FirstTimeCondition). */
|
||||
private Set<String> visitedZoneIds = new HashSet<>();
|
||||
|
||||
/** Freie Spielvariablen (key→value) für GameVariableCondition. */
|
||||
private Map<String, String> gameVariables = new HashMap<>();
|
||||
|
||||
/** Fraktionen, denen der Spieler angehört (für FactionMemberCondition). */
|
||||
private Set<UUID> memberFractionIds = new HashSet<>();
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
@Setter(AccessLevel.NONE)
|
||||
private List<CharacterListener> listeners = new ArrayList<CharacterListener>();
|
||||
@@ -52,6 +67,11 @@ public class MainCharacter extends GameCharacter {
|
||||
@Getter(AccessLevel.NONE)
|
||||
@Setter(AccessLevel.NONE)
|
||||
private transient Queue<Monologue> pendingMonologues = new ArrayDeque<>();
|
||||
|
||||
/** Warteschlange für per Trigger ausgelöste NPC-Dialoge – wird NICHT serialisiert. */
|
||||
@Getter(AccessLevel.NONE)
|
||||
@Setter(AccessLevel.NONE)
|
||||
private transient Queue<String> pendingDialogNpcIds = new ArrayDeque<>();
|
||||
|
||||
public void handleDialogOption(DialogOption option) {
|
||||
if (option.getRequiredItem() != null) {
|
||||
@@ -146,6 +166,37 @@ public class MainCharacter extends GameCharacter {
|
||||
return pendingMonologues.poll();
|
||||
}
|
||||
|
||||
/** Stellt einen per Trigger ausgelösten NPC-Dialog in die Warteschlange. */
|
||||
public void queueDialog(String npcId) {
|
||||
if (pendingDialogNpcIds == null) pendingDialogNpcIds = new ArrayDeque<>();
|
||||
pendingDialogNpcIds.offer(npcId);
|
||||
}
|
||||
|
||||
/** Gibt den nächsten ausstehenden Dialog-NPC zurück oder null. */
|
||||
public String pollPendingDialog() {
|
||||
if (pendingDialogNpcIds == null) return null;
|
||||
return pendingDialogNpcIds.poll();
|
||||
}
|
||||
|
||||
public boolean isQuestCompleted(String questId) {
|
||||
return completedQuests != null && completedQuests.stream()
|
||||
.anyMatch(q -> questId.equals(q.getQuestId()));
|
||||
}
|
||||
|
||||
public boolean isQuestAccepted(String questId) {
|
||||
return openQuests != null && openQuests.stream()
|
||||
.anyMatch(q -> questId.equals(q.getQuestId()));
|
||||
}
|
||||
|
||||
public boolean isQuestRejected(String questId) {
|
||||
return abortedQuests != null && abortedQuests.stream()
|
||||
.anyMatch(q -> questId.equals(q.getQuestId()));
|
||||
}
|
||||
|
||||
public boolean isFactionMember(UUID fractionId) {
|
||||
return memberFractionIds != null && memberFractionIds.contains(fractionId);
|
||||
}
|
||||
|
||||
/** Wendet die Quest-Folgen eines Monologs an. */
|
||||
public void handleMonologue(Monologue m) {
|
||||
if (m.getRecievesQuest() != null) startQuest(m.getRecievesQuest());
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ChapterCondition extends Condition {
|
||||
private int minChapter;
|
||||
|
||||
@Override
|
||||
public boolean evaluate(MainCharacter character) {
|
||||
return character.getChapter() >= minChapter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
|
||||
public abstract class Condition {
|
||||
public abstract boolean evaluate(MainCharacter character);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
public enum ConditionMode { ALL, ANY }
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class FactionMemberCondition extends Condition {
|
||||
private UUID fractionId;
|
||||
|
||||
@Override
|
||||
public boolean evaluate(MainCharacter character) {
|
||||
if (fractionId == null) return false;
|
||||
return character.isFactionMember(fractionId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class FirstTimeCondition extends Condition {
|
||||
private String zoneId;
|
||||
|
||||
@Override
|
||||
public boolean evaluate(MainCharacter character) {
|
||||
return zoneId != null && !character.getVisitedZoneIds().contains(zoneId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class GameVariableCondition extends Condition {
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
@Override
|
||||
public boolean evaluate(MainCharacter character) {
|
||||
if (key == null || key.isBlank()) return false;
|
||||
String actual = character.getGameVariables().get(key);
|
||||
if (value == null || value.isBlank()) return actual != null;
|
||||
return value.equals(actual);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class NpcDialogTrigger extends Trigger {
|
||||
private String npcId;
|
||||
|
||||
@Override
|
||||
public boolean isTriggarableDelegate(MainCharacter character) {
|
||||
return npcId != null && !npcId.isBlank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trigger(MainCharacter character) {
|
||||
if (npcId != null && !npcId.isBlank()) {
|
||||
character.queueDialog(npcId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QuestAcceptedCondition extends Condition {
|
||||
private String questId;
|
||||
|
||||
@Override
|
||||
public boolean evaluate(MainCharacter character) {
|
||||
return questId != null && character.isQuestAccepted(questId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QuestCompletedCondition extends Condition {
|
||||
private String questId;
|
||||
|
||||
@Override
|
||||
public boolean evaluate(MainCharacter character) {
|
||||
return questId != null && character.isQuestCompleted(questId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.blight.common.model.trigger;
|
||||
|
||||
import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QuestRejectedCondition extends Condition {
|
||||
private String questId;
|
||||
|
||||
@Override
|
||||
public boolean evaluate(MainCharacter character) {
|
||||
return questId != null && character.isQuestRejected(questId);
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,38 @@ import de.blight.common.model.MainCharacter;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class Trigger {
|
||||
|
||||
private int requiresChapter;
|
||||
|
||||
public boolean isTriggarable(MainCharacter character) {
|
||||
return character.getChapter() >= requiresChapter && isTriggarableDelegate(character);
|
||||
}
|
||||
|
||||
public abstract boolean isTriggarableDelegate(MainCharacter character);
|
||||
private String triggerId = UUID.randomUUID().toString();
|
||||
private int requiresChapter;
|
||||
private ConditionMode conditionMode = ConditionMode.ALL;
|
||||
private List<Condition> conditions = new ArrayList<>();
|
||||
|
||||
public abstract void trigger(MainCharacter character);
|
||||
public boolean isTriggarable(MainCharacter character) {
|
||||
if (triggerId != null && character.getFiredTriggerIds().contains(triggerId)) return false;
|
||||
if (character.getChapter() < requiresChapter) return false;
|
||||
if (!conditions.isEmpty()) {
|
||||
if (conditionMode == ConditionMode.ALL) {
|
||||
if (!conditions.stream().allMatch(c -> c.evaluate(character))) return false;
|
||||
} else {
|
||||
if (conditions.stream().noneMatch(c -> c.evaluate(character))) return false;
|
||||
}
|
||||
}
|
||||
return isTriggarableDelegate(character);
|
||||
}
|
||||
|
||||
public final void fire(MainCharacter character) {
|
||||
trigger(character);
|
||||
if (triggerId != null) character.getFiredTriggerIds().add(triggerId);
|
||||
}
|
||||
|
||||
public abstract boolean isTriggarableDelegate(MainCharacter character);
|
||||
|
||||
public abstract void trigger(MainCharacter character);
|
||||
}
|
||||
|
||||
@@ -9,19 +9,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Gson-Serialisierung für {@link Trigger}-Instanzen mit Typ-Diskriminator.
|
||||
*
|
||||
* JSON-Format (kompakt, kein Pretty-Print für Inline-Verwendung in z. B. LocationZoneIO):
|
||||
* {@code [{"type":"QUEST_START","requiresChapter":0,"questId":"my_quest"}, ...]}
|
||||
*
|
||||
* Bekannte Typen:
|
||||
* <ul>
|
||||
* <li>{@code QUEST_START} → {@link QuestStartTrigger}</li>
|
||||
* <li>{@code NPC_STATUS} → {@link NpcStatusTrigger}</li>
|
||||
* <li>{@code FRACTION_STATUS} → {@link FractionStatusTrigger}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class TriggerIO {
|
||||
|
||||
public static final String TYPE_QUEST_START = "QUEST_START";
|
||||
@@ -29,6 +16,7 @@ public final class TriggerIO {
|
||||
public static final String TYPE_FRACTION_STATUS = "FRACTION_STATUS";
|
||||
public static final String TYPE_CHANGE_ROUTINE = "CHANGE_ROUTINE";
|
||||
public static final String TYPE_MONOLOGUE = "MONOLOGUE";
|
||||
public static final String TYPE_NPC_DIALOG = "NPC_DIALOG";
|
||||
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.registerTypeHierarchyAdapter(Trigger.class, new TriggerAdapter())
|
||||
@@ -36,18 +24,15 @@ public final class TriggerIO {
|
||||
|
||||
private TriggerIO() {}
|
||||
|
||||
/** Registriert den Trigger-Typ-Adapter an einem GsonBuilder (für andere Module). */
|
||||
public static GsonBuilder registerAdapters(GsonBuilder builder) {
|
||||
return builder.registerTypeHierarchyAdapter(Trigger.class, new TriggerAdapter());
|
||||
}
|
||||
|
||||
/** Serialisiert eine Trigger-Liste als kompaktes JSON (kein Zeilenumbruch). */
|
||||
public static String serializeList(List<Trigger> triggers) {
|
||||
if (triggers == null || triggers.isEmpty()) return "[]";
|
||||
return GSON.toJson(triggers);
|
||||
}
|
||||
|
||||
/** Deserialisiert eine Trigger-Liste aus JSON. Gibt leere Liste bei Fehler zurück. */
|
||||
public static List<Trigger> deserializeList(String json) {
|
||||
if (json == null || json.isBlank() || "[]".equals(json.strip())) return new ArrayList<>();
|
||||
try {
|
||||
@@ -71,7 +56,13 @@ public final class TriggerIO {
|
||||
public JsonElement serialize(Trigger src, Type typeOfSrc, JsonSerializationContext ctx) {
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("type", typeOf(src));
|
||||
if (src.getTriggerId() != null) obj.addProperty("triggerId", src.getTriggerId());
|
||||
obj.addProperty("requiresChapter", src.getRequiresChapter());
|
||||
obj.addProperty("conditionMode", src.getConditionMode().name());
|
||||
|
||||
JsonArray condArr = new JsonArray();
|
||||
for (Condition c : src.getConditions()) condArr.add(serializeCondition(c));
|
||||
obj.add("conditions", condArr);
|
||||
|
||||
if (src instanceof QuestStartTrigger q) {
|
||||
if (q.getQuest() != null && q.getQuest().getQuestId() != null)
|
||||
@@ -86,10 +77,12 @@ public final class TriggerIO {
|
||||
if (f.getTargetStatus() != null)
|
||||
obj.addProperty("targetStatus", f.getTargetStatus().name());
|
||||
} else if (src instanceof ChangeRoutineTrigger r) {
|
||||
if (r.getNpcId() != null) obj.addProperty("npcId", r.getNpcId());
|
||||
if (r.getNpcId() != null) obj.addProperty("npcId", r.getNpcId());
|
||||
if (r.getRoutineName() != null) obj.addProperty("routineName", r.getRoutineName());
|
||||
} else if (src instanceof MonologueTrigger mo) {
|
||||
if (mo.getMonologueId() != null) obj.addProperty("monologueId", mo.getMonologueId());
|
||||
} else if (src instanceof NpcDialogTrigger nd) {
|
||||
if (nd.getNpcId() != null) obj.addProperty("npcId", nd.getNpcId());
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@@ -136,20 +129,117 @@ public final class TriggerIO {
|
||||
if (obj.has("monologueId")) mo.setMonologueId(obj.get("monologueId").getAsString());
|
||||
yield mo;
|
||||
}
|
||||
case TYPE_NPC_DIALOG -> {
|
||||
NpcDialogTrigger nd = new NpcDialogTrigger();
|
||||
if (obj.has("npcId")) nd.setNpcId(obj.get("npcId").getAsString());
|
||||
yield nd;
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
|
||||
if (t != null && obj.has("requiresChapter"))
|
||||
t.setRequiresChapter(obj.get("requiresChapter").getAsInt());
|
||||
if (t == null) return null;
|
||||
if (obj.has("triggerId")) t.setTriggerId(obj.get("triggerId").getAsString());
|
||||
if (obj.has("requiresChapter")) t.setRequiresChapter(obj.get("requiresChapter").getAsInt());
|
||||
if (obj.has("conditionMode")) {
|
||||
try { t.setConditionMode(ConditionMode.valueOf(obj.get("conditionMode").getAsString())); }
|
||||
catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
if (obj.has("conditions")) {
|
||||
List<Condition> conds = new ArrayList<>();
|
||||
for (JsonElement el : obj.getAsJsonArray("conditions")) {
|
||||
Condition c = deserializeCondition(el.getAsJsonObject());
|
||||
if (c != null) conds.add(c);
|
||||
}
|
||||
t.setConditions(conds);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
// ── Condition helpers ─────────────────────────────────────────────────
|
||||
|
||||
private static JsonObject serializeCondition(Condition c) {
|
||||
JsonObject o = new JsonObject();
|
||||
if (c instanceof ChapterCondition cc) {
|
||||
o.addProperty("type", "CHAPTER");
|
||||
o.addProperty("minChapter", cc.getMinChapter());
|
||||
} else if (c instanceof FirstTimeCondition ft) {
|
||||
o.addProperty("type", "FIRST_TIME");
|
||||
if (ft.getZoneId() != null) o.addProperty("zoneId", ft.getZoneId());
|
||||
} else if (c instanceof QuestCompletedCondition qc) {
|
||||
o.addProperty("type", "QUEST_COMPLETED");
|
||||
if (qc.getQuestId() != null) o.addProperty("questId", qc.getQuestId());
|
||||
} else if (c instanceof QuestAcceptedCondition qa) {
|
||||
o.addProperty("type", "QUEST_ACCEPTED");
|
||||
if (qa.getQuestId() != null) o.addProperty("questId", qa.getQuestId());
|
||||
} else if (c instanceof QuestRejectedCondition qr) {
|
||||
o.addProperty("type", "QUEST_REJECTED");
|
||||
if (qr.getQuestId() != null) o.addProperty("questId", qr.getQuestId());
|
||||
} else if (c instanceof GameVariableCondition gv) {
|
||||
o.addProperty("type", "GAME_VARIABLE");
|
||||
if (gv.getKey() != null) o.addProperty("key", gv.getKey());
|
||||
if (gv.getValue() != null) o.addProperty("value", gv.getValue());
|
||||
} else if (c instanceof FactionMemberCondition fm) {
|
||||
o.addProperty("type", "FACTION_MEMBER");
|
||||
if (fm.getFractionId() != null) o.addProperty("fractionId", fm.getFractionId().toString());
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
private static Condition deserializeCondition(JsonObject o) {
|
||||
String type = o.has("type") ? o.get("type").getAsString() : "";
|
||||
return switch (type) {
|
||||
case "CHAPTER" -> {
|
||||
ChapterCondition c = new ChapterCondition();
|
||||
if (o.has("minChapter")) c.setMinChapter(o.get("minChapter").getAsInt());
|
||||
yield c;
|
||||
}
|
||||
case "FIRST_TIME" -> {
|
||||
FirstTimeCondition c = new FirstTimeCondition();
|
||||
if (o.has("zoneId")) c.setZoneId(o.get("zoneId").getAsString());
|
||||
yield c;
|
||||
}
|
||||
case "QUEST_COMPLETED" -> {
|
||||
QuestCompletedCondition c = new QuestCompletedCondition();
|
||||
if (o.has("questId")) c.setQuestId(o.get("questId").getAsString());
|
||||
yield c;
|
||||
}
|
||||
case "QUEST_ACCEPTED" -> {
|
||||
QuestAcceptedCondition c = new QuestAcceptedCondition();
|
||||
if (o.has("questId")) c.setQuestId(o.get("questId").getAsString());
|
||||
yield c;
|
||||
}
|
||||
case "QUEST_REJECTED" -> {
|
||||
QuestRejectedCondition c = new QuestRejectedCondition();
|
||||
if (o.has("questId")) c.setQuestId(o.get("questId").getAsString());
|
||||
yield c;
|
||||
}
|
||||
case "GAME_VARIABLE" -> {
|
||||
GameVariableCondition c = new GameVariableCondition();
|
||||
if (o.has("key")) c.setKey(o.get("key").getAsString());
|
||||
if (o.has("value")) c.setValue(o.get("value").getAsString());
|
||||
yield c;
|
||||
}
|
||||
case "FACTION_MEMBER" -> {
|
||||
FactionMemberCondition c = new FactionMemberCondition();
|
||||
if (o.has("fractionId")) {
|
||||
try { c.setFractionId(UUID.fromString(o.get("fractionId").getAsString())); }
|
||||
catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
yield c;
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
// ── Type helpers ──────────────────────────────────────────────────────
|
||||
|
||||
private static String typeOf(Trigger t) {
|
||||
if (t instanceof QuestStartTrigger) return TYPE_QUEST_START;
|
||||
if (t instanceof NpcStatusTrigger) return TYPE_NPC_STATUS;
|
||||
if (t instanceof FractionStatusTrigger) return TYPE_FRACTION_STATUS;
|
||||
if (t instanceof ChangeRoutineTrigger) return TYPE_CHANGE_ROUTINE;
|
||||
if (t instanceof MonologueTrigger) return TYPE_MONOLOGUE;
|
||||
if (t instanceof NpcDialogTrigger) return TYPE_NPC_DIALOG;
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user