mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-10 17:56:08 +00:00
Fix Shafts
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -341,6 +341,8 @@ public class ServerConfigurator {
|
||||
definition.isReplaceVanilla(),
|
||||
definition.isSupportSmartBore(),
|
||||
definition.getReplaceTargets(),
|
||||
definition.getStructureAliases(),
|
||||
definition.getStructureSetAliases(),
|
||||
definition.getStructurePatches(),
|
||||
Set.of(),
|
||||
scopeKey,
|
||||
@@ -370,6 +372,8 @@ public class ServerConfigurator {
|
||||
group.replaceVanilla(),
|
||||
definition.isSupportSmartBore(),
|
||||
definition.getReplaceTargets(),
|
||||
definition.getStructureAliases(),
|
||||
definition.getStructureSetAliases(),
|
||||
definition.getStructurePatches(),
|
||||
group.forcedBiomeKeys(),
|
||||
group.scopeKey(),
|
||||
|
||||
@@ -28,6 +28,7 @@ import art.arcane.volmlib.util.director.annotations.Director;
|
||||
import art.arcane.volmlib.util.director.annotations.Param;
|
||||
import art.arcane.iris.util.common.director.specialhandlers.ObjectHandler;
|
||||
import art.arcane.iris.util.common.format.C;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -106,15 +107,20 @@ public class CommandFind implements DirectorExecutor {
|
||||
}
|
||||
|
||||
Set<String> structures = ExternalDataPackPipeline.resolveLocateStructuresForObjectKey(object);
|
||||
VolmitSender commandSender = sender();
|
||||
if (structures.isEmpty()) {
|
||||
sender().sendMessage(C.RED + object + " is not configured in any region/biome object placements and has no external structure mapping.");
|
||||
sender().sendMessage(C.GRAY + "Try /iris locateexternal <datapack-id> for external structure lookups.");
|
||||
if (commandSender != null) {
|
||||
commandSender.sendMessage(C.RED + object + " is not configured in any region/biome object placements and has no external structure mapping.");
|
||||
commandSender.sendMessage(C.GRAY + "Try /iris locateexternal <datapack-id> for external structure lookups.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Player target = player();
|
||||
if (target == null) {
|
||||
sender().sendMessage(C.RED + "No active player sender was available for object lookup.");
|
||||
if (commandSender != null) {
|
||||
commandSender.sendMessage(C.RED + "No active player sender was available for object lookup.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -124,21 +130,31 @@ public class CommandFind implements DirectorExecutor {
|
||||
String command = "locate structure " + structure;
|
||||
boolean accepted = Bukkit.dispatchCommand(target, command);
|
||||
if (!accepted) {
|
||||
sender().sendMessage(C.RED + "Failed to dispatch: /" + command);
|
||||
if (commandSender != null) {
|
||||
commandSender.sendMessage(C.RED + "Failed to dispatch: /" + command);
|
||||
}
|
||||
} else {
|
||||
sender().sendMessage(C.GREEN + "Dispatched: /" + command);
|
||||
if (commandSender != null) {
|
||||
commandSender.sendMessage(C.GREEN + "Dispatched: /" + command);
|
||||
}
|
||||
dispatched++;
|
||||
}
|
||||
}
|
||||
|
||||
if (teleport) {
|
||||
sender().sendMessage(C.YELLOW + "External object lookups are structure-backed and dispatch locate commands instead of direct teleport.");
|
||||
if (commandSender != null) {
|
||||
commandSender.sendMessage(C.YELLOW + "External object lookups are structure-backed and dispatch locate commands instead of direct teleport.");
|
||||
}
|
||||
}
|
||||
if (commandSender != null) {
|
||||
commandSender.sendMessage(C.GREEN + "External object mapping matched locateTargets=" + structures.size() + ", dispatched=" + dispatched + ".");
|
||||
}
|
||||
sender().sendMessage(C.GREEN + "External object mapping matched locateTargets=" + structures.size() + ", dispatched=" + dispatched + ".");
|
||||
};
|
||||
|
||||
if (!J.runEntity(target, dispatchTask)) {
|
||||
sender().sendMessage(C.RED + "Failed to schedule external object locate dispatch on your region thread.");
|
||||
if (commandSender != null) {
|
||||
commandSender.sendMessage(C.RED + "Failed to schedule external object locate dispatch on your region thread.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ public class IrisExternalDatapack {
|
||||
@Desc("Explicit replacement targets for minecraft namespace assets")
|
||||
private IrisExternalDatapackReplaceTargets replaceTargets = new IrisExternalDatapackReplaceTargets();
|
||||
|
||||
@ArrayType(type = IrisExternalDatapackStructureAlias.class, min = 1)
|
||||
@Desc("Optional structure alias mappings used to synthesize vanilla structure replacements from non-minecraft source keys")
|
||||
private KList<IrisExternalDatapackStructureAlias> structureAliases = new KList<>();
|
||||
|
||||
@ArrayType(type = IrisExternalDatapackStructureSetAlias.class, min = 1)
|
||||
@Desc("Optional structure-set alias mappings used to synthesize vanilla structure_set replacements from non-minecraft source keys")
|
||||
private KList<IrisExternalDatapackStructureSetAlias> structureSetAliases = new KList<>();
|
||||
|
||||
@ArrayType(type = IrisExternalDatapackStructurePatch.class, min = 1)
|
||||
@Desc("Structure placement patches applied when this external datapack is projected")
|
||||
private KList<IrisExternalDatapackStructurePatch> structurePatches = new KList<>();
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@Desc("Maps a vanilla structure replacement target to a source structure key from an external datapack")
|
||||
public class IrisExternalDatapackStructureAlias {
|
||||
@Desc("Vanilla replacement target structure id")
|
||||
private String target = "";
|
||||
|
||||
@Desc("Source structure id to clone when the target id is not provided directly")
|
||||
private String source = "";
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@Desc("Maps a vanilla structure_set replacement target to a source structure_set key from an external datapack")
|
||||
public class IrisExternalDatapackStructureSetAlias {
|
||||
@Desc("Vanilla replacement target structure_set id")
|
||||
private String target = "";
|
||||
|
||||
@Desc("Source structure_set id to clone when the target id is not provided directly")
|
||||
private String source = "";
|
||||
}
|
||||
@@ -202,7 +202,6 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
|
||||
List<StructureStart> starts = new ArrayList<>(structureManager.startsForStructure(chunkAccess.getPos(), structure -> true));
|
||||
starts.sort(Comparator.comparingInt(start -> structureOrder.getOrDefault(start.getStructure(), Integer.MAX_VALUE)));
|
||||
Set<String> externalSmartBoreStructures = ExternalDataPackPipeline.snapshotSmartBoreStructureKeys();
|
||||
Set<String> suppressedVanillaStructures = ExternalDataPackPipeline.snapshotSuppressedVanillaStructureKeys();
|
||||
|
||||
int seededStructureIndex = Integer.MIN_VALUE;
|
||||
for (int j = 0; j < starts.size(); j++) {
|
||||
@@ -215,9 +214,6 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
|
||||
}
|
||||
Supplier<String> supplier = () -> structureRegistry.getResourceKey(structure).map(Object::toString).orElseGet(structure::toString);
|
||||
String structureKey = resolveStructureKey(structureRegistry, structure);
|
||||
if (suppressedVanillaStructures.contains(structureKey)) {
|
||||
continue;
|
||||
}
|
||||
boolean isExternalSmartBoreStructure = externalSmartBoreStructures.contains(structureKey);
|
||||
BitSet[] beforeSolidColumns = null;
|
||||
if (isExternalSmartBoreStructure) {
|
||||
@@ -230,6 +226,9 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
|
||||
if (isExternalSmartBoreStructure && beforeSolidColumns != null) {
|
||||
applyExternalStructureFoundations(level, chunkAccess, beforeSolidColumns, EXTERNAL_FOUNDATION_MAX_DEPTH);
|
||||
}
|
||||
if (shouldLogExternalStructureFingerprint(structureKey)) {
|
||||
logExternalStructureFingerprint(structureKey, start);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
CrashReport crashReport = CrashReport.forThrowable(exception, "Feature placement");
|
||||
CrashReportCategory category = crashReport.addCategory("Feature");
|
||||
@@ -381,6 +380,133 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
|
||||
return Heightmap.Types.MOTION_BLOCKING_NO_LEAVES.isOpaque().test(state);
|
||||
}
|
||||
|
||||
private static boolean shouldLogExternalStructureFingerprint(String structureKey) {
|
||||
if (!IrisSettings.get().getGeneral().isDebug()) {
|
||||
return false;
|
||||
}
|
||||
if (structureKey == null || structureKey.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String normalized = structureKey.toLowerCase(Locale.ROOT);
|
||||
return "minecraft:ancient_city".equals(normalized)
|
||||
|| "minecraft:mineshaft".equals(normalized)
|
||||
|| "minecraft:mineshaft_mesa".equals(normalized);
|
||||
}
|
||||
|
||||
private static void logExternalStructureFingerprint(String structureKey, StructureStart start) {
|
||||
if (start == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<?> pieces = extractPieces(start);
|
||||
int pieceCount = pieces.size();
|
||||
String firstPieceType = "none";
|
||||
String firstPieceFingerprint = "none";
|
||||
if (!pieces.isEmpty()) {
|
||||
Object firstPiece = pieces.get(0);
|
||||
if (firstPiece != null) {
|
||||
firstPieceType = firstPiece.getClass().getName();
|
||||
firstPieceFingerprint = resolvePieceFingerprint(firstPiece);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.debug("External structure fingerprint: key=" + structureKey
|
||||
+ ", pieces=" + pieceCount
|
||||
+ ", firstPiece=" + firstPieceType
|
||||
+ ", fingerprint=" + firstPieceFingerprint);
|
||||
}
|
||||
|
||||
private static List<?> extractPieces(StructureStart start) {
|
||||
try {
|
||||
Method getPiecesMethod = start.getClass().getMethod("getPieces");
|
||||
Object result = getPiecesMethod.invoke(start);
|
||||
if (result instanceof List<?> list) {
|
||||
return list;
|
||||
}
|
||||
if (result != null) {
|
||||
Method piecesMethod = result.getClass().getMethod("pieces");
|
||||
Object piecesResult = piecesMethod.invoke(result);
|
||||
if (piecesResult instanceof List<?> list) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
Method piecesMethod = start.getClass().getMethod("pieces");
|
||||
Object result = piecesMethod.invoke(start);
|
||||
if (result instanceof List<?> list) {
|
||||
return list;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
return List.of();
|
||||
}
|
||||
|
||||
private static String resolvePieceFingerprint(Object piece) {
|
||||
if (piece == null) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
try {
|
||||
Method templateNameMethod = piece.getClass().getMethod("templateName");
|
||||
Object value = templateNameMethod.invoke(piece);
|
||||
if (value != null) {
|
||||
String normalized = String.valueOf(value);
|
||||
if (!normalized.isBlank()) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
Method templateMethod = piece.getClass().getMethod("template");
|
||||
Object value = templateMethod.invoke(piece);
|
||||
if (value != null) {
|
||||
return value.getClass().getName();
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
Class<?> current = piece.getClass();
|
||||
while (current != null && current != Object.class) {
|
||||
Field[] fields = current.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(piece);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value instanceof Identifier identifier) {
|
||||
String normalized = identifier.toString();
|
||||
if (!normalized.isBlank()) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
if (value instanceof String text) {
|
||||
String fieldName = field.getName() == null ? "" : field.getName().toLowerCase(Locale.ROOT);
|
||||
if (fieldName.contains("template") || fieldName.contains("name") || fieldName.contains("id")) {
|
||||
if (!text.isBlank()) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
|
||||
return piece.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
private Map<Structure, Integer> getStructureOrder(Registry<Structure> structureRegistry) {
|
||||
Map<Structure, Integer> localOrder = cachedStructureOrder;
|
||||
Registry<Structure> localRegistry = cachedStructureRegistry;
|
||||
|
||||
Reference in New Issue
Block a user