d
This commit is contained in:
Brian Neumann-Fopiano committed 2026-08-05 15:45:08 -06:00
1 parent 70d355621c
commit ce8c4ff578
18 files changed
+1958 -180

No files matched your search

@@ -69,9 +69,14 @@ public final class IrisStructureLocator {
private static final Pattern NAMESPACED_RESOURCE_KEY = Pattern.compile("[a-z0-9_.-]+:[a-z0-9/._-]+");
private static final Cache<Engine, PlacementIndex> INDEX_CACHE = Caffeine.newBuilder().weakKeys().build();
private static final Cache<Engine, LocatableIndex> LOCATABLE_INDEX_CACHE =
Caffeine.newBuilder().weakKeys().build();
private static final PlacementIndex EMPTY_INDEX = new PlacementIndex(
Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(),
Collections.emptySet(), Collections.emptyList());
private static final LocatableIndex EMPTY_LOCATABLE_INDEX = new LocatableIndex(
Collections.emptySet(), Collections.emptySet(), Collections.emptySet(),
Collections.emptySet(), Collections.emptySet(), Collections.emptySet());
private static final LocateResult NOT_FOUND_RESULT = new LocateResult(LocateStatus.NOT_FOUND, 0, 0, 0);
private static final LocateResult SEARCH_LIMIT_RESULT =
new LocateResult(LocateStatus.SEARCH_LIMIT_REACHED, 0, 0, 0);
@@ -97,6 +102,39 @@ public final class IrisStructureLocator {
|| placementIndex.vanillaAliases.contains(normalizedKey);
}
public static boolean hasLocatablePlacement(Engine engine, String key) {
if (engine == null || key == null || key.isBlank()) {
return false;
}
return locatableIndex(engine).normalizedKeys().contains(normalize(key));
}
public static boolean hasLocatableEditablePlacement(Engine engine, String key) {
if (engine == null || key == null || key.isBlank()) {
return false;
}
return locatableIndex(engine).normalizedEditableKeys().contains(normalize(key));
}
public static boolean hasLocatableNativePlacement(Engine engine, String key) {
if (engine == null || key == null || key.isBlank()) {
return false;
}
return locatableIndex(engine).normalizedNativeKeys().contains(normalize(key));
}
public static Set<String> locatableKeys(Engine engine) {
return locatableIndex(engine).keys();
}
public static Set<String> locatableEditableKeys(Engine engine) {
return locatableIndex(engine).editableKeys();
}
public static Set<String> locatableNativeKeys(Engine engine) {
return locatableIndex(engine).nativeKeys();
}
public static boolean hasNativePlacement(Engine engine, String key) {
if (engine == null || key == null || key.isBlank()) {
return false;
@@ -126,6 +164,7 @@ public final class IrisStructureLocator {
public static void invalidate(Engine engine) {
if (engine != null) {
INDEX_CACHE.invalidate(engine);
LOCATABLE_INDEX_CACHE.invalidate(engine);
}
}
@@ -796,7 +835,8 @@ public final class IrisStructureLocator {
List<IrisStructurePlacement> concentricRings = new ArrayList<>();
boolean hasDensity = false;
for (IrisStructurePlacement placement : index(engine).placements) {
if (!matches(placement, key, engine.getData())) {
if (!isSearchablePlacement(engine, placement)
|| !matches(placement, key, engine.getData())) {
continue;
}
if (placement.getDistribution() == StructureDistribution.RANDOM_SPREAD) {
@@ -805,7 +845,7 @@ public final class IrisStructureLocator {
StructurePlacementGrid.placementSalt(placement)));
} else if (placement.getDistribution() == StructureDistribution.CONCENTRIC_RINGS) {
concentricRings.add(placement);
} else if (isSearchableDensityPlacement(engine, placement)) {
} else if (placement.getDistribution() == StructureDistribution.DENSITY) {
hasDensity = true;
}
}
@@ -813,8 +853,18 @@ public final class IrisStructureLocator {
}
static boolean isSearchableDensityPlacement(Engine engine, IrisStructurePlacement placement) {
if (engine == null || placement == null || placement.getDistribution() != StructureDistribution.DENSITY
|| !(placement.getDensity() > 0.0) || engine.getHeight() <= 0) {
return placement != null
&& placement.getDistribution() == StructureDistribution.DENSITY
&& isSearchablePlacement(engine, placement);
}
static boolean isSearchablePlacement(Engine engine, IrisStructurePlacement placement) {
if (engine == null || placement == null || placement.getDistribution() == null
|| engine.getHeight() <= 0) {
return false;
}
if (placement.getDistribution() == StructureDistribution.DENSITY
&& !(placement.getDensity() > 0.0)) {
return false;
}
long worldMin = (long) engine.getMinHeight() + (placement.isUnderground() ? 1L : 0L);
@@ -952,6 +1002,64 @@ public final class IrisStructureLocator {
return INDEX_CACHE.get(engine, ignored -> build(engine));
}
private static LocatableIndex locatableIndex(Engine engine) {
if (engine == null) {
return EMPTY_LOCATABLE_INDEX;
}
return LOCATABLE_INDEX_CACHE.get(engine, ignored -> buildLocatableIndex(engine));
}
private static LocatableIndex buildLocatableIndex(Engine engine) {
IrisData data = engine.getData();
Set<String> keys = new LinkedHashSet<>();
Set<String> normalizedKeys = new LinkedHashSet<>();
Set<String> editableKeys = new LinkedHashSet<>();
Set<String> normalizedEditableKeys = new LinkedHashSet<>();
Set<String> nativeKeys = new LinkedHashSet<>();
Set<String> normalizedNativeKeys = new LinkedHashSet<>();
for (IrisStructurePlacement placement : index(engine).placements) {
if (!isSearchablePlacement(engine, placement)) {
continue;
}
if (placement.hasNativeStructures()) {
for (IrisNativeStructure source : placement.getNativeStructures()) {
addLocatableKey(source.getStructure(), keys, normalizedKeys);
addLocatableKey(source.getStructure(), nativeKeys, normalizedNativeKeys);
}
continue;
}
for (String structureKey : placement.getStructures()) {
IrisStructure structure = data.load(IrisStructure.class, structureKey, false);
if (structure == null) {
throw new IllegalStateException(
"Iris structure placement references missing structure '" + structureKey + "'");
}
addLocatableKey(structureKey, keys, normalizedKeys);
addLocatableKey(structureKey, editableKeys, normalizedEditableKeys);
addLocatableKey(structure.getLoadKey(), keys, normalizedKeys);
addLocatableKey(structure.getLoadKey(), editableKeys, normalizedEditableKeys);
addLocatableKey(structure.getVanillaSource(), keys, normalizedKeys);
addLocatableKey(structure.getVanillaSource(), editableKeys, normalizedEditableKeys);
}
}
return new LocatableIndex(
Collections.unmodifiableSet(keys),
Collections.unmodifiableSet(normalizedKeys),
Collections.unmodifiableSet(editableKeys),
Collections.unmodifiableSet(normalizedEditableKeys),
Collections.unmodifiableSet(nativeKeys),
Collections.unmodifiableSet(normalizedNativeKeys));
}
private static void addLocatableKey(String key, Set<String> keys, Set<String> normalizedKeys) {
if (key == null || key.isBlank()) {
return;
}
String trimmedKey = key.trim();
keys.add(trimmedKey);
normalizedKeys.add(normalize(trimmedKey));
}
private static PlacementIndex build(Engine engine) {
IrisData data = engine.getData();
Set<String> loadKeys = new LinkedHashSet<>();
@@ -1112,6 +1220,11 @@ public final class IrisStructureLocator {
List<IrisStructurePlacement> concentricRings, boolean hasDensity) {
}
private record LocatableIndex(Set<String> keys, Set<String> normalizedKeys,
Set<String> editableKeys, Set<String> normalizedEditableKeys,
Set<String> nativeKeys, Set<String> normalizedNativeKeys) {
}
private record ResolvedStart(int originX, int baseY, int originZ) {
}
@@ -18,42 +18,57 @@
package art.arcane.iris.util.common.director.specialhandlers;
import art.arcane.iris.core.nms.INMS;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.framework.IrisStructureLocator;
import art.arcane.volmlib.util.collection.KList;
import art.arcane.iris.engine.framework.NativeStructureGenerationPolicy;
import art.arcane.iris.engine.framework.StructureReachability;
import art.arcane.iris.engine.object.IrisNativeStructureDecision;
import art.arcane.iris.engine.object.NativeStructureGenerationStatus;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.spi.PlatformStructureHooks;
import art.arcane.iris.util.common.director.DirectorParameterHandler;
import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.director.exceptions.DirectorParsingException;
import org.bukkit.entity.Player;
import java.util.stream.Collectors;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class StructureHandler implements DirectorParameterHandler<String> {
@Override
public KList<String> getPossibilities() {
KList<String> keys = new KList<>();
try {
for (String k : INMS.get().getStructureKeys()) {
if (k != null && !k.isEmpty()) {
keys.addIfMissing(k);
}
}
} catch (Throwable ignored) {
Engine activeEngine = engine();
if (activeEngine == null) {
return new KList<>();
}
try {
Engine e = engine();
if (e != null) {
for (String k : IrisStructureLocator.placedKeys(e)) {
if (k != null && !k.isEmpty()) {
keys.addIfMissing(k);
}
}
boolean nativeGenerationEnabled = nativeStructureGenerationEnabled();
PlatformStructureHooks structureHooks = IrisPlatforms.get().structureHooks();
Map<String, String> registeredKeys = distinctKeys(structureHooks.structureKeys());
Set<String> reachableKeys = StructureReachability.reachableKeys(activeEngine);
Map<String, String> suggestions = new LinkedHashMap<>();
for (Map.Entry<String, String> entry : registeredKeys.entrySet()) {
if (isEligibleRegisteredKey(activeEngine, entry.getValue(), entry.getKey(), reachableKeys,
nativeGenerationEnabled)) {
suggestions.put(entry.getKey(), entry.getValue());
}
} catch (Throwable ignored) {
}
return keys;
Set<String> locatableKeys = IrisStructureLocator.locatableEditableKeys(activeEngine);
for (String key : locatableKeys) {
String normalizedKey = normalizeKey(key);
if (!normalizedKey.isEmpty()
&& !registeredKeys.containsKey(normalizedKey)
&& !IrisStructureLocator.hasNativePlacement(activeEngine, key)) {
suggestions.putIfAbsent(normalizedKey, key.trim());
}
}
return new KList<>(suggestions.values());
}
@Override
@@ -64,15 +79,12 @@ public class StructureHandler implements DirectorParameterHandler<String> {
@Override
public String parse(String in, boolean force) throws DirectorParsingException {
KList<String> options = getPossibilities(in);
if (options.isEmpty()) {
return in;
}
try {
return options.stream().filter((i) -> toString(i).equalsIgnoreCase(in)).collect(Collectors.toList()).get(0);
} catch (Throwable e) {
return in;
for (String option : options) {
if (option.equalsIgnoreCase(in)) {
return option;
}
}
return in;
}
@Override
@@ -86,4 +98,50 @@ public class StructureHandler implements DirectorParameterHandler<String> {
return f == null ? "minecraft_ancient_city" : f;
}
protected boolean nativeStructureGenerationEnabled() {
Player activePlayer = player();
return activePlayer != null && activePlayer.getWorld().canGenerateStructures();
}
private static Map<String, String> distinctKeys(List<String> keys) {
Map<String, String> distinct = new LinkedHashMap<>();
for (String key : keys) {
String normalizedKey = normalizeKey(key);
if (!normalizedKey.isEmpty()) {
distinct.putIfAbsent(normalizedKey, key.trim());
}
}
return distinct;
}
private static boolean isEligibleRegisteredKey(Engine engine, String key, String normalizedKey,
Set<String> reachableKeys, boolean nativeGenerationEnabled) {
IrisNativeStructureDecision decision = NativeStructureGenerationPolicy.resolve(engine, key, false);
boolean nativePlacement = IrisStructureLocator.hasNativePlacement(engine, key);
boolean locatableNativePlacement = nativePlacement
&& IrisStructureLocator.hasLocatableNativePlacement(engine, key);
boolean locatableEditableReplacement = !nativePlacement
&& decision.status() == NativeStructureGenerationStatus.REPLACED_BY_IRIS
&& IrisStructureLocator.hasLocatableEditablePlacement(engine, key);
return isEligibleRegisteredKey(
decision, nativePlacement, locatableNativePlacement, locatableEditableReplacement,
reachableKeys.contains(normalizedKey), nativeGenerationEnabled);
}
static boolean isEligibleRegisteredKey(IrisNativeStructureDecision decision, boolean nativePlacement,
boolean locatableNativePlacement,
boolean locatableEditableReplacement,
boolean reachable, boolean nativeGenerationEnabled) {
if (decision.status() == NativeStructureGenerationStatus.REPLACED_BY_IRIS) {
return locatableEditableReplacement
|| nativeGenerationEnabled && nativePlacement && locatableNativePlacement;
}
return nativeGenerationEnabled && decision.generate()
&& (reachable || (nativePlacement && locatableNativePlacement));
}
private static String normalizeKey(String key) {
return key == null ? "" : key.trim().toLowerCase(Locale.ROOT);
}
}