212 lines
7.4 KiB
Java
212 lines
7.4 KiB
Java
package com.hypixel.hytale.server.worldgen.chunk;
|
|
|
|
import com.hypixel.hytale.common.map.IWeightedMap;
|
|
import com.hypixel.hytale.logger.HytaleLogger;
|
|
import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.IPrefabBuffer;
|
|
import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.PrefabBuffer;
|
|
import com.hypixel.hytale.server.worldgen.biome.Biome;
|
|
import com.hypixel.hytale.server.worldgen.cave.CaveNodeType;
|
|
import com.hypixel.hytale.server.worldgen.cave.CaveType;
|
|
import com.hypixel.hytale.server.worldgen.cave.prefab.CavePrefabContainer;
|
|
import com.hypixel.hytale.server.worldgen.container.PrefabContainer;
|
|
import com.hypixel.hytale.server.worldgen.loader.WorldGenPrefabLoader;
|
|
import com.hypixel.hytale.server.worldgen.loader.WorldGenPrefabSupplier;
|
|
import com.hypixel.hytale.server.worldgen.prefab.unique.UniquePrefabGenerator;
|
|
import com.hypixel.hytale.server.worldgen.util.LogUtil;
|
|
import com.hypixel.hytale.server.worldgen.zone.Zone;
|
|
import com.hypixel.hytale.server.worldgen.zone.ZonePatternProvider;
|
|
import java.util.ArrayDeque;
|
|
import java.util.Deque;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.logging.Level;
|
|
import javax.annotation.Nonnull;
|
|
|
|
public class ValidationUtil {
|
|
public static boolean isInvalid(@Nonnull ZonePatternProvider zonePatternProvider, @Nonnull Executor executor) {
|
|
return CompletableFuture.<Boolean>supplyAsync(() -> {
|
|
Deque<String> trace = new ArrayDeque<>();
|
|
boolean invalid = false;
|
|
|
|
for (Zone zone : zonePatternProvider.getZones()) {
|
|
trace.push("Zone[\"" + zone.name() + "\"]");
|
|
|
|
try {
|
|
invalid |= isZoneInvalid(zone, trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
|
|
return invalid;
|
|
}, executor).join();
|
|
}
|
|
|
|
private static boolean isZoneInvalid(@Nonnull Zone zone, @Nonnull Deque<String> trace) {
|
|
boolean invalid = false;
|
|
|
|
for (UniquePrefabGenerator uniquePrefabGenerator : zone.uniquePrefabContainer().getGenerators()) {
|
|
trace.push("UniquePrefabs[\"" + uniquePrefabGenerator.getName() + "\"]");
|
|
|
|
try {
|
|
invalid |= arePrefabsInvalid(uniquePrefabGenerator.getPrefabs(), trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
|
|
for (Biome biome : zone.biomePatternGenerator().getBiomes()) {
|
|
trace.push("Biome[\"" + biome.getName() + "\"]");
|
|
|
|
try {
|
|
invalid |= isBiomeInvalid(biome, trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
|
|
if (zone.caveGenerator() != null) {
|
|
for (CaveType caveType : zone.caveGenerator().getCaveTypes()) {
|
|
trace.push("Cave[\"" + caveType.getName() + "\"].Entry");
|
|
|
|
try {
|
|
Set<String> encounteredNodes = new HashSet<>();
|
|
invalid |= isCaveNodeInvalid(caveType.getEntryNode(), encounteredNodes, trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
return invalid;
|
|
}
|
|
|
|
private static boolean isBiomeInvalid(@Nonnull Biome biome, @Nonnull Deque<String> trace) {
|
|
boolean invalid = false;
|
|
if (biome.getPrefabContainer() != null) {
|
|
PrefabContainer.PrefabContainerEntry[] prefabContainerEntries = biome.getPrefabContainer().getEntries();
|
|
|
|
for (int i = 0; i < prefabContainerEntries.length; i++) {
|
|
trace.push("Prefabs[" + i + "]");
|
|
|
|
try {
|
|
invalid |= arePrefabsInvalid(prefabContainerEntries[i].getPrefabs(), trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
return invalid;
|
|
}
|
|
|
|
private static boolean isCaveNodeInvalid(@Nonnull CaveNodeType caveNodeType, @Nonnull Set<String> encounteredNodes, @Nonnull Deque<String> trace) {
|
|
if (!encounteredNodes.add(caveNodeType.getName())) {
|
|
return false;
|
|
} else {
|
|
boolean invalid = false;
|
|
if (caveNodeType.getPrefabContainer() != null) {
|
|
CavePrefabContainer.CavePrefabEntry[] cavePrefabEntries = caveNodeType.getPrefabContainer().getEntries();
|
|
|
|
for (int i = 0; i < cavePrefabEntries.length; i++) {
|
|
trace.push("Prefabs[" + i + "]");
|
|
|
|
try {
|
|
invalid |= arePrefabsInvalid(cavePrefabEntries[i].getPrefabs(), trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
CaveNodeType.CaveNodeChildEntry[] children = caveNodeType.getChildren();
|
|
|
|
for (int i = 0; i < children.length; i++) {
|
|
CaveNodeType[] nodes = children[i].getTypes().internalKeys();
|
|
|
|
for (int n = 0; n < nodes.length; n++) {
|
|
trace.push("Children[" + i + "].Node[" + n + "]");
|
|
|
|
try {
|
|
invalid |= isCaveNodeInvalid(nodes[n], encounteredNodes, trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
return invalid;
|
|
}
|
|
}
|
|
|
|
private static boolean arePrefabsInvalid(@Nonnull IWeightedMap<WorldGenPrefabSupplier> prefabs, @Nonnull Deque<String> trace) {
|
|
boolean invalid = false;
|
|
WorldGenPrefabSupplier[] suppliers = prefabs.internalKeys();
|
|
|
|
for (int i = 0; i < suppliers.length; i++) {
|
|
trace.push("Prefabs[" + i + "]");
|
|
|
|
try {
|
|
IPrefabBuffer prefab;
|
|
try {
|
|
prefab = suppliers[i].get();
|
|
} catch (Throwable var27) {
|
|
invalid = true;
|
|
((HytaleLogger.Api)LogUtil.getLogger().at(Level.SEVERE).withCause(var27))
|
|
.log("Failed to load prefab: %s loaded from %s", suppliers[i].getName(), String.join(".", trace));
|
|
continue;
|
|
}
|
|
|
|
trace.push("{" + suppliers[i].getName() + "}");
|
|
|
|
try {
|
|
for (PrefabBuffer.ChildPrefab childMarker : prefab.getChildPrefabs()) {
|
|
trace.push("(" + childMarker.getX() + "," + childMarker.getY() + "," + childMarker.getZ() + ")");
|
|
|
|
try {
|
|
invalid |= isChildPrefabInvalid(childMarker, suppliers[i].getLoader(), trace);
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
} finally {
|
|
trace.pop();
|
|
}
|
|
}
|
|
|
|
return invalid;
|
|
}
|
|
|
|
private static boolean isChildPrefabInvalid(
|
|
@Nonnull PrefabBuffer.ChildPrefab childMarker, @Nonnull WorldGenPrefabLoader loader, @Nonnull Deque<String> trace
|
|
) {
|
|
WorldGenPrefabSupplier[] suppliers;
|
|
try {
|
|
suppliers = loader.get(childMarker.getPath());
|
|
} catch (Throwable var11) {
|
|
((HytaleLogger.Api)LogUtil.getLogger().at(Level.SEVERE).withCause(var11))
|
|
.log("Failed to resolve child prefab: %s loaded from %s", childMarker.getPath(), String.join(".", trace));
|
|
return true;
|
|
}
|
|
|
|
boolean invalid = false;
|
|
|
|
for (WorldGenPrefabSupplier childSupplier : suppliers) {
|
|
try {
|
|
childSupplier.get();
|
|
} catch (Throwable var10) {
|
|
invalid = true;
|
|
((HytaleLogger.Api)LogUtil.getLogger().at(Level.SEVERE).withCause(var10))
|
|
.log("Failed to load child prefab: %s loaded from %s", childSupplier.getName(), String.join(".", trace));
|
|
}
|
|
}
|
|
|
|
return invalid;
|
|
}
|
|
}
|