This commit is contained in:
Brian Neumann-Fopiano committed 2026-08-05 14:30:07 -06:00
1 parent a66cba6418
commit 70d355621c
26 files changed
+1719 -35

No files matched your search

@@ -3205,7 +3205,7 @@ public final class DatapackIngestService {
}
int transactionCount = 0;
for (Path transactionRoot : transactionRoots) {
if (isHarmlessTransactionArtifact(transactionRoot)) {
if (isHarmlessRecoveryArtifact(transactionRoot)) {
continue;
}
transactionCount++;
@@ -3214,7 +3214,7 @@ public final class DatapackIngestService {
}
}
for (Path transactionRoot : transactionRoots) {
if (isHarmlessTransactionArtifact(transactionRoot)) {
if (isHarmlessRecoveryArtifact(transactionRoot)) {
Files.deleteIfExists(transactionRoot);
continue;
}
@@ -3242,15 +3242,25 @@ public final class DatapackIngestService {
verifyDirectoryContainerIfPresent(scratchRoot.toFile(), "datapack install scratch");
List<Path> children;
try (Stream<Path> paths = Files.list(scratchRoot)) {
children = paths.limit(MAX_MANAGED_PATHS + 1L).sorted().toList();
children = paths.limit(MAX_MANAGED_PATHS + 2L).sorted().toList();
}
if (children.size() > MAX_MANAGED_PATHS) {
throw new IOException("Datapack install scratch contains too many entries");
int managedEntries = 0;
for (Path child : children) {
if (!isHarmlessRecoveryArtifact(child)) {
managedEntries++;
}
if (managedEntries > MAX_MANAGED_PATHS) {
throw new IOException("Datapack install scratch contains too many entries");
}
}
List<StagingScratch> pending = new ArrayList<>();
List<StagingScratch> backups = new ArrayList<>();
for (Path child : children) {
if (isHarmlessRecoveryArtifact(child)) {
Files.deleteIfExists(child);
continue;
}
StagingScratch scratch = parseInstallScratch(scratchRoot, child);
if (scratch == null) {
throw new IOException("Unexpected datapack install scratch artifact " + child);
@@ -3429,12 +3439,12 @@ public final class DatapackIngestService {
return ownership;
}
private static boolean isHarmlessTransactionArtifact(Path path) throws IOException {
private static boolean isHarmlessRecoveryArtifact(Path path) throws IOException {
if (!".DS_Store".equals(path.getFileName().toString())) {
return false;
}
if (Files.isSymbolicLink(path) || !Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS)) {
throw new IOException("Suspicious datapack transaction artifact " + path);
throw new IOException("Suspicious datapack recovery artifact " + path);
}
return true;
}
@@ -117,6 +117,7 @@ final class PackStructurePlacementValidator {
registries.hooks(), blockingErrors);
continue;
}
validateEditableStructureTerrain(placementPath, placement, blockingErrors);
Set<String> editableStructureKeys = new HashSet<>();
for (int referenceIndex = 0; referenceIndex < references.length(); referenceIndex++) {
Object rawReference = references.opt(referenceIndex);
@@ -650,6 +651,20 @@ final class PackStructurePlacementValidator {
}
}
private static void validateEditableStructureTerrain(
String path, JSONObject placement, List<String> blockingErrors) {
JSONObject terrain = placement.optJSONObject("terrain");
if (terrain == null) {
return;
}
String mode = terrain.optString("mode", "SOURCE");
if ("VACUUM".equals(mode) || "ENCASE".equals(mode)) {
blockingErrors.add(path + ".terrain.mode " + mode
+ " cannot target editable Iris structures; use nativeStructures or "
+ "importedStructures.adjustments for native terrain preparation.");
}
}
static void validateStructureStartPools(File structuresFolder,
Set<String> poolKeys,
List<String> blockingErrors) {
@@ -118,6 +118,32 @@ public record NativeStructureOwnershipRecord(
&& chunkZ >= referenceMinChunkZ && chunkZ <= referenceMaxChunkZ;
}
public NativeStructureOwnershipRecord withReferenceEnvelope(
int referenceMinChunkX, int referenceMaxChunkX,
int referenceMinChunkZ, int referenceMaxChunkZ) {
return new NativeStructureOwnershipRecord(
schema,
structureKey,
originChunkX,
originChunkZ,
placementIdentity,
baseY,
contentMinX,
contentMinY,
contentMinZ,
contentMaxX,
contentMaxY,
contentMaxZ,
locatorY,
referenceMinChunkX,
referenceMaxChunkX,
referenceMinChunkZ,
referenceMaxChunkZ,
contentFingerprint,
decision
);
}
public OwnershipKey ownershipKey() {
return new OwnershipKey(structureKey, originChunkX, originChunkZ);
}
@@ -91,7 +91,7 @@ public class IrisStructurePlacement {
@Desc("If true, the structure starts at a deterministic random world Y inside [minHeight, maxHeight]. Terrain integration is then controlled independently by terrain.")
private boolean underground = false;
@Desc("Terrain integration shared by editable Iris assemblies and live registered structures.")
@Desc("Terrain integration for this placement. The editable structures backend supports SOURCE, PRESERVE, BORE, and FORCE_CARVE. The nativeStructures backend supports every terrain mode.")
private IrisStructureTerrain terrain = new IrisStructureTerrain();
@Desc("Optional foundation columns placed beneath the assembled structure's occupied bottom cells. Columns pass through air and fluids until they reach solid ground, up to maxDepth.")
@@ -22,12 +22,12 @@ public class IrisStructureTerrain {
private static final double MAX_EROSION_FREQUENCY = 1D;
private static final double MAX_LOBE_FREQUENCY = 1D;
@Desc("Terrain operation. SOURCE applies the registered native structure's authored terrain adaptation and is a no-op for editable Iris structures. PRESERVE disables terrain integration. FORCE_CARVE clears the requested envelope, while ENCASE fills it before placement so native shells are not lost to pre-carved air.")
@Desc("Terrain operation. SOURCE applies the registered native structure's authored terrain adaptation and is a no-op for editable Iris structures. PRESERVE disables terrain integration. VACUUM forces a 12-block surface bend to every rigid native piece base. BORE and FORCE_CARVE clear the requested envelope, while ENCASE fills it before placement so native shells are not lost to pre-carved air.")
private IrisStructureTerrainMode mode = IrisStructureTerrainMode.SOURCE;
@MinNumber(0)
@MaxNumber(128)
@Desc("Horizontal clearance around the assembled pieces.")
@Desc("Horizontal clearance around the assembled pieces for BORE, FORCE_CARVE, and ENCASE. VACUUM uses its fixed 12-block terrain falloff.")
private int horizontalPadding = 0;
@MinNumber(0)
@@ -8,6 +8,8 @@ public enum IrisStructureTerrainMode {
PRESERVE,
BORE,
FORCE_CARVE,
@Desc("Bends surface terrain to every rigid piece base with a 12-block falloff, even when the registered structure has no authored terrain adaptation. Terrain is raised or lowered rather than carved away.")
VACUUM,
@Desc("Fills the padded piece volume with solid blocks before any piece is placed so shells, walls, and floors land in solid ground instead of pre-carved air. Only air and liquid cells are filled; existing terrain and structures are never overwritten. Native pieces then carve their own interiors.")
@@ -57,7 +57,7 @@ public class IrisVanillaStructureAdjustment {
@Desc("Optional foundation columns placed beneath the native structure piece bases after placement.")
private IrisStructureStiltSettings stilt = null;
@Desc("Optional terrain integration override. FORCE_CARVE clears every intersecting chunk before native pieces are placed, ENCASE fills it with solid blocks instead. Left unset, SOURCE replays the registered structure's authored terrain adaptation, including surface fitting, burial, and encapsulation.")
@Desc("Optional terrain integration override. VACUUM forces surface terrain to bend to every rigid native piece base even when the structure did not author terrain adaptation. BORE and FORCE_CARVE clear every intersecting chunk before native pieces are placed, while ENCASE fills it with solid blocks instead. Left unset, SOURCE replays the registered structure's authored terrain adaptation, including surface fitting, burial, and encapsulation.")
private IrisStructureTerrain terrain = null;
public boolean matches(String key) {