This commit is contained in:
Brian Neumann-Fopiano
2026-08-24 02:27:26 -04:00
parent fe5651f854
commit e20bb86f40
228 changed files with 5716 additions and 3577 deletions
@@ -82,8 +82,6 @@ import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Arrays;
@@ -98,7 +96,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.IntBinaryOperator;
public final class IrisModdedChunkGenerator extends ChunkGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
// Vanilla-shaped fallback for an unbound generator (matches IrisDimension defaults). getMinY,
// getSeaLevel and getGenDepth are called from world creation and client screens, so they must
// answer without disk I/O and without throwing before a level is bound.
@@ -368,7 +365,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
// Bind time: a feature-order cycle is reported here, once, and degrades to features-off. Non-waiting for
// the same reason as repointAndBind: this method owns the generator monitor.
importedFeatures.prepareWithoutWaiting(bound);
LOGGER.info("Iris bound {}: chunk system {}", level.dimension().identifier(), ModdedGenPool.describeChunkSystem());
ModdedIrisLog.info("Iris bound {}: chunk system {}", level.dimension().identifier(), ModdedGenPool.describeChunkSystem());
}
private Engine bindEngine(ServerLevel level) {
@@ -601,7 +598,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
try {
heightMetadata = configuredPack().metadata();
} catch (Throwable e) {
LOGGER.warn("Iris generator '{}' could not pre-resolve pack heights for {}:{}: {}",
ModdedIrisLog.warn("Iris generator '{}' could not pre-resolve pack heights for {}:{}: {}",
dimensionKey, activePack, activeDimensionKey, e.toString());
}
}
@@ -726,7 +723,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
Engine generationEngine = engine();
ChunkPos pos = chunk.getPos();
lastChunkGenAt = System.currentTimeMillis();
LOGGER.debug("Iris generating chunk {},{}", pos.x(), pos.z());
ModdedIrisLog.debug("Iris generating chunk {},{}", pos.x(), pos.z());
PlatformBlockState air = IrisPlatforms.get().registries().air();
@@ -744,7 +741,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
try (GenerationSessionLease lease = generationEngine.acquireGenerationLease("modded_chunk_pipeline");
IrisContext.Scope ignored = IrisContext.open(generationEngine, lease.sessionId(), null)) {
if (announced.compareAndSet(false, true)) {
LOGGER.info("Iris generating {} through IrisModdedChunkGenerator (dim={} first chunk {},{})",
ModdedIrisLog.info("Iris generating {} through IrisModdedChunkGenerator (dim={} first chunk {},{})",
dimensionKey, generationEngine.getDimension().getLoadKey(), pos.x(), pos.z());
}
int dimMinY = generationEngine.getMinHeight();
@@ -763,14 +760,14 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
return chunk;
} catch (GenerationSessionException e) {
if (generationEngine.isClosing() || e.isExpectedTeardown()) {
LOGGER.debug("Iris chunk {},{} skipped: engine sealed for hotload/teardown", pos.x(), pos.z());
ModdedIrisLog.debug("Iris chunk {},{} skipped: engine sealed for hotload/teardown", pos.x(), pos.z());
throw new IllegalStateException(
"Iris chunk generation was rejected during an engine transition.", e);
}
LOGGER.error("Iris failed to generate chunk {},{}", pos.x(), pos.z(), e);
ModdedIrisLog.error("Iris failed to generate chunk {},{}", pos.x(), pos.z(), e);
throw new IllegalStateException("Iris generation failed for chunk " + pos.x() + "," + pos.z(), e);
} catch (Throwable e) {
LOGGER.error("Iris failed to generate chunk {},{}", pos.x(), pos.z(), e);
ModdedIrisLog.error("Iris failed to generate chunk {},{}", pos.x(), pos.z(), e);
throw new IllegalStateException("Iris generation failed for chunk " + pos.x() + "," + pos.z(), e);
}
}
@@ -18,8 +18,6 @@
package art.arcane.iris.modded;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -32,7 +30,6 @@ import java.util.Optional;
import java.util.UUID;
public final class MainWorldService {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String MARKER_NAME = "mainworld.pending";
private static final String PROPERTIES_NAME = "server.properties";
/**
@@ -80,12 +77,12 @@ public final class MainWorldService {
if (!target.equals(currentType)) {
writeLevelProperties(properties, target, config.mainWorldSeed());
markPending();
LOGGER.warn("Iris main world '{}' staged: {} level-type set to {}. Restart again to generate it (this boot still uses the previous overworld; player data is kept).",
ModdedIrisLog.warn("Iris main world '{}' staged: {} level-type set to {}. Restart again to generate it (this boot still uses the previous overworld; player data is kept).",
pack, properties, target);
if (config.mainWorldAutoRestart()) {
LOGGER.warn("Iris mainWorldAutoRestart is enabled; stopping the JVM now with exit status {} so a restart wrapper brings the server back on the new main world.",
ModdedIrisLog.warn("Iris mainWorldAutoRestart is enabled; stopping the JVM now with exit status {} so a restart wrapper brings the server back on the new main world.",
AUTO_RESTART_EXIT_STATUS);
LOGGER.warn("Configure the start script to restart the server on exit status {} (status 0 means a clean stop, so it must not be reused for this).",
ModdedIrisLog.warn("Configure the start script to restart the server on exit status {} (status 0 means a clean stop, so it must not be reused for this).",
AUTO_RESTART_EXIT_STATUS);
System.exit(AUTO_RESTART_EXIT_STATUS);
}
@@ -102,16 +99,16 @@ public final class MainWorldService {
// bootstrap: there is no prior overworld to move aside, so this is nothing to quarantine, not a
// reason to refuse startup.
clearPending();
LOGGER.warn("Iris main world '{}' had nothing to quarantine: {} does not exist. Continuing boot; the overworld generates as {}.",
ModdedIrisLog.warn("Iris main world '{}' had nothing to quarantine: {} does not exist. Continuing boot; the overworld generates as {}.",
pack, missing.path(), target);
return;
}
Path recovery = quarantineVanillaDimensions(worldRoot);
clearPending();
LOGGER.warn("Iris main world '{}' generated fresh: moved the prior overworld/nether/end data from {} to {} so this boot regenerates them as {} (player data kept).",
ModdedIrisLog.warn("Iris main world '{}' generated fresh: moved the prior overworld/nether/end data from {} to {} so this boot regenerates them as {} (player data kept).",
pack, worldRoot, recovery, target);
} catch (Throwable e) {
LOGGER.error("Iris main world reconciliation failed", e);
ModdedIrisLog.error("Iris main world reconciliation failed", e);
throw new IllegalStateException(
"Iris refused startup after main-world reconciliation failed", e);
}
@@ -119,7 +116,7 @@ public final class MainWorldService {
public static boolean stage(String packRef, long seed) {
if (ModdedEngineBootstrap.loader().clientEnvironment()) {
LOGGER.error("Iris main-world replacement is only available on dedicated servers; use the Create World generator selector in singleplayer");
ModdedIrisLog.error("Iris main-world replacement is only available on dedicated servers; use the Create World generator selector in singleplayer");
return false;
}
Path instanceRoot = verifiedInstanceRoot("stage the Iris main world");
@@ -131,7 +128,7 @@ public final class MainWorldService {
markPending();
return true;
} catch (IOException e) {
LOGGER.error("Iris failed to stage the main world in server.properties", e);
ModdedIrisLog.error("Iris failed to stage the main world in server.properties", e);
return false;
}
}
@@ -140,7 +137,7 @@ public final class MainWorldService {
try {
clearPending();
} catch (IOException e) {
LOGGER.error("Iris failed to clear the pending main world marker", e);
ModdedIrisLog.error("Iris failed to clear the pending main world marker", e);
}
}
@@ -156,8 +153,8 @@ public final class MainWorldService {
if (Files.isRegularFile(workingDirectory.resolve(PROPERTIES_NAME))) {
return workingDirectory;
}
LOGGER.error("Iris refuses to {}: no {} in the server working directory {}", operation, PROPERTIES_NAME, workingDirectory);
LOGGER.error("Iris only edits main-world properties in the directory the dedicated server reads {} from, and it moves no world data outside it. Start the server from its instance directory, or clear mainWorldPack in irisworldgen/modded.json.", PROPERTIES_NAME);
ModdedIrisLog.error("Iris refuses to {}: no {} in the server working directory {}", operation, PROPERTIES_NAME, workingDirectory);
ModdedIrisLog.error("Iris only edits main-world properties in the directory the dedicated server reads {} from, and it moves no world data outside it. Start the server from its instance directory, or clear mainWorldPack in irisworldgen/modded.json.", PROPERTIES_NAME);
return null;
}
@@ -305,7 +302,7 @@ public final class MainWorldService {
return List.of(arguments.get());
}
} catch (RuntimeException unavailable) {
LOGGER.debug("Iris could not read the process arguments", unavailable);
ModdedIrisLog.debug("Iris could not read the process arguments", unavailable);
}
// Whitespace split only: sun.java.command is a flattened string with no quoting information, so a
// --universe or --world value containing spaces cannot be recovered from it. Deliberately not parsed
@@ -29,8 +29,6 @@ import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.biome.Biome;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -39,7 +37,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
public final class ModdedBiomeWriter implements PlatformBiomeWriter {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String VANILLA_FALLBACK_KEY = "minecraft:plains";
private static final int MAX_CACHED_IDS = 4096;
/** NUL cannot occur in a pack or registry key, so the composite cache key stays unambiguous. */
@@ -61,7 +58,7 @@ public final class ModdedBiomeWriter implements PlatformBiomeWriter {
return 0;
}
if (key == null) {
LOGGER.warn("Iris biome writer got a null biome key; falling back to {}", VANILLA_FALLBACK_KEY);
ModdedIrisLog.warn("Iris biome writer got a null biome key; falling back to {}", VANILLA_FALLBACK_KEY);
return fallbackId(registry);
}
@@ -217,7 +214,7 @@ public final class ModdedBiomeWriter implements PlatformBiomeWriter {
private void reportMissingServer(String operation, String fallback) {
if (serverMissingReported.compareAndSet(false, true)) {
LOGGER.warn("Iris cannot {} before the Minecraft server is available; {}", operation, fallback);
ModdedIrisLog.warn("Iris cannot {} before the Minecraft server is available; {}", operation, fallback);
}
}
@@ -43,14 +43,11 @@ import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public final class ModdedBlockBreakHandler {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final ConcurrentHashMap<BreakKey, PendingBreak> PENDING = new ConcurrentHashMap<>();
private ModdedBlockBreakHandler() {
@@ -72,7 +69,7 @@ public final class ModdedBlockBreakHandler {
if (scheduler == null) {
// finishPending is the only thing that evicts an unconsumed entry. With no scheduler there is no
// sweep, so an entry inserted here would leak for the rest of the server uptime.
LOGGER.debug("Iris skipped block-break provenance at {},{},{}: scheduler unavailable",
ModdedIrisLog.debug("Iris skipped block-break provenance at {},{},{}: scheduler unavailable",
position.getX(), position.getY(), position.getZ());
return;
}
@@ -150,7 +147,7 @@ public final class ModdedBlockBreakHandler {
try {
return evaluate(level, position, pending);
} catch (Throwable error) {
LOGGER.error("Iris block-break processing failed at {},{},{} in {}", position.getX(), position.getY(), position.getZ(),
ModdedIrisLog.error("Iris block-break processing failed at {},{},{} in {}", position.getX(), position.getY(), position.getZ(),
level.dimension().identifier(), error);
return Result.empty();
}
@@ -182,7 +179,7 @@ public final class ModdedBlockBreakHandler {
try {
return evaluateDrops(level, position, brokenState, engine);
} catch (Throwable error) {
LOGGER.error("Iris managed block-drop processing failed at {},{},{} in {}", position.getX(), position.getY(), position.getZ(),
ModdedIrisLog.error("Iris managed block-drop processing failed at {},{},{} in {}", position.getX(), position.getY(), position.getZ(),
level.dimension().identifier(), error);
return Result.empty();
}
@@ -315,7 +312,7 @@ public final class ModdedBlockBreakHandler {
try {
return irisGenerator.commandEngine();
} catch (Throwable error) {
LOGGER.error("Iris could not resolve the engine for a block break in {}", level.dimension().identifier(), error);
ModdedIrisLog.error("Iris could not resolve the engine for a block break in {}", level.dimension().identifier(), error);
return null;
}
}
@@ -46,8 +46,6 @@ import net.minecraft.world.level.storage.DerivedLevelData;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WorldData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
@@ -60,7 +58,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
public final class ModdedDimensionManager {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Object LOCK = new Object();
private static final ConcurrentHashMap<String, Handle> HANDLES = new ConcurrentHashMap<>();
private static final TicketType TELEPORT_WARM_TICKET = new TicketType(TicketType.NO_TIMEOUT,
@@ -137,7 +134,7 @@ public final class ModdedDimensionManager {
if (present == null || !(present.getChunkSource().getGenerator() instanceof IrisModdedChunkGenerator generator)) {
throw new IllegalStateException("Iris cannot inject dimension '" + dimensionId + "': a non-Iris level with that id is already loaded");
}
LOGGER.warn("Iris dimension '{}' is already present in the running server; reusing it", dimensionId);
ModdedIrisLog.warn("Iris dimension '{}' is already present in the running server; reusing it", dimensionId);
generator.repointAndBind(present, pack, packDimensionKey, seed);
Handle handle = new Handle(dimensionId, pack, packDimensionKey, seed, present, generator);
HANDLES.put(dimensionId, handle);
@@ -147,10 +144,10 @@ public final class ModdedDimensionManager {
try {
Handle handle = inject(server, serverAccess, dimensionId, key, pack, packDimensionKey, seed);
HANDLES.put(dimensionId, handle);
LOGGER.info("Iris injected runtime dimension '{}' (pack={} dim={} seed={})", dimensionId, pack, packDimensionKey, seed);
ModdedIrisLog.info("Iris injected runtime dimension '{}' (pack={} dim={} seed={})", dimensionId, pack, packDimensionKey, seed);
return handle;
} catch (Throwable e) {
LOGGER.error("Iris failed to inject runtime dimension '{}' (pack={} dim={} seed={})", dimensionId, pack, packDimensionKey, seed, e);
ModdedIrisLog.error("Iris failed to inject runtime dimension '{}' (pack={} dim={} seed={})", dimensionId, pack, packDimensionKey, seed, e);
throw new IllegalStateException("Iris runtime dimension injection failed for " + dimensionId, e);
}
}
@@ -233,11 +230,11 @@ public final class ModdedDimensionManager {
if (wipeStorage) {
ModdedDimensionStorage.wipe(server, key);
}
LOGGER.info("Iris removed runtime dimension '{}'", dimensionId);
ModdedIrisLog.info("Iris removed runtime dimension '{}'", dimensionId);
return true;
} catch (Throwable e) {
rollbackRemoval(server, serverAccess, key, level, generator, generatorUnbound, e);
LOGGER.error("Iris failed to remove runtime dimension '{}'", dimensionId, e);
ModdedIrisLog.error("Iris failed to remove runtime dimension '{}'", dimensionId, e);
throw new IllegalStateException("Iris runtime dimension removal failed for " + dimensionId, e);
}
}
@@ -256,7 +253,7 @@ public final class ModdedDimensionManager {
if (rollbackFailure != failure) {
failure.addSuppressed(rollbackFailure);
}
LOGGER.error("Iris failed to restore the engine for retained runtime dimension '{}'",
ModdedIrisLog.error("Iris failed to restore the engine for retained runtime dimension '{}'",
key.identifier(), rollbackFailure);
}
}
@@ -282,7 +279,7 @@ public final class ModdedDimensionManager {
.whenComplete((Object result, Throwable error) -> server.execute(() -> {
level.getChunkSource().removeTicketWithRadius(TELEPORT_WARM_TICKET, chunkPos, 1);
if (error != null) {
LOGGER.warn("Iris chunk warm for teleport into '{}' at {},{} failed: {}", dimensionId, chunkPos.x(), chunkPos.z(), error.toString());
ModdedIrisLog.warn("Iris chunk warm for teleport into '{}' at {},{} failed: {}", dimensionId, chunkPos.x(), chunkPos.z(), error.toString());
}
ServerPlayer target = server.getPlayerList().getPlayer(playerId);
if (target == null) {
@@ -325,7 +322,7 @@ public final class ModdedDimensionManager {
}
return dimension;
} catch (Throwable e) {
LOGGER.error("Iris could not load pack '{}' dimension '{}' for dimension type resolution",
ModdedIrisLog.error("Iris could not load pack '{}' dimension '{}' for dimension type resolution",
pack, packDimensionKey, e);
if (e instanceof Error fatalError) {
throw fatalError;
@@ -401,19 +398,19 @@ public final class ModdedDimensionManager {
}
} catch (Throwable cleanupError) {
failure.addSuppressed(cleanupError);
LOGGER.error("Iris failed to remove a partially injected level for {}", key.identifier(), cleanupError);
ModdedIrisLog.error("Iris failed to remove a partially injected level for {}", key.identifier(), cleanupError);
}
try {
generator.unbindEngine(level);
} catch (Throwable cleanupError) {
failure.addSuppressed(cleanupError);
LOGGER.error("Iris failed to close a partially bound engine for {}", key.identifier(), cleanupError);
ModdedIrisLog.error("Iris failed to close a partially bound engine for {}", key.identifier(), cleanupError);
}
try {
level.close();
} catch (Throwable cleanupError) {
failure.addSuppressed(cleanupError);
LOGGER.error("Iris failed to close a partially injected level for {}", key.identifier(), cleanupError);
ModdedIrisLog.error("Iris failed to close a partially injected level for {}", key.identifier(), cleanupError);
}
}
@@ -22,8 +22,6 @@ import art.arcane.volmlib.util.json.JSONArray;
import art.arcane.volmlib.util.json.JSONObject;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.storage.LevelResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.channels.FileChannel;
@@ -41,7 +39,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class ModdedDimensionRegistryStore {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String FILE_NAME = "iris-dimensions.json";
private static final Pattern ID_FIELD = Pattern.compile("\"id\"\\s*:\\s*\"([^\"]+)\"");
@@ -68,13 +65,13 @@ public final class ModdedDimensionRegistryStore {
try {
return load(file);
} catch (RuntimeException corrupt) {
LOGGER.error("Iris persistent dimension registry at {} is corrupt; quarantining it and continuing boot",
ModdedIrisLog.error("Iris persistent dimension registry at {} is corrupt; quarantining it and continuing boot",
file, corrupt);
List<String> lostIds = salvageIds(file);
if (lostIds.isEmpty()) {
LOGGER.error("Iris could not recover any dimension ids from the corrupt registry; re-create the worlds with /iris world create");
ModdedIrisLog.error("Iris could not recover any dimension ids from the corrupt registry; re-create the worlds with /iris world create");
} else {
LOGGER.error("Iris lost {} persistent dimension(s) from the corrupt registry: {}",
ModdedIrisLog.error("Iris lost {} persistent dimension(s) from the corrupt registry: {}",
lostIds.size(), String.join(", ", lostIds));
}
quarantine(file);
@@ -93,7 +90,7 @@ public final class ModdedDimensionRegistryStore {
}
}
} catch (IOException | RuntimeException unreadable) {
LOGGER.warn("Iris could not scan the corrupt persistent dimension registry at {} for lost ids", file, unreadable);
ModdedIrisLog.warn("Iris could not scan the corrupt persistent dimension registry at {} for lost ids", file, unreadable);
}
return ids;
}
@@ -102,9 +99,9 @@ public final class ModdedDimensionRegistryStore {
Path broken = file.resolveSibling(FILE_NAME + ".broken-" + System.currentTimeMillis());
try {
Files.move(file, broken, StandardCopyOption.REPLACE_EXISTING);
LOGGER.error("Iris moved the corrupt persistent dimension registry to {}", broken);
ModdedIrisLog.error("Iris moved the corrupt persistent dimension registry to {}", broken);
} catch (IOException failure) {
LOGGER.error("Iris could not quarantine the corrupt persistent dimension registry at {}; delete it by hand",
ModdedIrisLog.error("Iris could not quarantine the corrupt persistent dimension registry at {}; delete it by hand",
file, failure);
}
}
@@ -134,14 +131,14 @@ public final class ModdedDimensionRegistryStore {
PersistentDimension previous = deduplicated.putIfAbsent(
id, new PersistentDimension(id, pack, dimension, entry.getLong("seed")));
if (previous != null) {
LOGGER.warn("Iris persistent dimension registry entry {} in {} duplicates id '{}'; keeping the first",
ModdedIrisLog.warn("Iris persistent dimension registry entry {} in {} duplicates id '{}'; keeping the first",
index, file, id);
}
} catch (RuntimeException invalidEntry) {
if (raw != null) {
unparsed.add(raw);
}
LOGGER.warn("Iris persistent dimension registry entry {} in {} is invalid ({}); kept verbatim: {}",
ModdedIrisLog.warn("Iris persistent dimension registry entry {} in {} is invalid ({}); kept verbatim: {}",
index, file, invalidEntry.getMessage(), raw);
}
}
@@ -23,8 +23,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -35,7 +33,6 @@ import java.util.List;
import java.util.stream.Stream;
public final class ModdedDimensionStorage {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final List<String> CHUNK_DATA_FOLDERS = List.of("region", "entities", "poi", "mantle");
private ModdedDimensionStorage() {
@@ -56,7 +53,7 @@ public final class ModdedDimensionStorage {
"Iris failed to completely wipe dimension storage at "
+ storageFolder.getAbsolutePath(), e);
}
LOGGER.info("Iris wiped dimension storage at {}", storageFolder.getAbsolutePath());
ModdedIrisLog.info("Iris wiped dimension storage at {}", storageFolder.getAbsolutePath());
}
private static void deleteRecursively(Path root) throws IOException {
@@ -55,13 +55,10 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.storage.LevelData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayDeque;
public final class ModdedEngineBootstrap {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String[] CORE_SELF_TEST_CLASSES = {
"art.arcane.iris.engine.IrisEngine",
"art.arcane.iris.util.common.data.B",
@@ -156,7 +153,7 @@ public final class ModdedEngineBootstrap {
try {
generator.unbindEngine(level);
} catch (Throwable exception) {
LOGGER.error("Iris engine unload failed for {}", level.dimension().identifier(), exception);
ModdedIrisLog.error("Iris engine unload failed for {}", level.dimension().identifier(), exception);
if (exception instanceof RuntimeException runtimeException) {
throw runtimeException;
}
@@ -207,7 +204,7 @@ public final class ModdedEngineBootstrap {
if (failure != null) {
// The shutdown path must not propagate: propagating aborts the remaining loader stop handlers and
// can leave the level unsaved. Every stage already logged its own failure.
LOGGER.error("Iris modded shutdown completed with failures", failure);
ModdedIrisLog.error("Iris modded shutdown completed with failures", failure);
}
}
@@ -216,7 +213,7 @@ public final class ModdedEngineBootstrap {
action.run();
return failure;
} catch (Throwable stageFailure) {
LOGGER.error("Iris modded shutdown stage '{}' failed", stage, stageFailure);
ModdedIrisLog.error("Iris modded shutdown stage '{}' failed", stage, stageFailure);
if (failure == null) {
return stageFailure;
}
@@ -255,7 +252,7 @@ public final class ModdedEngineBootstrap {
BlockPos position = reconciledSpawnPosition(surfaceY, level.getMinY(), level.getHeight());
server.setRespawnData(LevelData.RespawnData.of(
level.dimension(), position, current.yaw(), current.pitch()));
LOGGER.info("Iris spawn reconciled for {} at {},{},{}", dimensionId,
ModdedIrisLog.info("Iris spawn reconciled for {} at {},{},{}", dimensionId,
position.getX(), position.getY(), position.getZ());
}
@@ -321,7 +318,7 @@ public final class ModdedEngineBootstrap {
Class.forName(className, true, classLoader);
loadedClasses++;
} catch (Throwable error) {
LOGGER.error("Iris core self-test failed to initialize {}", className, error);
ModdedIrisLog.error("Iris core self-test failed to initialize {}", className, error);
}
}
@@ -404,7 +401,7 @@ public final class ModdedEngineBootstrap {
ModdedIrisSplash.print(boundLoader);
} catch (Throwable splashFailure) {
// A cosmetic banner must never roll back the platform bind.
LOGGER.warn("Iris splash could not be printed", splashFailure);
ModdedIrisLog.warn("Iris splash could not be printed", splashFailure);
}
createdServices.enableAll();
runtime = new BoundRuntime(created, createdServices);
@@ -413,7 +410,7 @@ public final class ModdedEngineBootstrap {
} catch (Throwable failure) {
createdServices.rollback(failure);
rollback.restore(failure);
LOGGER.error("Iris modded platform binding failed", failure);
ModdedIrisLog.error("Iris modded platform binding failed", failure);
if (failure instanceof RuntimeException runtimeException) {
throw runtimeException;
}
@@ -39,8 +39,6 @@ import net.minecraft.server.packs.PathPackResources;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackSource;
import net.minecraft.server.packs.repository.RepositorySource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -67,7 +65,6 @@ import java.util.function.Consumer;
import java.util.stream.Stream;
public final class ModdedForcedDatapack {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String PACK_ID = "iris_worldgen";
private static final String PACK_FOLDER = "iris";
private static final String HASH_FILE_NAME = "packs.hash";
@@ -111,7 +108,7 @@ public final class ModdedForcedDatapack {
return requireReadablePack(current.directory());
} catch (RuntimeException unreadable) {
published = null;
LOGGER.error("Iris could not read the published forced datapack at {}; regenerating",
ModdedIrisLog.error("Iris could not read the published forced datapack at {}; regenerating",
current.directory(), unreadable);
}
}
@@ -125,19 +122,19 @@ public final class ModdedForcedDatapack {
reason = "stale cache (hash changed)";
} else {
if (hash.isEmpty() && STALE_SERVE_LOGGED.compareAndSet(false, true)) {
LOGGER.warn("Iris cannot hash the installed packs; serving the last generated forced datapack from {} unverified",
ModdedIrisLog.warn("Iris cannot hash the installed packs; serving the last generated forced datapack from {} unverified",
state.directory());
}
try {
return requireReadablePack(state.directory());
} catch (RuntimeException unreadable) {
published = null;
LOGGER.error("Iris could not read the published forced datapack at {}; regenerating",
ModdedIrisLog.error("Iris could not read the published forced datapack at {}; regenerating",
state.directory(), unreadable);
}
reason = "unreadable published pack";
}
LOGGER.info("Iris forced datapack cache is unusable ({}); generating it once now", reason);
ModdedIrisLog.info("Iris forced datapack cache is unusable ({}); generating it once now", reason);
return buildPack();
}
}
@@ -151,11 +148,11 @@ public final class ModdedForcedDatapack {
if (packs.isEmpty()) {
return;
}
LOGGER.error("===============================================================");
LOGGER.error("Iris forced datapack '{}' was never loaded by this server.", PACK_ID);
LOGGER.error("{} installed pack(s) at {} contributed no dimension types or custom biomes.", packs.size(), packsRoot);
LOGGER.error("Datapack source injection failed for this loader (mixin/event not applied), so world creation will fail and restarting will not fix it.");
LOGGER.error("===============================================================");
ModdedIrisLog.error("===============================================================");
ModdedIrisLog.error("Iris forced datapack '{}' was never loaded by this server.", PACK_ID);
ModdedIrisLog.error("{} installed pack(s) at {} contributed no dimension types or custom biomes.", packs.size(), packsRoot);
ModdedIrisLog.error("Datapack source injection failed for this loader (mixin/event not applied), so world creation will fail and restarting will not fix it.");
ModdedIrisLog.error("===============================================================");
}
public static Path datapackRoot() {
@@ -172,7 +169,7 @@ public final class ModdedForcedDatapack {
} catch (RuntimeException | Error generationFailure) {
Path lastKnownGood = packDirectory();
if (Files.isRegularFile(lastKnownGood.resolve("pack.mcmeta"))) {
LOGGER.error("Iris kept the last known-good generated datapack after regeneration failed",
ModdedIrisLog.error("Iris kept the last known-good generated datapack after regeneration failed",
generationFailure);
return requireReadablePack(lastKnownGood);
}
@@ -201,7 +198,7 @@ public final class ModdedForcedDatapack {
try {
return write();
} catch (Throwable e) {
LOGGER.error("Iris failed to generate the forced startup datapack", e);
ModdedIrisLog.error("Iris failed to generate the forced startup datapack", e);
if (e instanceof RuntimeException runtimeException) {
throw runtimeException;
}
@@ -222,10 +219,10 @@ public final class ModdedForcedDatapack {
String currentHash = packsHashOrEmpty();
PublishedState state = publishedState();
if (state != null && !currentHash.isEmpty() && state.packsHash().equals(currentHash)) {
LOGGER.debug("Iris forced datapack is current ({}); skipping regeneration", reason);
ModdedIrisLog.debug("Iris forced datapack is current ({}); skipping regeneration", reason);
return false;
}
LOGGER.info("Iris regenerating the forced datapack ({})", reason);
ModdedIrisLog.info("Iris regenerating the forced datapack ({})", reason);
regenerate();
return true;
}
@@ -240,7 +237,7 @@ public final class ModdedForcedDatapack {
try {
regenerateIfStale(reason);
} catch (Throwable failure) {
LOGGER.error("Iris forced datapack regeneration failed ({})", reason, failure);
ModdedIrisLog.error("Iris forced datapack regeneration failed ({})", reason, failure);
}
};
ModdedScheduler scheduler = ModdedEngineBootstrap.schedulerOrNull();
@@ -301,7 +298,7 @@ public final class ModdedForcedDatapack {
try {
return Files.readString(hashFile, StandardCharsets.UTF_8).trim();
} catch (IOException unreadable) {
LOGGER.warn("Iris could not read the forced datapack hash at {}", hashFile, unreadable);
ModdedIrisLog.warn("Iris could not read the forced datapack hash at {}", hashFile, unreadable);
return "";
}
}
@@ -332,7 +329,7 @@ public final class ModdedForcedDatapack {
try {
hash = packsHash();
} catch (IOException | RuntimeException failure) {
LOGGER.warn("Iris could not hash the installed packs directory", failure);
ModdedIrisLog.warn("Iris could not hash the installed packs directory", failure);
hash = "";
}
packsHashMemo = new HashMemo(hash, now);
@@ -412,9 +409,9 @@ public final class ModdedForcedDatapack {
if (!presetIds.isEmpty()) {
writeWorldPresetTag(stagingDirectory, presetIds);
}
LOGGER.info("Iris forced startup datapack staged: {} pack(s), {} world preset(s), {} custom biome(s) at {}", packCount, presetIds.size(), countBiomes(seenBiomes), stagingDirectory);
ModdedIrisLog.info("Iris forced startup datapack staged: {} pack(s), {} world preset(s), {} custom biome(s) at {}", packCount, presetIds.size(), countBiomes(seenBiomes), stagingDirectory);
if (packCount == 0) {
LOGGER.warn("Iris installed NO worldgen packs into the forced datapack - custom biomes and their colors will NOT generate. Install a pack with /iris download pack=overworld, /iris download pack=underworld, or /iris download link=<zip-url>, then restart before creating an Iris world.");
ModdedIrisLog.warn("Iris installed NO worldgen packs into the forced datapack - custom biomes and their colors will NOT generate. Install a pack with /iris download pack=overworld, /iris download pack=underworld, or /iris download link=<zip-url>, then restart before creating an Iris world.");
}
}
@@ -425,13 +422,13 @@ public final class ModdedForcedDatapack {
try {
validation = PackValidator.validateForDatapackBootstrap(sourcePack);
} catch (Throwable validationFailure) {
LOGGER.error("Iris excluded pack '{}' from Create World because validation failed",
ModdedIrisLog.error("Iris excluded pack '{}' from Create World because validation failed",
sourcePack.getName(), validationFailure);
rethrowIfUnrecoverable(validationFailure);
return false;
}
if (!validation.isLoadable()) {
LOGGER.error("Iris excluded pack '{}' from Create World: {} blocking validation error(s); first error: {}",
ModdedIrisLog.error("Iris excluded pack '{}' from Create World: {} blocking validation error(s); first error: {}",
sourcePack.getName(), validation.getBlockingErrors().size(),
validation.getBlockingErrors().getFirst());
return false;
@@ -447,7 +444,7 @@ public final class ModdedForcedDatapack {
try {
installed = installPack(sourcePack, fixer, packFolders, packBiomes, packPresetIds);
} catch (Throwable installationFailure) {
LOGGER.error("Iris excluded pack '{}' from Create World because datapack serialization failed",
ModdedIrisLog.error("Iris excluded pack '{}' from Create World because datapack serialization failed",
sourcePack.getName(), installationFailure);
rethrowIfUnrecoverable(installationFailure);
installed = false;
@@ -465,7 +462,7 @@ public final class ModdedForcedDatapack {
try {
clean(packStagingDirectory);
} catch (Throwable cleanupFailure) {
LOGGER.warn("Iris could not remove temporary datapack staging for pack '{}'",
ModdedIrisLog.warn("Iris could not remove temporary datapack staging for pack '{}'",
sourcePack.getName(), cleanupFailure);
}
}
@@ -728,7 +725,7 @@ public final class ModdedForcedDatapack {
try {
clean(backupDirectory);
} catch (Throwable cleanupError) {
LOGGER.warn("Iris published the forced datapack but could not remove backup {}",
ModdedIrisLog.warn("Iris published the forced datapack but could not remove backup {}",
backupDirectory, cleanupError);
}
}
@@ -18,8 +18,6 @@
package art.arcane.iris.modded;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -42,7 +40,6 @@ import java.util.concurrent.atomic.AtomicReference;
* missing hop serializes generation on the loader's chunk threads.
*/
public final class ModdedGenPool {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final long SHUTDOWN_DRAIN_MILLIS = 2_000L;
private static final String[] C2ME_MARKERS = {
"com.ishland.c2me.base.ModProperties",
@@ -116,7 +113,7 @@ public final class ModdedGenPool {
if (pool.awaitTermination(SHUTDOWN_DRAIN_MILLIS, TimeUnit.MILLISECONDS)) {
return;
}
LOGGER.debug("Iris gen pool did not drain in {}ms, forcing shutdown", SHUTDOWN_DRAIN_MILLIS);
ModdedIrisLog.debug("Iris gen pool did not drain in {}ms, forcing shutdown", SHUTDOWN_DRAIN_MILLIS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
@@ -131,7 +128,7 @@ public final class ModdedGenPool {
if (detected == null) {
detected = new ChunkSystem(false, "vanilla");
}
LOGGER.info("Iris chunk system: {} (parallel={}, generation on {})",
ModdedIrisLog.info("Iris chunk system: {} (parallel={}, generation on {})",
detected.description(),
detected.parallel() ? "yes" : "no",
detected.parallel() ? "loader threads" : "Iris gen pool");
@@ -182,7 +179,7 @@ public final class ModdedGenPool {
try {
value = field.get(null);
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not read {}.{}: {}", configClass.getName(), section, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not read {}.{}: {}", configClass.getName(), section, e.toString());
continue;
}
if (value instanceof Boolean flag) {
@@ -209,7 +206,7 @@ public final class ModdedGenPool {
return flag;
}
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not read {}.{}: {}", type.getName(), name, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not read {}.{}: {}", type.getName(), name, e.toString());
}
}
Method method = declaredMethodOrNull(type, name);
@@ -219,7 +216,7 @@ public final class ModdedGenPool {
return flag;
}
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not call {}.{}(): {}", type.getName(), name, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not call {}.{}(): {}", type.getName(), name, e.toString());
}
}
}
@@ -241,7 +238,7 @@ public final class ModdedGenPool {
return number.intValue();
}
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not read {}.{}: {}", marker.getName(), name, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not read {}.{}: {}", marker.getName(), name, e.toString());
}
}
}
@@ -254,7 +251,7 @@ public final class ModdedGenPool {
try {
pool = field.get(null);
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not read {}.{}: {}", marker.getName(), poolName, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not read {}.{}: {}", marker.getName(), poolName, e.toString());
continue;
}
if (pool == null) {
@@ -281,7 +278,7 @@ public final class ModdedGenPool {
return number.intValue();
}
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not call {}.{}(): {}", current.getName(), name, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not call {}.{}(): {}", current.getName(), name, e.toString());
}
}
return null;
@@ -305,7 +302,7 @@ public final class ModdedGenPool {
} catch (NoSuchFieldException e) {
return null;
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not access field {}.{}: {}", type.getName(), name, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not access field {}.{}: {}", type.getName(), name, e.toString());
return null;
}
}
@@ -318,7 +315,7 @@ public final class ModdedGenPool {
} catch (NoSuchMethodException e) {
return null;
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe could not access method {}.{}(): {}", type.getName(), name, e.toString());
ModdedIrisLog.debug("Iris chunk system probe could not access method {}.{}(): {}", type.getName(), name, e.toString());
return null;
}
}
@@ -336,7 +333,7 @@ public final class ModdedGenPool {
try {
return Class.forName(name, false, ModdedGenPool.class.getClassLoader());
} catch (Throwable e) {
LOGGER.debug("Iris chunk system probe: {} absent ({})", name, e.getClass().getSimpleName());
ModdedIrisLog.debug("Iris chunk system probe: {} absent ({})", name, e.getClass().getSimpleName());
return null;
}
}
@@ -46,8 +46,6 @@ import net.minecraft.world.level.levelgen.RandomSupport;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.XoroshiroRandomSource;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -76,7 +74,6 @@ import java.util.concurrent.locks.ReentrantLock;
* {@link #generationSettings} answers exactly what vanilla's default getter answers.
*/
final class ModdedImportedFeatureStage {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String CYCLE_MARKER = "Feature order cycle found";
private static final long NO_GENERATION = Long.MIN_VALUE;
@@ -179,7 +176,7 @@ final class ModdedImportedFeatureStage {
try {
control = NativeFeatureGenerationPolicy.control(engine);
} catch (RuntimeException error) {
LOGGER.error("Iris could not read importedFeatures for this dimension; features off: {}",
ModdedIrisLog.error("Iris could not read importedFeatures for this dimension; features off: {}",
error.toString());
markInert(generation);
return;
@@ -193,7 +190,7 @@ final class ModdedImportedFeatureStage {
IrisContext.Scope ignored = IrisContext.open(engine, lease.sessionId(), null)) {
built = buildTable(engine, control, generation);
} catch (Throwable error) {
LOGGER.error("Iris importedFeatures is off for {}: feature table construction failed: {}",
ModdedIrisLog.error("Iris importedFeatures is off for {}: feature table construction failed: {}",
dimensionKey(engine), error.toString());
markInert(generation);
return;
@@ -207,7 +204,7 @@ final class ModdedImportedFeatureStage {
// Arm the worldcheck log watch here, before any chunk decorates: arming from the first pass instead
// missed every far-chunk write the first chunk made. No-op unless -Diris.worldcheck is set.
WorldCheckFeaturePlacement.arm();
LOGGER.info("Iris importedFeatures on for {}: {} biomes, {} steps, {} custom-biome derivative maps",
ModdedIrisLog.info("Iris importedFeatures on for {}: {} biomes, {} steps, {} custom-biome derivative maps",
dimensionKey(engine), built.biomes().size(), built.steps().size(),
built.derivatives().size());
}
@@ -222,7 +219,7 @@ final class ModdedImportedFeatureStage {
// detection depend on JVM hash order and turns a real cycle into an intermittent one.
List<Holder<Biome>> biomes = biomeSource.orderedPossibleBiomes();
if (biomes.isEmpty()) {
LOGGER.error("Iris importedFeatures is on but {} exposes no biomes; features off",
ModdedIrisLog.error("Iris importedFeatures is on but {} exposes no biomes; features off",
dimensionKey(engine));
return null;
}
@@ -245,7 +242,7 @@ final class ModdedImportedFeatureStage {
if (message == null || !message.contains(CYCLE_MARKER)) {
throw error;
}
LOGGER.error("Iris importedFeatures is off for {}: the registered placed features cannot be ordered."
ModdedIrisLog.error("Iris importedFeatures is off for {}: the registered placed features cannot be ordered."
+ " {}. Remove or reorder the conflicting content, or leave"
+ " importedFeatures.enabled false.",
dimensionKey(engine), message);
@@ -276,7 +273,7 @@ final class ModdedImportedFeatureStage {
derivative = biomeSource.registeredBiome(derivativeKey);
}
if (derivative == null) {
LOGGER.warn("Iris importedFeatures: vanilla derivative {} of biome {} is not registered;"
ModdedIrisLog.warn("Iris importedFeatures: vanilla derivative {} of biome {} is not registered;"
+ " its custom biomes generate no imported features",
derivativeKey, irisBiome.getLoadKey());
continue;
@@ -54,18 +54,55 @@ public final class ModdedIrisLog {
LOGGER.info("[Iris/DEBUG] " + clean(message));
}
public static void debug(String format, Object... arguments) {
RenderedLog rendered = render(format, arguments);
if (rendered.error() == null) {
debug(rendered.message());
return;
}
if (!debugEnabled()) {
LOGGER.debug(clean(rendered.message()), rendered.error());
return;
}
LOGGER.info("[Iris/DEBUG] " + clean(rendered.message()), rendered.error());
}
public static void info(String message) {
LOGGER.info(clean(message));
}
public static void info(String format, Object... arguments) {
RenderedLog rendered = render(format, arguments);
if (rendered.error() != null) {
LOGGER.info(clean(rendered.message()), rendered.error());
return;
}
info(rendered.message());
}
public static void warn(String message) {
LOGGER.warn(clean(message));
}
public static void warn(String format, Object... arguments) {
RenderedLog rendered = render(format, arguments);
if (rendered.error() != null) {
LOGGER.warn(clean(rendered.message()), rendered.error());
return;
}
warn(rendered.message());
}
public static void error(String message) {
LOGGER.error(clean(message));
}
public static void error(String format, Object... arguments) {
RenderedLog rendered = render(format, arguments);
error(rendered.message(), rendered.error());
}
public static void error(String message, Throwable error) {
if (error == null) {
error(message);
@@ -79,6 +116,34 @@ public final class ModdedIrisLog {
return IrisLogging.clean(message);
}
static RenderedLog render(String format, Object... arguments) {
String source = format == null ? "null" : format;
if (arguments == null || arguments.length == 0) {
return new RenderedLog(source, null);
}
int argumentCount = arguments.length;
Throwable error = arguments[argumentCount - 1] instanceof Throwable throwable ? throwable : null;
if (error != null) {
argumentCount--;
}
StringBuilder output = new StringBuilder(source.length() + argumentCount * 8);
int cursor = 0;
int argumentIndex = 0;
while (argumentIndex < argumentCount) {
int placeholder = source.indexOf("{}", cursor);
if (placeholder < 0) {
break;
}
output.append(source, cursor, placeholder);
output.append(String.valueOf(arguments[argumentIndex++]));
cursor = placeholder + 2;
}
output.append(source, cursor, source.length());
return new RenderedLog(output.toString(), error);
}
private static boolean debugEnabled() {
try {
IrisSettings settings = IrisSettings.settings != null ? IrisSettings.settings : IrisSettings.get();
@@ -97,4 +162,7 @@ public final class ModdedIrisLog {
DEBUG_SETTING_WARNING_LOGGED = true;
LOGGER.warn("Iris debug logging setting could not be read", error);
}
record RenderedLog(String message, Throwable error) {
}
}
@@ -18,8 +18,6 @@
package art.arcane.iris.modded;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -40,7 +38,6 @@ import java.util.function.BooleanSupplier;
* references and is safe on a dedicated server.
*/
public final class ModdedMixinAudit {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final AtomicBoolean AUDITED = new AtomicBoolean(false);
private static final List<ExpectedMixin> EXPECTED = List.of(
@@ -95,20 +92,20 @@ public final class ModdedMixinAudit {
}
}
if (missing.isEmpty()) {
LOGGER.info("Iris mixin audit ok on {} ({} dist): {}", platform,
ModdedIrisLog.info("Iris mixin audit ok on {} ({} dist): {}", platform,
clientEnvironment ? "client" : "server", String.join(", ", applied));
return;
}
LOGGER.error("===============================================================");
LOGGER.error("Iris mixin audit FAILED on {} ({} dist): {} of {} expected mixin(s) were not applied.",
ModdedIrisLog.error("===============================================================");
ModdedIrisLog.error("Iris mixin audit FAILED on {} ({} dist): {} of {} expected mixin(s) were not applied.",
platform, clientEnvironment ? "client" : "server", missing.size(),
missing.size() + applied.size());
for (String entry : missing) {
LOGGER.error(" missing: {}", entry);
ModdedIrisLog.error(" missing: {}", entry);
}
LOGGER.error("The mixin config was not registered for this loader (fabric.mod.json mixins, neoforge.mods.toml [[mixins]], forge MixinConfigs manifest attribute).");
LOGGER.error("Entity persistence, custom mob loot, parallel structure safety, or Iris world-type labels are disabled until this is fixed.");
LOGGER.error("===============================================================");
ModdedIrisLog.error("The mixin config was not registered for this loader (fabric.mod.json mixins, neoforge.mods.toml [[mixins]], forge MixinConfigs manifest attribute).");
ModdedIrisLog.error("Entity persistence, custom mob loot, parallel structure safety, or Iris world-type labels are disabled until this is fixed.");
ModdedIrisLog.error("===============================================================");
}
private static boolean isApplied(ExpectedMixin expected) {
@@ -126,7 +123,7 @@ public final class ModdedMixinAudit {
}
return false;
} catch (ClassNotFoundException | LinkageError unavailable) {
LOGGER.warn("Iris mixin audit could not inspect {}", expected.targetClass(), unavailable);
ModdedIrisLog.warn("Iris mixin audit could not inspect {}", expected.targetClass(), unavailable);
return true;
}
}
@@ -24,11 +24,8 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class ModdedModConfig {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Object LOCK = new Object();
private static volatile ModdedModConfig instance;
@@ -128,7 +125,7 @@ public final class ModdedModConfig {
json.optLong("mainWorldSeed", defaults.mainWorldSeed),
json.optBoolean("mainWorldAutoRestart", defaults.mainWorldAutoRestart));
} catch (RuntimeException | IOException e) {
LOGGER.error("Iris modded config at {} is invalid; using defaults", file, e);
ModdedIrisLog.error("Iris modded config at {} is invalid; using defaults", file, e);
return defaults;
}
}
@@ -145,7 +142,7 @@ public final class ModdedModConfig {
Files.createDirectories(file.getParent());
Files.writeString(file, json.toString(4), StandardCharsets.UTF_8);
} catch (IOException e) {
LOGGER.error("Iris failed to write modded config at {}", file, e);
ModdedIrisLog.error("Iris failed to write modded config at {}", file, e);
}
}
}
@@ -29,8 +29,6 @@ import art.arcane.iris.spi.PlatformBiome;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.iris.util.project.hunk.Hunk;
import net.minecraft.server.MinecraftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.nio.charset.StandardCharsets;
@@ -48,7 +46,6 @@ import java.util.Map;
import java.util.TreeMap;
public final class ModdedParityProbe {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String DIMENSION_KEY = "overworld";
private static final long SEED = 1337L;
private static final int BIOME_STEP = 4;
@@ -82,7 +79,7 @@ public final class ModdedParityProbe {
}
if (server == null) {
LOGGER.error("[parity] server did not become ready within 10 minutes");
ModdedIrisLog.error("[parity] server did not become ready within 10 minutes");
return;
}
@@ -90,10 +87,10 @@ public final class ModdedParityProbe {
try {
match = run(server, config);
} catch (Throwable e) {
LOGGER.error("[parity] probe failed", e);
ModdedIrisLog.error("[parity] probe failed", e);
}
LOGGER.info("[parity] shutting down dev server (result={})", match ? "MATCH" : "MISMATCH");
ModdedIrisLog.info("[parity] shutting down dev server (result={})", match ? "MATCH" : "MISMATCH");
server.halt(false);
}
@@ -112,7 +109,7 @@ public final class ModdedParityProbe {
File packSource = new File(packPath);
if (!packSource.isDirectory()) {
LOGGER.error("[parity] pack folder not found: {}", packSource.getAbsolutePath());
ModdedIrisLog.error("[parity] pack folder not found: {}", packSource.getAbsolutePath());
return false;
}
@@ -121,14 +118,14 @@ public final class ModdedParityProbe {
File workRoot = Files.createTempDirectory("iris-parity").toFile();
File pack = clonePack(packSource, workRoot);
LOGGER.info("[parity] pack: {}", packSource.getAbsolutePath());
LOGGER.info("[parity] work copy: {}", pack.getAbsolutePath());
LOGGER.info("[parity] radius: {} ({} chunks)", radius, (2 * radius + 1) * (2 * radius + 1));
ModdedIrisLog.info("[parity] pack: {}", packSource.getAbsolutePath());
ModdedIrisLog.info("[parity] work copy: {}", pack.getAbsolutePath());
ModdedIrisLog.info("[parity] radius: {} ({} chunks)", radius, (2 * radius + 1) * (2 * radius + 1));
IrisData data = IrisData.get(pack);
IrisDimension dimension = data.getDimensionLoader().load(DIMENSION_KEY);
if (dimension == null) {
LOGGER.error("[parity] dimension '{}' did not load from {}", DIMENSION_KEY, pack.getAbsolutePath());
ModdedIrisLog.error("[parity] dimension '{}' did not load from {}", DIMENSION_KEY, pack.getAbsolutePath());
return false;
}
@@ -147,7 +144,7 @@ public final class ModdedParityProbe {
int minY = dimension.getMinHeight();
int maxY = dimension.getMaxHeight();
int height = maxY - minY;
LOGGER.info("[parity] engine up: dim={} seed={} minY={} maxY={}", engine.getDimension().getLoadKey(), engine.getSeedManager().getSeed(), minY, maxY);
ModdedIrisLog.info("[parity] engine up: dim={} seed={} minY={} maxY={}", engine.getDimension().getLoadKey(), engine.getSeedManager().getSeed(), minY, maxY);
Map<String, String> goldenChunks = new HashMap<>();
String goldenCombined = null;
@@ -173,7 +170,7 @@ public final class ModdedParityProbe {
goldenChunks.put(line.substring(0, second), line);
}
}
LOGGER.info("[parity] golden: {} ({} chunks, combined={})", goldenPath, goldenChunks.size(), goldenCombined);
ModdedIrisLog.info("[parity] golden: {} ({} chunks, combined={})", goldenPath, goldenChunks.size(), goldenCombined);
}
PlatformBlockState airState = IrisPlatforms.get().registries().air();
@@ -198,9 +195,9 @@ public final class ModdedParityProbe {
if (!failures.isEmpty()) {
failed++;
LOGGER.error("[parity] chunk {},{} FAILED ({} error(s))", cx, cz, failures.size());
ModdedIrisLog.error("[parity] chunk {},{} FAILED ({} error(s))", cx, cz, failures.size());
for (Throwable failure : failures) {
LOGGER.error("[parity] chunk {},{} error", cx, cz, failure);
ModdedIrisLog.error("[parity] chunk {},{} error", cx, cz, failure);
}
continue;
}
@@ -212,9 +209,9 @@ public final class ModdedParityProbe {
String golden = goldenChunks.get(key);
if (golden != null && !golden.equals(line)) {
mismatches.add(key);
LOGGER.warn("[parity] chunk {} MISMATCH", key);
LOGGER.warn("[parity] golden: {}", golden);
LOGGER.warn("[parity] actual: {}", line);
ModdedIrisLog.warn("[parity] chunk {} MISMATCH", key);
ModdedIrisLog.warn("[parity] golden: {}", golden);
ModdedIrisLog.warn("[parity] actual: {}", line);
if (mismatches.size() == 1) {
diffDeep(cx, cz, blocks, height, minY);
}
@@ -231,9 +228,9 @@ public final class ModdedParityProbe {
boolean match = goldenChunks.isEmpty() ? combinedMatch : (chunkMatch && (radius != 8 || combinedMatch));
if (!goldenChunks.isEmpty()) {
LOGGER.info("[parity] per-chunk: {}/{} matched golden ({} failed)", body.size() - mismatches.size(), body.size(), failed);
ModdedIrisLog.info("[parity] per-chunk: {}/{} matched golden ({} failed)", body.size() - mismatches.size(), body.size(), failed);
}
LOGGER.info("[parity] combined={} expected={} {} ({}/{})",
ModdedIrisLog.info("[parity] combined={} expected={} {} ({}/{})",
combined.substring(0, 12), expected, match ? "MATCH" : "MISMATCH", body.size() - mismatches.size(), targets.size());
return match;
}
@@ -246,7 +243,7 @@ public final class ModdedParityProbe {
try {
Path goldenDump = Path.of(deepDir, cx + "_" + cz + ".txt");
if (!Files.exists(goldenDump)) {
LOGGER.warn("[parity] no deep dump for chunk {},{} at {}", cx, cz, goldenDump);
ModdedIrisLog.warn("[parity] no deep dump for chunk {},{} at {}", cx, cz, goldenDump);
return;
}
List<String> golden = Files.readAllLines(goldenDump, StandardCharsets.UTF_8);
@@ -267,15 +264,15 @@ public final class ModdedParityProbe {
String g = i < golden.size() ? golden.get(i) : "<missing>";
String a = i < actual.size() ? actual.get(i) : "<missing>";
if (!g.equals(a)) {
LOGGER.warn("[parity] deep diff line {}: golden='{}' actual='{}'", i, g, a);
ModdedIrisLog.warn("[parity] deep diff line {}: golden='{}' actual='{}'", i, g, a);
shown++;
}
}
File out = new File(IrisPlatforms.get().dataFolder("parity"), "deep-" + cx + "_" + cz + ".txt");
Files.write(out.toPath(), actual, StandardCharsets.UTF_8);
LOGGER.warn("[parity] full actual dump: {}", out.getAbsolutePath());
ModdedIrisLog.warn("[parity] full actual dump: {}", out.getAbsolutePath());
} catch (Throwable e) {
LOGGER.warn("[parity] deep diff failed", e);
ModdedIrisLog.warn("[parity] deep diff failed", e);
}
}
@@ -367,7 +364,7 @@ public final class ModdedParityProbe {
}
} else {
for (Throwable error : batch) {
LOGGER.warn("[parity] engine-init reported error (non-fatal)", error);
ModdedIrisLog.warn("[parity] engine-init reported error (non-fatal)", error);
}
quietSince = System.currentTimeMillis();
}
@@ -21,8 +21,6 @@ package art.arcane.iris.modded;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -31,7 +29,6 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public final class ModdedPrimaryWorldRouter {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int TICK_INTERVAL = 20;
private static final Set<UUID> routed = ConcurrentHashMap.newKeySet();
@@ -96,7 +93,7 @@ public final class ModdedPrimaryWorldRouter {
ModdedDimensionManager.teleport(player, server, primary, player.getX(), Double.MIN_VALUE, player.getZ());
routed.add(id);
} catch (Throwable e) {
LOGGER.error("Iris failed to route player {} to primary world '{}'", id, primary, e);
ModdedIrisLog.error("Iris failed to route player {} to primary world '{}'", id, primary, e);
}
}
}
@@ -19,6 +19,7 @@
package art.arcane.iris.modded;
import art.arcane.iris.core.protocol.EngineResolver;
import art.arcane.iris.core.protocol.IrisCursorRequestService;
import art.arcane.iris.core.protocol.IrisProtocolServer;
import art.arcane.iris.core.protocol.IrisSession;
import art.arcane.iris.core.protocol.IrisSessionRegistry;
@@ -30,8 +31,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.UUID;
@@ -43,7 +42,6 @@ public final class ModdedProtocolHandler {
| IrisProtocol.CAPABILITY_CURSOR
| IrisProtocol.CAPABILITY_STUDIO;
private static final int DIMENSION_SYNC_INTERVAL_TICKS = 5;
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final ConcurrentHashMap<String, Engine> SESSION_ENGINES = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, String> SESSION_LEVELS = new ConcurrentHashMap<>();
@@ -53,6 +51,7 @@ public final class ModdedProtocolHandler {
private static volatile IrisSessionRegistry registry;
private static volatile IrisProtocolServer protocolServer;
private static volatile ModdedProtocolTransport transport;
private static volatile IrisCursorRequestService cursorRequests;
private static volatile IrisVisionRequestService visionRequests;
private static int dimensionSyncTicks;
@@ -80,11 +79,14 @@ public final class ModdedProtocolHandler {
return engine == null || engine.isClosed() ? null : engine;
};
protocol.setEngineResolver(engineResolver);
IrisCursorRequestService cursorService = IrisCursorRequestService.create(engineResolver, sessionRegistry);
protocol.setCursorInfoHandler(cursorService);
IrisVisionRequestService visionService = IrisVisionRequestService.create(engineResolver, sessionRegistry);
protocol.setVisionTileHandler(visionService);
registry = sessionRegistry;
transport = serverTransport;
protocolServer = protocol;
cursorRequests = cursorService;
visionRequests = visionService;
IrisServices.register(IrisProtocolServer.class, protocol);
if (server.getPlayerList() == null) {
@@ -98,10 +100,14 @@ public final class ModdedProtocolHandler {
public static void stop() {
IrisServices.remove(IrisProtocolServer.class);
IrisSessionRegistry current = registry;
IrisCursorRequestService cursor = cursorRequests;
IrisVisionRequestService vision = visionRequests;
if (current != null) {
for (IrisSession session : current.all()) {
current.unregister(session.id());
if (cursor != null) {
cursor.clearSession(session.id());
}
if (vision != null) {
vision.clearSession(session.id());
}
@@ -114,6 +120,7 @@ public final class ModdedProtocolHandler {
registry = null;
protocolServer = null;
transport = null;
cursorRequests = null;
visionRequests = null;
}
@@ -147,6 +154,10 @@ public final class ModdedProtocolHandler {
if (current != null) {
current.unregister(sessionId);
}
IrisCursorRequestService cursor = cursorRequests;
if (cursor != null) {
cursor.clearSession(sessionId);
}
IrisVisionRequestService vision = visionRequests;
if (vision != null) {
vision.clearSession(sessionId);
@@ -229,7 +240,7 @@ public final class ModdedProtocolHandler {
Engine engine = generator.engineIfBound();
return engine == null || engine.isClosed() ? null : engine;
} catch (Throwable failure) {
LOGGER.error("Iris dimension status engine lookup failed for {}", level.dimension().identifier(), failure);
ModdedIrisLog.error("Iris dimension status engine lookup failed for {}", level.dimension().identifier(), failure);
return null;
}
}
@@ -21,8 +21,6 @@ package art.arcane.iris.modded;
import art.arcane.iris.spi.PlatformScheduler;
import art.arcane.iris.spi.PlatformWorld;
import net.minecraft.server.MinecraftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -41,7 +39,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public final class ModdedScheduler implements PlatformScheduler {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int ASYNC_MAX_THREADS = Math.max(4, Runtime.getRuntime().availableProcessors());
private static final long ASYNC_KEEP_ALIVE_SECONDS = 30L;
private static final int ASYNC_BACKLOG_WARN = 8192;
@@ -85,10 +82,10 @@ public final class ModdedScheduler implements PlatformScheduler {
rejectionAwareTask.reject();
}
if (executor.isShutdown()) {
LOGGER.debug("Iris async task dropped: scheduler is shut down");
ModdedIrisLog.debug("Iris async task dropped: scheduler is shut down");
return;
}
LOGGER.error("Iris async task rejected by the executor (queued={} active={})",
ModdedIrisLog.error("Iris async task rejected by the executor (queued={} active={})",
executor.getQueue().size(), executor.getActiveCount());
};
}
@@ -217,7 +214,7 @@ public final class ModdedScheduler implements PlatformScheduler {
if (now - last < ASYNC_BACKLOG_WARN_INTERVAL_MILLIS || !lastBacklogWarnAt.compareAndSet(last, now)) {
return;
}
LOGGER.warn("Iris async backlog {} tasks (threads={}); async work is falling behind", queued, executor.getPoolSize());
ModdedIrisLog.warn("Iris async backlog {} tasks (threads={}); async work is falling behind", queued, executor.getPoolSize());
}
private void drain() {
@@ -262,7 +259,7 @@ public final class ModdedScheduler implements PlatformScheduler {
try {
task.run();
} catch (Throwable error) {
LOGGER.error("Iris scheduled task failed", error);
ModdedIrisLog.error("Iris scheduled task failed", error);
}
}
@@ -23,8 +23,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.LevelStorageSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ConcurrentModificationException;
import java.util.LinkedHashMap;
@@ -35,7 +33,6 @@ import java.util.concurrent.Executor;
import java.util.function.Consumer;
public final class ModdedServerLevels implements ModdedServerAccess {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int CAPTURE_ATTEMPTS = 16;
private static volatile Snapshot snapshot;
@@ -125,7 +122,7 @@ public final class ModdedServerLevels implements ModdedServerAccess {
Thread.onSpinWait();
}
}
LOGGER.error("Iris could not snapshot the level map after {} attempts; readers will see the previous snapshot", CAPTURE_ATTEMPTS);
ModdedIrisLog.error("Iris could not snapshot the level map after {} attempts; readers will see the previous snapshot", CAPTURE_ATTEMPTS);
Snapshot current = snapshot;
return current != null && current.server() == server ? current : null;
}
@@ -21,14 +21,11 @@ package art.arcane.iris.modded;
import art.arcane.iris.modded.service.ModdedService;
import art.arcane.iris.modded.service.ModdedTickableService;
import net.minecraft.server.MinecraftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedHashMap;
import java.util.Map;
public final class ModdedServiceManager {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private final Map<Class<? extends ModdedService>, ModdedService> services = new LinkedHashMap<>();
private boolean enabled = false;
@@ -103,7 +100,7 @@ public final class ModdedServiceManager {
service.onDisable();
} catch (Throwable serviceFailure) {
failed++;
LOGGER.error("Iris service onDisable failed for {}", service.getClass().getName(), serviceFailure);
ModdedIrisLog.error("Iris service onDisable failed for {}", service.getClass().getName(), serviceFailure);
if (failure == null) {
failure = serviceFailure;
} else if (serviceFailure != failure) {
@@ -113,7 +110,7 @@ public final class ModdedServiceManager {
}
enabled = false;
if (failure != null) {
LOGGER.error("Iris disabled all services with {} failure(s)", failed, failure);
ModdedIrisLog.error("Iris disabled all services with {} failure(s)", failed, failure);
}
}
@@ -132,7 +129,7 @@ public final class ModdedServiceManager {
try {
service.onServerTick(server);
} catch (Throwable error) {
LOGGER.error("Iris service tick failed for {}", service.getClass().getName(), error);
ModdedIrisLog.error("Iris service tick failed for {}", service.getClass().getName(), error);
}
}
@@ -143,12 +140,12 @@ public final class ModdedServiceManager {
if (cleanupError != failure) {
failure.addSuppressed(cleanupError);
}
LOGGER.error("Iris service rollback failed for {}", service.getClass().getName(), cleanupError);
ModdedIrisLog.error("Iris service rollback failed for {}", service.getClass().getName(), cleanupError);
}
}
private RuntimeException serviceFailure(ModdedService service, Throwable failure) {
LOGGER.error("Iris service onEnable failed for {}", service.getClass().getName(), failure);
ModdedIrisLog.error("Iris service onEnable failed for {}", service.getClass().getName(), failure);
if (failure instanceof RuntimeException runtimeException) {
return runtimeException;
}
@@ -29,8 +29,6 @@ import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -43,7 +41,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
public final class ModdedStartup {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final AtomicBoolean PREPARED = new AtomicBoolean(false);
private static final AtomicBoolean STARTED = new AtomicBoolean(false);
@@ -76,7 +73,7 @@ public final class ModdedStartup {
}
if (!PackDirectoryResolver.listVisiblePackDirectories(legacy).isEmpty()) {
File real = art.arcane.iris.spi.IrisPlatforms.get().packsFolderNoCreate();
LOGGER.warn("Iris found packs under the legacy directory {} - modded packs load from {} only. Move them there.",
ModdedIrisLog.warn("Iris found packs under the legacy directory {} - modded packs load from {} only. Move them there.",
legacy.getAbsolutePath(), real.getAbsolutePath());
return;
}
@@ -85,7 +82,7 @@ public final class ModdedStartup {
legacy.delete();
}
} catch (Throwable e) {
LOGGER.debug("Iris legacy packs directory check failed", e);
ModdedIrisLog.debug("Iris legacy packs directory check failed", e);
}
}
@@ -104,7 +101,7 @@ public final class ModdedStartup {
try {
ModdedForcedDatapack.regenerateIfStale("boot");
} catch (Throwable failure) {
LOGGER.error("Iris could not refresh the forced datapack at boot", failure);
ModdedIrisLog.error("Iris could not refresh the forced datapack at boot", failure);
}
}
@@ -133,7 +130,7 @@ public final class ModdedStartup {
List<File> packDirs = PackDirectoryResolver.listVisiblePackDirectories(packsRoot);
PackValidationRegistry.clear();
if (packDirs.isEmpty()) {
LOGGER.info("Iris found no packs to validate under {}; install one with /iris download pack=overworld, /iris download pack=underworld, or /iris download link=<zip-url>",
ModdedIrisLog.info("Iris found no packs to validate under {}; install one with /iris download pack=overworld, /iris download pack=underworld, or /iris download link=<zip-url>",
packsRoot.getAbsolutePath());
return;
}
@@ -142,19 +139,19 @@ public final class ModdedStartup {
PackValidationResult result = PackValidator.validate(packDir);
PackValidationRegistry.publish(result);
if (!result.isLoadable()) {
LOGGER.error("Iris pack '{}' FAILED validation with {} blocking error(s); world/studio creation will be refused. First error: {}",
ModdedIrisLog.error("Iris pack '{}' FAILED validation with {} blocking error(s); world/studio creation will be refused. First error: {}",
result.getPackName(), result.getBlockingErrors().size(),
result.getBlockingErrors().getFirst());
} else if (!result.getWarnings().isEmpty()) {
LOGGER.info("Iris pack '{}' validated ({} warning(s)).", result.getPackName(), result.getWarnings().size());
ModdedIrisLog.info("Iris pack '{}' validated ({} warning(s)).", result.getPackName(), result.getWarnings().size());
for (String warning : result.getWarnings()) {
LOGGER.warn(" [{}] {}", result.getPackName(), warning);
ModdedIrisLog.warn(" [{}] {}", result.getPackName(), warning);
}
} else {
LOGGER.info("Iris pack '{}' validated.", result.getPackName());
ModdedIrisLog.info("Iris pack '{}' validated.", result.getPackName());
}
} catch (Throwable e) {
LOGGER.error("Iris pack validation failed for '{}'", packDir.getName(), e);
ModdedIrisLog.error("Iris pack validation failed for '{}'", packDir.getName(), e);
String detail = e.getMessage();
if (detail == null || detail.isBlank()) {
detail = e.getClass().getSimpleName();
@@ -190,7 +187,7 @@ public final class ModdedStartup {
} catch (BrokenPackException e) {
throw e;
} catch (Throwable e) {
LOGGER.error("Iris required world-creation validation failed for '{}'", pack, e);
ModdedIrisLog.error("Iris required world-creation validation failed for '{}'", pack, e);
String detail = e.getMessage();
if (detail == null || detail.isBlank()) {
detail = e.getClass().getSimpleName();
@@ -220,17 +217,17 @@ public final class ModdedStartup {
try {
ModdedDimensionManager.create(server, dimension.id(), dimension.pack(), dimension.dimension(), dimension.seed());
injected++;
LOGGER.info("Iris re-injected {}/{} '{}' (pack={} dim={}) in {}ms",
ModdedIrisLog.info("Iris re-injected {}/{} '{}' (pack={} dim={}) in {}ms",
index, dimensions.size(), dimension.id(), dimension.pack(), dimension.dimension(),
System.currentTimeMillis() - dimensionStartedAt);
} catch (Throwable e) {
LOGGER.error("Iris failed to re-inject persistent dimension '{}' (pack={} dim={} seed={})", dimension.id(), dimension.pack(), dimension.dimension(), dimension.seed(), e);
ModdedIrisLog.error("Iris failed to re-inject persistent dimension '{}' (pack={} dim={} seed={})", dimension.id(), dimension.pack(), dimension.dimension(), dimension.seed(), e);
if (e instanceof OutOfMemoryError outOfMemory) {
throw outOfMemory;
}
}
}
LOGGER.info("Iris re-injected {}/{} persistent dimension(s) at startup in {}ms",
ModdedIrisLog.info("Iris re-injected {}/{} persistent dimension(s) at startup in {}ms",
injected, dimensions.size(), System.currentTimeMillis() - startedAt);
}
@@ -245,7 +242,7 @@ public final class ModdedStartup {
}
}
} catch (IOException | RuntimeException unreadable) {
LOGGER.debug("Iris could not stat {} for validation reuse; revalidating", root, unreadable);
ModdedIrisLog.debug("Iris could not stat {} for validation reuse; revalidating", root, unreadable);
return Long.MAX_VALUE;
}
return newest;
@@ -32,8 +32,6 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.levelgen.Heightmap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@@ -53,7 +51,6 @@ public final class ModdedWorldCheck {
private static final long SERVER_WAIT_TIMEOUT_MILLIS = 600000L;
private static final long SERVER_WAIT_INTERVAL_MILLIS = 250L;
private static final long SERVER_TASK_TIMEOUT_MILLIS = 900000L;
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
// halt, not exit: awaitStopAndExit already waited for MinecraftServer.halt(true), and exit() would run the
// shutdown hooks and block behind the server thread it just stopped, so a finished check could hang forever.
private static final ProcessExit PROCESS_EXIT = Runtime.getRuntime()::halt;
@@ -100,7 +97,7 @@ public final class ModdedWorldCheck {
}
if (server == null) {
LOGGER.error("[worldcheck] server did not finish starting within 10 minutes");
ModdedIrisLog.error("[worldcheck] server did not finish starting within 10 minutes");
return;
}
@@ -115,15 +112,15 @@ public final class ModdedWorldCheck {
}
)).get(SERVER_TASK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
LOGGER.error("[worldcheck] coordinator interrupted", e);
ModdedIrisLog.error("[worldcheck] coordinator interrupted", e);
Thread.currentThread().interrupt();
} catch (TimeoutException e) {
LOGGER.error("[worldcheck] server task did not finish within {}ms", SERVER_TASK_TIMEOUT_MILLIS);
ModdedIrisLog.error("[worldcheck] server task did not finish within {}ms", SERVER_TASK_TIMEOUT_MILLIS);
} catch (Throwable e) {
LOGGER.error("[worldcheck] check failed", e);
ModdedIrisLog.error("[worldcheck] check failed", e);
} finally {
int resultCode = exitCode;
LOGGER.info("[worldcheck] shutting down dev server (result={})", resultCode == EXIT_PASS ? "PASS" : "FAIL");
ModdedIrisLog.info("[worldcheck] shutting down dev server (result={})", resultCode == EXIT_PASS ? "PASS" : "FAIL");
MinecraftServer serverRef = server;
if (serverRef != null && stopRequested.get()) {
awaitStopAndExit(() -> serverRef.halt(true), resultCode, processExit);
@@ -138,12 +135,12 @@ public final class ModdedWorldCheck {
try {
exitCode = check.getAsBoolean() ? EXIT_PASS : EXIT_FAILURE;
} catch (Throwable e) {
LOGGER.error("[worldcheck] check failed", e);
ModdedIrisLog.error("[worldcheck] check failed", e);
}
try {
requestStop.run();
} catch (Throwable e) {
LOGGER.error("[worldcheck] server stop request failed", e);
ModdedIrisLog.error("[worldcheck] server stop request failed", e);
return EXIT_FAILURE;
}
return exitCode;
@@ -159,7 +156,7 @@ public final class ModdedWorldCheck {
awaitStop.run();
} catch (Throwable e) {
exitCode = EXIT_FAILURE;
LOGGER.error("[worldcheck] waiting for server shutdown failed", e);
ModdedIrisLog.error("[worldcheck] waiting for server shutdown failed", e);
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
@@ -171,25 +168,25 @@ public final class ModdedWorldCheck {
private static WorldCheckPreparation run(MinecraftServer server) {
ServerLevel level = targetLevel(server);
if (level == null) {
LOGGER.error("[worldcheck] no Iris dimension is loaded");
ModdedIrisLog.error("[worldcheck] no Iris dimension is loaded");
return new WorldCheckPreparation(false, false, false, false,
new NativeStructureGate(false, 0, false, null));
}
String levelId = level.dimension().identifier().toString();
String generatorClass = level.getChunkSource().getGenerator().getClass().getName();
LOGGER.info("[worldcheck] {} generator: {}", levelId, generatorClass);
ModdedIrisLog.info("[worldcheck] {} generator: {}", levelId, generatorClass);
IrisModdedChunkGenerator generator = level.getChunkSource().getGenerator() instanceof IrisModdedChunkGenerator iris
? iris : null;
boolean irisGenerator = generator != null;
if (!irisGenerator) {
LOGGER.error("[worldcheck] {} is NOT using IrisModdedChunkGenerator", levelId);
ModdedIrisLog.error("[worldcheck] {} is NOT using IrisModdedChunkGenerator", levelId);
}
boolean dimensionTypeOk = generator != null
&& WorldCheckDimensionContract.checkDimensionType(level, generator);
BlockPos spawn = level.getRespawnData().pos();
LOGGER.info("[worldcheck] spawn: {} {} {} (minY={} height={})", spawn.getX(), spawn.getY(), spawn.getZ(), level.getMinY(), level.getHeight());
ModdedIrisLog.info("[worldcheck] spawn: {} {} {} (minY={} height={})", spawn.getX(), spawn.getY(), spawn.getZ(), level.getMinY(), level.getHeight());
MessageDigest digest = WorldCheckPredicates.sha256();
List<String> samples = new ArrayList<>();
@@ -210,9 +207,9 @@ public final class ModdedWorldCheck {
}
for (int i = 0; i < Math.min(6, samples.size()); i++) {
LOGGER.info("[worldcheck] surface sample: {}", samples.get(i));
ModdedIrisLog.info("[worldcheck] surface sample: {}", samples.get(i));
}
LOGGER.info("[worldcheck] surface digest: {} ({} columns, {} distinct surface blocks: {})",
ModdedIrisLog.info("[worldcheck] surface digest: {} ({} columns, {} distinct surface blocks: {})",
HexFormat.of().formatHex(digest.digest()).substring(0, 12), samples.size(), surfaceKeys.size(), surfaceKeys);
ChunkAccess zeroChunk = level.getChunk(0, 0);
@@ -230,16 +227,16 @@ public final class ModdedWorldCheck {
columnKeys.add(BuiltInRegistries.BLOCK.getKey(state.getBlock()).toString());
}
}
LOGGER.info("[worldcheck] chunk 0,0: {} non-empty sections of {}; column blocks at (8,*,8): {}",
ModdedIrisLog.info("[worldcheck] chunk 0,0: {} non-empty sections of {}; column blocks at (8,*,8): {}",
nonEmptySections, zeroChunk.getSections().length, columnKeys);
boolean sectionsOk = nonEmptySections >= 4;
boolean varietyOk = columnKeys.size() >= 2 || surfaceKeys.size() >= 2;
if (!sectionsOk) {
LOGGER.error("[worldcheck] chunk 0,0 looks empty/vanilla-flat ({} non-empty sections)", nonEmptySections);
ModdedIrisLog.error("[worldcheck] chunk 0,0 looks empty/vanilla-flat ({} non-empty sections)", nonEmptySections);
}
if (!varietyOk) {
LOGGER.error("[worldcheck] generated terrain has no block variety (flat-world signature)");
ModdedIrisLog.error("[worldcheck] generated terrain has no block variety (flat-world signature)");
}
boolean entityMixinsOk = WorldCheckDimensionContract.checkEntityMixins(level);
@@ -262,7 +259,7 @@ public final class ModdedWorldCheck {
WorldCheckPredicates.qaEvent("village_poi_metric", "village", poiOk,
"inBounds=" + poi.inBounds() + ",outOfBounds=" + poi.outOfBounds());
if (!poiOk) {
LOGGER.error("[worldcheck] village POI audit failed: inBounds={} outOfBounds={}",
ModdedIrisLog.error("[worldcheck] village POI audit failed: inBounds={} outOfBounds={}",
poi.inBounds(), poi.outOfBounds());
}
} else {
@@ -271,12 +268,12 @@ public final class ModdedWorldCheck {
int passed = structureGate.nonVillagePassed()
+ (structureGate.villagePassBeforePoi() && poiOk ? 1 : 0);
boolean structurePass = structureGate.passBeforePoi() && poiOk;
LOGGER.info("[worldcheck] native structure gate: {}/{} passed", passed,
ModdedIrisLog.info("[worldcheck] native structure gate: {}/{} passed", passed,
WorldCheckStructureAudit.STRUCTURE_CHECKS.size());
WorldCheckPredicates.qaEvent("structure_aggregate", "all", structurePass,
"passed=" + passed + ",total=" + WorldCheckStructureAudit.STRUCTURE_CHECKS.size());
boolean pass = preparation.nonStructurePass() && structurePass;
LOGGER.info("[worldcheck] {}", pass ? "PASS" : "FAIL");
ModdedIrisLog.info("[worldcheck] {}", pass ? "PASS" : "FAIL");
WorldCheckPredicates.qaEvent("worldcheck_final", "all", pass,
"structures=" + WorldCheckStructureAudit.STRUCTURE_CHECKS.size()
+ ",terrain=" + preparation.terrainOk()
@@ -295,7 +292,7 @@ public final class ModdedWorldCheck {
if (requested != null) {
return requested;
}
LOGGER.error("[worldcheck] requested dimension '{}' is not loaded", target);
ModdedIrisLog.error("[worldcheck] requested dimension '{}' is not loaded", target);
return null;
}
@@ -31,8 +31,6 @@ import art.arcane.iris.modded.command.ModdedGuiHost;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
@@ -42,7 +40,6 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
public final class ModdedWorldEngines {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final ConcurrentHashMap<ServerLevel, Engine> ENGINES = new ConcurrentHashMap<>();
private ModdedWorldEngines() {
@@ -64,7 +61,7 @@ public final class ModdedWorldEngines {
try {
evictOrThrow(level);
} catch (Throwable e) {
LOGGER.error("Iris engine evict close failed for {}", level.dimension().identifier(), e);
ModdedIrisLog.error("Iris engine evict close failed for {}", level.dimension().identifier(), e);
}
}
@@ -80,7 +77,7 @@ public final class ModdedWorldEngines {
}
// The GUI host holds strong Engine/ServerLevel references with no other remove path.
ModdedGuiHost.unbind(removed[0]);
LOGGER.info("Iris engine evicted for {}", level.dimension().identifier());
ModdedIrisLog.info("Iris engine evicted for {}", level.dimension().identifier());
}
static Engine prepareReplacement(ServerLevel level, String pack, String dimensionKey, long seedOverride) {
@@ -111,7 +108,7 @@ public final class ModdedWorldEngines {
IrisData data = IrisData.openRuntime(packDir);
IrisDimension dimension = data.getDimensionLoader().load(dimensionKey);
if (dimension == null) {
LOGGER.error("Iris pack '{}' at {} does not contain dimension '{}' (expected dimensions/{}.json). Install a matching Iris pack and restart.",
ModdedIrisLog.error("Iris pack '{}' at {} does not contain dimension '{}' (expected dimensions/{}.json). Install a matching Iris pack and restart.",
pack, packDir.getAbsolutePath(), dimensionKey, dimensionKey);
throw new IllegalStateException("Iris dimension '" + dimensionKey + "' missing from pack " + packDir.getAbsolutePath());
}
@@ -142,7 +139,7 @@ public final class ModdedWorldEngines {
throw failure;
}
LOGGER.info("Iris engine up for {}: pack={} dim={} seed={} height={}..{}",
ModdedIrisLog.info("Iris engine up for {}: pack={} dim={} seed={} height={}..{}",
level.dimension().identifier(), packDir.getAbsolutePath(), dimension.getLoadKey(), seed, dimension.getMinHeight(), dimension.getMaxHeight());
return engine;
}
@@ -182,11 +179,11 @@ public final class ModdedWorldEngines {
return packDir;
}
LOGGER.error("===============================================================");
LOGGER.error("Iris pack '{}' is not installed.", pack);
LOGGER.error("Expected a pack folder at: {}", packDir.getAbsolutePath());
LOGGER.error("Install an Iris pack there (the folder must contain dimensions/{}.json) and restart the server.", dimensionKey);
LOGGER.error("===============================================================");
ModdedIrisLog.error("===============================================================");
ModdedIrisLog.error("Iris pack '{}' is not installed.", pack);
ModdedIrisLog.error("Expected a pack folder at: {}", packDir.getAbsolutePath());
ModdedIrisLog.error("Install an Iris pack there (the folder must contain dimensions/{}.json) and restart the server.", dimensionKey);
ModdedIrisLog.error("===============================================================");
throw new IllegalStateException("Iris pack not installed: " + packDir.getAbsolutePath());
}
@@ -215,9 +212,9 @@ public final class ModdedWorldEngines {
+ level.dimension().identifier());
}
}
LOGGER.info("Iris engine closed for {}", level.dimension().identifier());
ModdedIrisLog.info("Iris engine closed for {}", level.dimension().identifier());
} catch (Throwable e) {
LOGGER.error("Iris engine close failed for {}", level.dimension().identifier(), e);
ModdedIrisLog.error("Iris engine close failed for {}", level.dimension().identifier(), e);
if (failure == null) {
failure = e;
} else if (e != failure) {
@@ -25,11 +25,8 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.dimension.DimensionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final class WorldCheckDimensionContract {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private WorldCheckDimensionContract() {
}
@@ -44,13 +41,13 @@ final class WorldCheckDimensionContract {
+ ",levelMinY=" + level.getMinY() + ",levelHeight=" + level.getHeight();
WorldCheckPredicates.qaEvent("dimension_type", dimension.getLoadKey(), pass, detail);
if (!pass) {
LOGGER.error("[worldcheck] dimension type mismatch for {}: {}", dimension.getLoadKey(), detail);
ModdedIrisLog.error("[worldcheck] dimension type mismatch for {}: {}", dimension.getLoadKey(), detail);
} else {
LOGGER.info("[worldcheck] dimension type contract: {}", detail);
ModdedIrisLog.info("[worldcheck] dimension type contract: {}", detail);
}
return pass;
} catch (Throwable error) {
LOGGER.error("[worldcheck] could not validate the Iris dimension type contract", error);
ModdedIrisLog.error("[worldcheck] could not validate the Iris dimension type contract", error);
WorldCheckPredicates.qaEvent("dimension_type", generator.activeDimensionKey(), false,
"validationError=" + error.getClass().getSimpleName() + ":" + error.getMessage());
return false;
@@ -102,7 +99,7 @@ final class WorldCheckDimensionContract {
WorldCheckPredicates.qaEvent("entity_mixin", "persistence", pass,
"vanilla=" + vanillaSave + ",suppressed=" + suppressed + ",restored=" + restored);
if (!pass) {
LOGGER.error("[worldcheck] shared entity mixins are not active on this loader");
ModdedIrisLog.error("[worldcheck] shared entity mixins are not active on this loader");
}
return pass;
}
@@ -20,14 +20,11 @@ package art.arcane.iris.modded;
import art.arcane.iris.engine.framework.StructureVerticalBounds;
import art.arcane.iris.modded.WorldCheckStructureAudit.StructureCheck;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
final class WorldCheckPredicates {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private WorldCheckPredicates() {
}
@@ -39,7 +36,7 @@ final class WorldCheckPredicates {
}
static void qaEvent(String event, String structure, boolean pass, String detail) {
LOGGER.info(qaEventJson(event, structure, pass, detail));
ModdedIrisLog.info(qaEventJson(event, structure, pass, detail));
}
static String qaEventJson(String event, String structure, boolean pass, String detail) {
@@ -48,8 +48,6 @@ import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -77,7 +75,6 @@ final class WorldCheckStructureAudit {
private static final int MAX_FOOTPRINT_CHUNKS = 96;
private static final int MAX_START_REFERENCE_CHUNKS = 16;
private static final int MAX_STRUCTURE_CANDIDATES = 1024;
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private WorldCheckStructureAudit() {
}
@@ -123,13 +120,13 @@ final class WorldCheckStructureAudit {
}
}
boolean registryOk = registered.size() == check.registryKeys().size();
LOGGER.info("[worldcheck] {} registry: {}/{} resolved {}", check.label(), registered.size(),
ModdedIrisLog.info("[worldcheck] {} registry: {}/{} resolved {}", check.label(), registered.size(),
check.registryKeys().size(), registeredKeys);
WorldCheckPredicates.qaEvent("structure_registry", check.label(), registryOk,
"resolved=" + registered.size() + ",expected=" + check.registryKeys().size()
+ ",keys=" + String.join("|", registeredKeys));
if (!registryOk) {
LOGGER.error("[worldcheck] {} registry resolution failed; expected {}", check.label(), check.registryKeys());
ModdedIrisLog.error("[worldcheck] {} registry resolution failed; expected {}", check.label(), check.registryKeys());
WorldCheckPredicates.emitSkipped(check, "registry", "structure_reachability", "structure_locate",
"structure_start_reference", "structure_footprint", "structure_material",
"structure_block_entity");
@@ -149,12 +146,12 @@ final class WorldCheckStructureAudit {
}
}
boolean reachableOk = !reachable.isEmpty();
LOGGER.info("[worldcheck] {} biome-reachable through Iris: {}", check.label(), reachableKeys);
ModdedIrisLog.info("[worldcheck] {} biome-reachable through Iris: {}", check.label(), reachableKeys);
WorldCheckPredicates.qaEvent("structure_reachability", check.label(), reachableOk,
"reachable=" + reachable.size() + ",registered=" + registered.size()
+ ",keys=" + String.join("|", reachableKeys));
if (!reachableOk) {
LOGGER.error("[worldcheck] {} cannot generate in any biome produced by this Iris pack", check.label());
ModdedIrisLog.error("[worldcheck] {} cannot generate in any biome produced by this Iris pack", check.label());
WorldCheckPredicates.emitSkipped(check, "reachability", "structure_locate", "structure_start_reference",
"structure_footprint", "structure_material", "structure_block_entity");
return new StructureCheckResult(false, null);
@@ -170,7 +167,7 @@ final class WorldCheckStructureAudit {
"method=placement_candidates,millis=" + locateMillis + ",radius=" + check.locateRadius()
+ ",result=" + (foundKey == null ? "none" : foundKey));
if (found == null) {
LOGGER.error("[worldcheck] {} native placement candidates produced no valid start within {} rings after {}ms",
ModdedIrisLog.error("[worldcheck] {} native placement candidates produced no valid start within {} rings after {}ms",
check.label(), check.locateRadius(), locateMillis);
WorldCheckPredicates.emitSkipped(check, "locate", "structure_start_reference", "structure_footprint",
"structure_material", "structure_block_entity");
@@ -178,11 +175,11 @@ final class WorldCheckStructureAudit {
}
BlockPos position = found.getFirst();
LOGGER.info("[worldcheck] {} generated candidate: {} {} {} in {}ms (radius={}, result={})",
ModdedIrisLog.info("[worldcheck] {} generated candidate: {} {} {} in {}ms (radius={}, result={})",
check.label(), position.getX(), position.getY(), position.getZ(), locateMillis,
check.locateRadius(), foundKey);
if (!locateOk) {
LOGGER.error("[worldcheck] {} candidate scan returned unexpected structure {}", check.label(), foundKey);
ModdedIrisLog.error("[worldcheck] {} candidate scan returned unexpected structure {}", check.label(), foundKey);
WorldCheckPredicates.emitSkipped(check, "locate", "structure_start_reference", "structure_footprint",
"structure_material", "structure_block_entity");
return new StructureCheckResult(false, null);
@@ -196,13 +193,13 @@ final class WorldCheckStructureAudit {
boolean validStart = start != null && start.isValid();
int references = targetChunk.getReferencesForStructure(structure).size();
boolean startReferenceOk = WorldCheckPredicates.hasNativeStructureEvidence(validStart, references);
LOGGER.info("[worldcheck] {} target chunk {},{}: valid start={}, references={}",
ModdedIrisLog.info("[worldcheck] {} target chunk {},{}: valid start={}, references={}",
check.label(), chunkX, chunkZ, validStart, references);
WorldCheckPredicates.qaEvent("structure_start_reference", check.label(), startReferenceOk,
"chunk=" + chunkX + "," + chunkZ + ",validStart=" + validStart
+ ",references=" + references);
if (!startReferenceOk || !validStart) {
LOGGER.error("[worldcheck] {} located at chunk {},{} but no resolvable valid start was generated",
ModdedIrisLog.error("[worldcheck] {} located at chunk {},{} but no resolvable valid start was generated",
check.label(), chunkX, chunkZ);
WorldCheckPredicates.emitSkipped(check, "start_reference", "structure_footprint", "structure_material",
"structure_block_entity");
@@ -221,7 +218,7 @@ final class WorldCheckStructureAudit {
"configured=" + decision.yShift() + ",applied="
+ (appliedShift == null ? "unrecorded" : appliedShift));
if (!verticalShiftOk) {
LOGGER.error("[worldcheck] {} expected vertical shift {} but generation recorded {}",
ModdedIrisLog.error("[worldcheck] {} expected vertical shift {} but generation recorded {}",
check.label(), decision.yShift(), appliedShift);
}
@@ -229,7 +226,7 @@ final class WorldCheckStructureAudit {
boolean footprintOk = footprint.inspectedChunks() > 0
&& footprint.evidenceChunks() == footprint.inspectedChunks()
&& footprint.coveredPieces() == footprint.totalPieces();
LOGGER.info("[worldcheck] {} footprint: chunks={}/{} evidence={} pieces={}/{}",
ModdedIrisLog.info("[worldcheck] {} footprint: chunks={}/{} evidence={} pieces={}/{}",
check.label(), footprint.inspectedChunks(), footprint.availableChunks(),
footprint.evidenceChunks(), footprint.coveredPieces(), footprint.totalPieces());
WorldCheckPredicates.qaEvent("structure_footprint", check.label(), footprintOk,
@@ -239,7 +236,7 @@ final class WorldCheckStructureAudit {
boolean materialOk = WorldCheckPredicates.hasCharacteristicMaterialEvidence(footprint.characteristicBlocks(),
footprint.characteristicChunks(), footprint.materialScannedChunks());
LOGGER.info("[worldcheck] {} material: blocks={} chunks={}/{}",
ModdedIrisLog.info("[worldcheck] {} material: blocks={} chunks={}/{}",
check.label(), footprint.characteristicBlocks(), footprint.characteristicChunks(),
footprint.materialScannedChunks());
WorldCheckPredicates.qaEvent("structure_material", check.label(), materialOk,
@@ -250,7 +247,7 @@ final class WorldCheckStructureAudit {
if (check.label().equals("mansion")) {
boolean overlap = footprint.vegetationBlocks() > 0;
vegetationOk = WorldCheckPredicates.mansionVegetationPass(footprint.vegetationBlocks());
LOGGER.info("[worldcheck] mansion vegetation metric: remaining log/leaf blocks={} columns={} overlap={}",
ModdedIrisLog.info("[worldcheck] mansion vegetation metric: remaining log/leaf blocks={} columns={} overlap={}",
footprint.vegetationBlocks(), footprint.vegetationColumns(), overlap);
WorldCheckPredicates.qaEvent("mansion_vegetation_metric", check.label(), vegetationOk,
"remainingLogsOrLeaves=" + footprint.vegetationBlocks() + ",columns="
@@ -261,7 +258,7 @@ final class WorldCheckStructureAudit {
PendingVillagePoi pendingPoi = null;
if (check.label().equals("village")) {
foundationOk = WorldCheckPredicates.villageFoundationPass(footprint.foundationGapColumns());
LOGGER.info("[worldcheck] village foundation metric: bases={} cobblestone={} columns={} unsupported={}",
ModdedIrisLog.info("[worldcheck] village foundation metric: bases={} cobblestone={} columns={} unsupported={}",
footprint.foundationBaseColumns(), footprint.foundationBlocks(),
footprint.foundationColumns(), footprint.foundationGapColumns());
WorldCheckPredicates.qaEvent("village_foundation_metric", check.label(), foundationOk,
@@ -272,26 +269,26 @@ final class WorldCheckStructureAudit {
}
boolean blockEntityOk = footprint.blockEntityStates() == footprint.blockEntitiesPresent();
LOGGER.info("[worldcheck] {} block entities: state blocks={}, present={}, missing={}",
ModdedIrisLog.info("[worldcheck] {} block entities: state blocks={}, present={}, missing={}",
check.label(), footprint.blockEntityStates(), footprint.blockEntitiesPresent(),
footprint.blockEntityStates() - footprint.blockEntitiesPresent());
WorldCheckPredicates.qaEvent("structure_block_entity", check.label(), blockEntityOk,
"states=" + footprint.blockEntityStates() + ",present=" + footprint.blockEntitiesPresent()
+ ",missing=" + (footprint.blockEntityStates() - footprint.blockEntitiesPresent()));
if (!footprintOk) {
LOGGER.error("[worldcheck] {} structure footprint is incomplete", check.label());
ModdedIrisLog.error("[worldcheck] {} structure footprint is incomplete", check.label());
}
if (!materialOk) {
LOGGER.error("[worldcheck] {} has no distributed characteristic structure material", check.label());
ModdedIrisLog.error("[worldcheck] {} has no distributed characteristic structure material", check.label());
}
if (!blockEntityOk) {
LOGGER.error("[worldcheck] {} generated block-entity states without matching block entities", check.label());
ModdedIrisLog.error("[worldcheck] {} generated block-entity states without matching block entities", check.label());
}
if (!vegetationOk) {
LOGGER.error("[worldcheck] mansion vegetation still intersects the generated structure footprint");
ModdedIrisLog.error("[worldcheck] mansion vegetation still intersects the generated structure footprint");
}
if (!foundationOk) {
LOGGER.error("[worldcheck] village has unsupported foundation columns after stilt placement");
ModdedIrisLog.error("[worldcheck] village has unsupported foundation columns after stilt placement");
}
boolean pass = verticalShiftOk && footprintOk && materialOk && blockEntityOk
&& vegetationOk && foundationOk;
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.api;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.modded.ModdedBlockResolution;
import net.minecraft.core.BlockPos;
@@ -25,8 +26,6 @@ import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
@@ -57,7 +56,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
* next provider.
*/
public final class ModdedCustomContentRegistry {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final List<ModdedDataProvider> PROVIDERS = new CopyOnWriteArrayList<>();
private static final Map<String, BlockState> CUSTOM_BLOCKS = new ConcurrentHashMap<>();
private static volatile boolean scanned = false;
@@ -77,14 +75,14 @@ public final class ModdedCustomContentRegistry {
}
Identifier identifier = Identifier.tryParse(namespace + ":" + key);
if (identifier == null) {
LOGGER.warn("Iris custom block data registration rejected invalid id {}:{}", namespace, key);
ModdedIrisLog.warn("Iris custom block data registration rejected invalid id {}:{}", namespace, key);
return;
}
BlockState parsed;
try {
parsed = ModdedBlockResolution.strictParse(state).handle();
} catch (Throwable error) {
LOGGER.error("Iris custom block data '{}:{}' has unparseable state '{}'", namespace, key, state, error);
ModdedIrisLog.error("Iris custom block data '{}:{}' has unparseable state '{}'", namespace, key, state, error);
return;
}
DiscoveryBatch activeBatch = discoveryBatch;
@@ -93,7 +91,7 @@ public final class ModdedCustomContentRegistry {
} else {
activeBatch.customBlocks.put(identifier.toString(), parsed);
}
LOGGER.info("Iris registered custom block data {}:{} -> {}", namespace, key, state);
ModdedIrisLog.info("Iris registered custom block data {}:{} -> {}", namespace, key, state);
}
/**
@@ -112,7 +110,7 @@ public final class ModdedCustomContentRegistry {
}
for (ModdedDataProvider existing : PROVIDERS) {
if (existing.modId().equals(provider.modId())) {
LOGGER.warn("Iris custom content provider for '{}' already registered; ignoring duplicate", provider.modId());
ModdedIrisLog.warn("Iris custom content provider for '{}' already registered; ignoring duplicate", provider.modId());
return;
}
}
@@ -120,9 +118,9 @@ public final class ModdedCustomContentRegistry {
try {
provider.init();
} catch (Throwable error) {
LOGGER.error("Iris custom content provider '{}' failed to initialize", provider.modId(), error);
ModdedIrisLog.error("Iris custom content provider '{}' failed to initialize", provider.modId(), error);
}
LOGGER.info("Iris registered custom content provider '{}'", provider.modId());
ModdedIrisLog.info("Iris registered custom content provider '{}'", provider.modId());
}
/**
@@ -159,7 +157,7 @@ public final class ModdedCustomContentRegistry {
CUSTOM_BLOCKS.putAll(batch.customBlocks);
scanned = true;
for (ModdedDataProvider provider : batch.additions) {
LOGGER.info("Iris registered custom content provider '{}'", provider.modId());
ModdedIrisLog.info("Iris registered custom content provider '{}'", provider.modId());
}
return new Discovery(previousProviders, previousCustomBlocks,
previousDiscoveryComplete, true);
@@ -171,7 +169,7 @@ public final class ModdedCustomContentRegistry {
failure.addSuppressed(rollbackFailure);
}
}
LOGGER.warn("Iris custom content provider discovery failed at {}",
ModdedIrisLog.warn("Iris custom content provider discovery failed at {}",
providerIdentity(failingProvider), failure);
if (failure instanceof RuntimeException runtimeException) {
throw runtimeException;
@@ -242,7 +240,7 @@ public final class ModdedCustomContentRegistry {
try {
types = provider.getTypes(type);
} catch (Throwable error) {
LOGGER.error("Iris custom content provider '{}' failed listing {} types", provider.modId(), type, error);
ModdedIrisLog.error("Iris custom content provider '{}' failed listing {} types", provider.modId(), type, error);
continue;
}
if (types == null) {
@@ -288,7 +286,7 @@ public final class ModdedCustomContentRegistry {
return resolved;
}
} catch (Throwable error) {
LOGGER.error("Iris custom content provider '{}' failed resolving block {}", provider.modId(), key, error);
ModdedIrisLog.error("Iris custom content provider '{}' failed resolving block {}", provider.modId(), key, error);
}
}
return null;
@@ -302,7 +300,7 @@ public final class ModdedCustomContentRegistry {
public static void processBlockPlacement(Engine engine, ServerLevel level, BlockPos position, String key) {
Identifier base = parseIdentifier(key);
if (base == null) {
LOGGER.warn("Iris deferred custom block placement rejected invalid id {}", key);
ModdedIrisLog.warn("Iris deferred custom block placement rejected invalid id {}", key);
return;
}
Map<String, String> state = parseState(key);
@@ -314,11 +312,11 @@ public final class ModdedCustomContentRegistry {
provider.processBlockPlacement(new ModdedBlockPlacementContext(
engine, level, position.immutable(), base, state, level.getBlockState(position)));
} catch (Throwable error) {
LOGGER.error("Iris custom content provider '{}' failed post-placement for {} at {}", provider.modId(), key, position, error);
ModdedIrisLog.error("Iris custom content provider '{}' failed post-placement for {} at {}", provider.modId(), key, position, error);
}
return;
}
LOGGER.warn("Iris deferred custom block placement has no provider for {}", key);
ModdedIrisLog.warn("Iris deferred custom block placement has no provider for {}", key);
}
/**
@@ -343,7 +341,7 @@ public final class ModdedCustomContentRegistry {
return entity;
}
} catch (Throwable error) {
LOGGER.error("Iris custom content provider '{}' failed spawning mob {}", provider.modId(), key, error);
ModdedIrisLog.error("Iris custom content provider '{}' failed spawning mob {}", provider.modId(), key, error);
}
}
return null;
@@ -439,7 +437,7 @@ public final class ModdedCustomContentRegistry {
"Iris custom content provider returned a null mod id");
for (ModdedDataProvider existing : providers) {
if (modId.equals(existing.modId())) {
LOGGER.warn("Iris custom content provider for '{}' already registered; ignoring duplicate", modId);
ModdedIrisLog.warn("Iris custom content provider for '{}' already registered; ignoring duplicate", modId);
return;
}
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.IrisMessages;
@@ -51,8 +52,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -67,7 +66,6 @@ import java.util.concurrent.TimeUnit;
import art.arcane.volmlib.util.localization.MessageArgument;
public final class IrisModdedCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final long DOWNLOAD_SHUTDOWN_POLL_SECONDS = 15L;
private static final Object DOWNLOAD_MONITOR = new Object();
@@ -82,7 +80,7 @@ public final class IrisModdedCommands {
LiteralCommandNode<CommandSourceStack> root = dispatcher.register(ModdedCommandTree.rootTree());
dispatcher.register(Commands.literal("ir").redirect(root));
dispatcher.register(Commands.literal("irs").redirect(root));
IrisLogging.info("Iris /iris command tree registered");
IrisLogging.debug("Iris /iris command tree registered");
}
public static void openDownloadAdmission() {
@@ -108,7 +106,7 @@ public final class IrisModdedCommands {
try {
if (!execution.await(DOWNLOAD_SHUTDOWN_POLL_SECONDS, TimeUnit.SECONDS) && !warned) {
warned = true;
LOGGER.warn(execution.isPublishing()
ModdedIrisLog.warn(execution.isPublishing()
? "Waiting for atomic pack publication to finish before Iris shutdown."
: "Waiting for the active pack download to cancel before Iris shutdown.");
}
@@ -354,7 +352,7 @@ public final class IrisModdedCommands {
accepted = scheduler.asyncIfRunning(execution, execution::cancel);
} catch (Throwable error) {
execution.cancel();
LOGGER.error("Iris pack download dispatch failed for {}", target, error);
ModdedIrisLog.error("Iris pack download dispatch failed for {}", target, error);
fail(source, IrisLanguage.plain(
ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_DOWNLOAD_FAILED_SEE_CONSOLE,
MessageArgument.untrusted("pack", target),
@@ -363,7 +361,7 @@ public final class IrisModdedCommands {
}
if (!accepted) {
execution.cancel();
LOGGER.error("Iris pack download dispatch rejected for {} because the scheduler is shut down", target);
ModdedIrisLog.error("Iris pack download dispatch rejected for {} because the scheduler is shut down", target);
fail(source, IrisLanguage.plain(
ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_DOWNLOAD_FAILED_SEE_CONSOLE,
MessageArgument.untrusted("pack", target),
@@ -416,7 +414,7 @@ public final class IrisModdedCommands {
dispatchDownloadFeedback(source, () -> fail(source, error.getMessage()));
return;
} catch (IOException | RuntimeException error) {
LOGGER.error("Iris pack download failed for {}", target, error);
ModdedIrisLog.error("Iris pack download failed for {}", target, error);
}
dispatchDownloadFeedback(source, () -> fail(source, IrisLanguage.plain(
ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_DOWNLOAD_FAILED_SEE_CONSOLE,
@@ -512,7 +510,7 @@ public final class IrisModdedCommands {
try {
return irisGenerator.commandEngine();
} catch (Throwable e) {
LOGGER.error("Iris engine lookup failed for {}", level.dimension().identifier(), e);
ModdedIrisLog.error("Iris engine lookup failed for {}", level.dimension().identifier(), e);
return null;
}
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.core.pack.PackDirectoryResolver;
import art.arcane.iris.engine.framework.Engine;
@@ -40,8 +41,6 @@ import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.levelgen.structure.Structure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
@@ -66,7 +65,6 @@ final class ModdedCommandSuggestions {
static final SuggestionProvider<CommandSourceStack> PACK_NAMES = (CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) -> suggestPackNames(context, builder);
static final SuggestionProvider<CommandSourceStack> DIMENSION_NAMES = (CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) -> suggestDimensionNames(context, builder);
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int TAB_FAILURE_KEYS_MAX = 256;
private static final Set<String> REPORTED_TAB_FAILURES = ConcurrentHashMap.newKeySet();
private static final long PACK_NAME_CACHE_TTL_MS = 3_000L;
@@ -180,7 +178,7 @@ final class ModdedCommandSuggestions {
if (REPORTED_TAB_FAILURES.size() > TAB_FAILURE_KEYS_MAX) {
REPORTED_TAB_FAILURES.clear();
}
LOGGER.warn("Iris tab-complete for {} in {} failed; suggestions will be empty", suggestion, origin, error);
ModdedIrisLog.warn("Iris tab-complete for {} in {} failed; suggestions will be empty", suggestion, origin, error);
}
private static String tabOrigin(CommandSourceStack source) {
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.core.nms.datapack.DataVersion;
import art.arcane.iris.core.pack.PackDirectoryResolver;
@@ -35,8 +36,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -56,7 +55,6 @@ import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.iris.core.localization.RuntimeUiMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
public final class ModdedDatapackCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private static final String WORLD_PACK_NAME = "iris";
@@ -170,7 +168,7 @@ public final class ModdedDatapackCommands {
try {
json = dimension.getDimensionType().toJson(DataVersion.getLatest().get());
} catch (Throwable e) {
LOGGER.error("Iris dimension type generation failed for {}", dimension.getLoadKey(), e);
ModdedIrisLog.error("Iris dimension type generation failed for {}", dimension.getLoadKey(), e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_DIMENSION_TYPE_GENERATION_FAILED, MessageArgument.untrusted("value", level.dimension().identifier()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage()))));
continue;
}
@@ -180,7 +178,7 @@ public final class ModdedDatapackCommands {
Files.writeString(output.toPath(), json, StandardCharsets.UTF_8);
written.add(output.getPath());
} catch (IOException e) {
LOGGER.error("Iris dimension type write failed for {}", output, e);
ModdedIrisLog.error("Iris dimension type write failed for {}", output, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_FAILED_WRITE, MessageArgument.untrusted("output", output), MessageArgument.untrusted("value", String.valueOf(e.getMessage()))));
}
}
@@ -204,7 +202,7 @@ public final class ModdedDatapackCommands {
Files.writeString(mcmeta.toPath(), meta, StandardCharsets.UTF_8);
written.add(mcmeta.getPath());
} catch (IOException e) {
LOGGER.error("Iris pack.mcmeta write failed for {}", mcmeta, e);
ModdedIrisLog.error("Iris pack.mcmeta write failed for {}", mcmeta, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_FAILED_WRITE_2, MessageArgument.untrusted("mcmeta", mcmeta), MessageArgument.untrusted("value", String.valueOf(e.getMessage()))));
return 0;
}
@@ -237,7 +235,7 @@ public final class ModdedDatapackCommands {
}
}
} catch (Throwable e) {
LOGGER.error("Iris datapack import scan failed for pack {}", pack.getName(), e);
ModdedIrisLog.error("Iris datapack import scan failed for pack {}", pack.getName(), e);
}
}
@@ -18,13 +18,12 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.spi.IrisPlatforms;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
@@ -37,7 +36,6 @@ import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
final class ModdedDeveloperCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private ModdedDeveloperCommands() {
@@ -71,7 +69,7 @@ final class ModdedDeveloperCommands {
}
return 1;
} catch (SocketException error) {
LOGGER.error("Iris developer network dump failed", error);
ModdedIrisLog.error("Iris developer network dump failed", error);
ModdedCommandFeedback.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DEVELOPER_COMMANDS_NETWORK_SCAN_FAILED, MessageArgument.untrusted("value", error.getClass().getSimpleName())));
return 0;
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.RuntimeUiMessages;
import art.arcane.iris.engine.framework.Engine;
@@ -46,8 +47,6 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.level.biome.Biome;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -62,7 +61,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
public final class ModdedDustRevealer {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int MAX_HITS = 2_048;
private static final int PARTICLE_BATCH_SIZE = 64;
private static final DustParticleOptions REVEAL_DUST = new DustParticleOptions(0xFFD24A, 1.2F);
@@ -231,7 +229,7 @@ public final class ModdedDustRevealer {
}
private static void revealFailure(ModdedScheduler scheduler, RevealRun run, Throwable error) {
LOGGER.error("Iris dust reveal failed for {} at {}", run.key(), coordinates(run.origin()), error);
ModdedIrisLog.error("Iris dust reveal failed for {} at {}", run.key(), coordinates(run.origin()), error);
scheduler.global(() -> {
if (ACTIVE_RUNS.remove(run.playerId(), run)) {
run.player().sendSystemMessage(Component.literal(
@@ -415,7 +413,7 @@ public final class ModdedDustRevealer {
}
}
} catch (Throwable error) {
LOGGER.error("Iris dust column-object lookup failed at {}, {}, {}",
ModdedIrisLog.error("Iris dust column-object lookup failed at {}, {}, {}",
x, relativeY + minHeight, z, error);
}
return null;
@@ -458,7 +456,7 @@ public final class ModdedDustRevealer {
try {
return supplier.get();
} catch (Throwable error) {
LOGGER.error("Iris dust {} failed", operation, error);
ModdedIrisLog.error("Iris dust {} failed", operation, error);
return null;
}
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.gui.GuiHost;
import art.arcane.iris.core.loader.IrisRegistrant;
import art.arcane.iris.core.localization.IrisLanguage;
@@ -29,14 +30,11 @@ import art.arcane.volmlib.util.localization.MessageArgument;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Desktop;
import java.io.File;
final class ModdedEditCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private ModdedEditCommands() {
}
@@ -123,7 +121,7 @@ final class ModdedEditCommands {
try {
Desktop.getDesktop().open(file);
} catch (Throwable e) {
LOGGER.error("Iris edit failed to open {}", file, e);
ModdedIrisLog.error("Iris edit failed to open {}", file, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_COULD_NOT_OPEN, MessageArgument.untrusted("value", file.getName()), MessageArgument.untrusted("value2", e.getClass().getSimpleName())));
return 0;
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.runtime.GoldenHashEngine;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.modded.ModdedBlockBuffer;
@@ -29,8 +30,6 @@ import art.arcane.iris.util.project.hunk.Hunk;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -47,7 +46,6 @@ public final class ModdedGoldenHash {
VERIFY
}
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final AtomicBoolean ACTIVE = new AtomicBoolean(false);
private final CommandSourceStack source;
@@ -96,7 +94,7 @@ public final class ModdedGoldenHash {
MessageArgument.trusted("threads", Math.max(1, threads)),
MessageArgument.untrusted("mode", mode)
));
LOGGER.info("goldenhash start: dim={} seed={} radius={} threads={} mode={} file={}",
ModdedIrisLog.info("goldenhash start: dim={} seed={} radius={} threads={} mode={} file={}",
engine.getDimension().getLoadKey(), engine.getSeedManager().getSeed(), boundedRadius, Math.max(1, threads), mode, scan.hashEngine.getGoldenFile().getName());
Thread thread = new Thread(() -> {
try {
@@ -182,7 +180,7 @@ public final class ModdedGoldenHash {
@Override
public void chunkFailed(int chunkX, int chunkZ, Throwable error) {
LOGGER.error("goldenhash chunk {},{} failed", chunkX, chunkZ, error);
ModdedIrisLog.error("goldenhash chunk {},{} failed", chunkX, chunkZ, error);
ModdedGoldenHash.this.fail(IrisLanguage.plain(
RuntimeProgressMessages.GOLDEN_CHUNK_FAILED,
MessageArgument.trusted("x", chunkX),
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.iris.engine.framework.Engine;
@@ -51,8 +52,6 @@ import net.minecraft.world.entity.Relative;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.structure.Structure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Optional;
import java.util.Set;
@@ -64,7 +63,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
final class ModdedLocateCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final long LOCATE_TIMEOUT_MS = 120000L;
private static final int NATIVE_STRUCTURE_LOCATE_RADIUS = 100;
private static final ConcurrentHashMap<UUID, CompletableFuture<Position2>> ACTIVE_LOCATE_REQUESTS = new ConcurrentHashMap<>();
@@ -260,7 +258,7 @@ final class ModdedLocateCommands {
server.execute(() -> teleportToStructure(source, level, player, targetX, targetY, targetZ,
"Iris-placed structure " + key));
} catch (Throwable e) {
LOGGER.error("Iris structure locate failed for {}", key, e);
ModdedIrisLog.error("Iris structure locate failed for {}", key, e);
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCH_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()))));
}
}, "Iris Structure Locator");
@@ -302,7 +300,7 @@ final class ModdedLocateCommands {
teleportToStructure(source, level, player, targetX, targetY, targetZ,
"native structure " + target.key());
} catch (Throwable e) {
LOGGER.error("Native structure locate failed for {}", target.key(), e);
ModdedIrisLog.error("Native structure locate failed for {}", target.key(), e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCH_NATIVE_STRUCTURE_FAILED, MessageArgument.untrusted("value", target.key()), MessageArgument.untrusted("value2", e.getClass().getSimpleName())));
}
}
@@ -518,7 +516,7 @@ final class ModdedLocateCommands {
return;
}
if (failure != null) {
LOGGER.error("Iris locate failed for {}", label, failure);
ModdedIrisLog.error("Iris locate failed for {}", label, failure);
server.execute(() -> {
if (ACTIVE_LOCATE_REQUESTS.remove(playerId, search)) {
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCH_FAILED_2, MessageArgument.untrusted("failure", failure)));
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.core.tools.TreePlausibilizeBatch;
import art.arcane.iris.core.tools.TreePlausibilizer;
@@ -54,8 +55,6 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -74,7 +73,6 @@ import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.iris.core.localization.RuntimeUiMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
public final class ModdedObjectCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private static final long MAX_SAVE_VOLUME = 500000L;
private static final long MAX_AUTOSELECT_VOLUME = 100000L;
@@ -313,7 +311,7 @@ public final class ModdedObjectCommands {
try {
object.write(file);
} catch (IOException e) {
LOGGER.error("Iris object save failed for {}", file.getAbsolutePath(), e);
ModdedIrisLog.error("Iris object save failed for {}", file.getAbsolutePath(), e);
if (finalClaimed) {
// Never leave a 0-byte claim file permanently blocking non-overwrite saves.
file.delete();
@@ -332,7 +330,7 @@ public final class ModdedObjectCommands {
tileNote.append(" (").append(tilesSkipped[0]).append(" tile state(s) could not be captured)");
}
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_SAVED_OBJECTS_IOB_X_X_BLOCK_S, MessageArgument.untrusted("value", engine.getData().getDataFolder().getName()), MessageArgument.untrusted("name", name), MessageArgument.untrusted("w", w), MessageArgument.untrusted("h", h), MessageArgument.untrusted("d", d), MessageArgument.untrusted("value2", object.getBlocks().size()), MessageArgument.untrusted("tileNote", tileNote))));
LOGGER.info("Iris object save: {} {}x{}x{} blocks={} tilesSaved={} tilesSkipped={} -> {}", name, w, h, d, object.getBlocks().size(), tilesSaved[0], tilesSkipped[0], file.getAbsolutePath());
ModdedIrisLog.info("Iris object save: {} {}x{}x{} blocks={} tilesSaved={} tilesSkipped={} -> {}", name, w, h, d, object.getBlocks().size(), tilesSaved[0], tilesSkipped[0], file.getAbsolutePath());
});
return 1;
}
@@ -378,7 +376,7 @@ public final class ModdedObjectCommands {
String blockKey = BuiltInRegistries.BLOCK.getKey(state.getBlock()).toString();
return ModdedTileData.capture(blockKey, snbt);
} catch (Throwable e) {
LOGGER.error("Iris tile capture failed at {} {} {}", pos.getX(), pos.getY(), pos.getZ(), e);
ModdedIrisLog.error("Iris tile capture failed at {} {} {}", pos.getX(), pos.getY(), pos.getZ(), e);
return null;
}
}
@@ -391,7 +389,7 @@ public final class ModdedObjectCommands {
try {
object = IrisData.loadAnyObject(key, engine == null ? null : engine.getData());
} catch (Throwable e) {
LOGGER.error("Iris object load failed for {}", key, e);
ModdedIrisLog.error("Iris object load failed for {}", key, e);
}
if (object == null || object.getBlocks().size() == 0) {
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_UNKNOWN_EMPTY_OBJECT, MessageArgument.untrusted("key", key)));
@@ -419,7 +417,7 @@ public final class ModdedObjectCommands {
try {
object.place(target.getX(), target.getY() + object.getCenter().getY(), target.getZ(), placer, placement, new RNG(), null);
} catch (Throwable e) {
LOGGER.error("Iris paste failed for {}", key, e);
ModdedIrisLog.error("Iris paste failed for {}", key, e);
ModdedObjectUndo.record(player == null ? ModdedObjectUndo.CONSOLE : player.getUUID(), level, placer.undoSnapshot());
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_PASTE_FAILED_PARTIAL_CHANGES_RECORDED_UNDO, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
return 0;
@@ -428,7 +426,7 @@ public final class ModdedObjectCommands {
ModdedObjectUndo.record(owner, level, placer.undoSnapshot());
String tileNote = tileNote(placer);
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_PLACED_AT_ROT_WRITE_S_NON_AIR, MessageArgument.untrusted("key", key), MessageArgument.untrusted("value", target.getX()), MessageArgument.untrusted("value2", target.getY()), MessageArgument.untrusted("value3", target.getZ()), MessageArgument.untrusted("rotation", rotation), MessageArgument.untrusted("value4", placer.writes()), MessageArgument.untrusted("value5", placer.nonAirWrites()), MessageArgument.untrusted("tileNote", tileNote)));
LOGGER.info("Iris paste: {} at {},{},{} rot={} writes={} nonAir={} tilesRestored={} tilesSkipped={}",
ModdedIrisLog.info("Iris paste: {} at {},{},{} rot={} writes={} nonAir={} tilesRestored={} tilesSkipped={}",
key, target.getX(), target.getY(), target.getZ(), rotation, placer.writes(), placer.nonAirWrites(), placer.restoredTiles(), placer.skippedTiles());
return placer.writes() > 0 ? 1 : 0;
}
@@ -608,7 +606,7 @@ public final class ModdedObjectCommands {
try {
object = IrisData.loadAnyObject(key, engine == null ? null : engine.getData());
} catch (Throwable e) {
LOGGER.error("Iris object load failed for {}", key, e);
ModdedIrisLog.error("Iris object load failed for {}", key, e);
}
if (object == null) {
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_UNKNOWN_OBJECT, MessageArgument.untrusted("key", key)));
@@ -648,7 +646,7 @@ public final class ModdedObjectCommands {
try {
object = IrisData.loadAnyObject(key, engine == null ? null : engine.getData());
} catch (Throwable e) {
LOGGER.error("Iris object load failed for {}", key, e);
ModdedIrisLog.error("Iris object load failed for {}", key, e);
}
if (object == null) {
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_UNKNOWN_OBJECT_2, MessageArgument.untrusted("key", key)));
@@ -665,7 +663,7 @@ public final class ModdedObjectCommands {
try {
object.write(file);
} catch (IOException e) {
LOGGER.error("Iris object shrink save failed for {}", file.getAbsolutePath(), e);
ModdedIrisLog.error("Iris object shrink save failed for {}", file.getAbsolutePath(), e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_FAILED_SAVE_OBJECT_2, MessageArgument.untrusted("value", file.getName()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage()))));
return 0;
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.object.IObjectPlacer;
@@ -37,14 +38,11 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
final class ModdedObjectPlacer implements IObjectPlacer {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int DEFAULT_FLUID_HEIGHT = 63;
private final ServerLevel level;
@@ -199,7 +197,7 @@ final class ModdedObjectPlacer implements IObjectPlacer {
}
restoredTiles++;
} catch (Throwable e) {
LOGGER.error("Iris tile restore failed at {} {} {}", xx, yy, zz, e);
ModdedIrisLog.error("Iris tile restore failed at {} {} {}", xx, yy, zz, e);
skippedTiles++;
}
}
@@ -18,13 +18,12 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayDeque;
import java.util.Deque;
@@ -34,7 +33,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public final class ModdedObjectUndo {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int MAX_ENTRIES_PER_OWNER = 32;
private static final ConcurrentHashMap<UUID, Deque<Entry>> UNDOS = new ConcurrentHashMap<>();
private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);
@@ -48,7 +46,7 @@ public final class ModdedObjectUndo {
public static void init() {
if (INITIALIZED.compareAndSet(false, true)) {
LOGGER.info("Iris object undo service ready (bounded to {} paste(s) per player)", MAX_ENTRIES_PER_OWNER);
ModdedIrisLog.info("Iris object undo service ready (bounded to {} paste(s) per player)", MAX_ENTRIES_PER_OWNER);
}
}
@@ -93,7 +91,7 @@ public final class ModdedObjectUndo {
// dimension id must never have blocks replayed into the dead ServerLevel.
MinecraftServer server = entry.level().getServer();
if (server == null || server.getLevel(entry.level().dimension()) != entry.level()) {
LOGGER.warn("Iris object undo: skipped a stale entry for removed dimension {}",
ModdedIrisLog.warn("Iris object undo: skipped a stale entry for removed dimension {}",
entry.level().dimension().identifier());
continue;
}
@@ -103,10 +101,10 @@ public final class ModdedObjectUndo {
entry.level().setBlock(block.getKey(), block.getValue(), Block.UPDATE_CLIENTS | Block.UPDATE_KNOWN_SHAPE);
writes++;
} catch (Throwable e) {
LOGGER.error("Iris object undo: failed to revert a block at {}", block.getKey(), e);
ModdedIrisLog.error("Iris object undo: failed to revert a block at {}", block.getKey(), e);
}
}
LOGGER.info("Iris object undo: reverted {} block(s) in {}", writes, entry.level().dimension().identifier());
ModdedIrisLog.info("Iris object undo: reverted {} block(s) in {}", writes, entry.level().dimension().identifier());
reverted++;
}
return reverted;
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.core.pack.PackDirectoryResolver;
import art.arcane.iris.core.pack.PackResourceCleanup;
@@ -31,8 +32,6 @@ import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.MinecraftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
@@ -44,7 +43,6 @@ import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
public final class ModdedPackCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private ModdedPackCommands() {
@@ -139,7 +137,7 @@ public final class ModdedPackCommands {
}
server.execute(() -> report(source, result));
} catch (Throwable e) {
LOGGER.error("Iris pack validation failed for {}", target.getName(), e);
ModdedIrisLog.error("Iris pack validation failed for {}", target.getName(), e);
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_VALIDATION_FAILED, MessageArgument.untrusted("value", target.getName()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage())))));
broken++;
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.pregenerator.PregenListener;
import art.arcane.iris.core.pregenerator.PregenMantleBackpressure;
@@ -31,8 +32,6 @@ import net.minecraft.server.level.ChunkResult;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -48,7 +47,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
public final class ModdedPregenMethod implements PregeneratorMethod {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final TicketType PREGEN_TICKET = new TicketType(TicketType.NO_TIMEOUT, TicketType.FLAG_LOADING | TicketType.FLAG_KEEP_DIMENSION_ACTIVE);
private static final int ADAPTIVE_TIMEOUT_STEP = 3;
private static final long ADAPTIVE_RECOVERY_INTERVAL = 64L;
@@ -106,7 +104,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
@Override
public void init() {
pauseGuard.suspend();
LOGGER.info("Iris modded pregen init: dim={} mode={} inFlightCap={} timeout={}s workerPool={} chunkSystem={}",
ModdedIrisLog.info("Iris modded pregen init: dim={} mode={} inFlightCap={} timeout={}s workerPool={} chunkSystem={}",
level.dimension().identifier(),
sync ? "sync" : "async",
sync ? 1 : maxInFlight,
@@ -114,7 +112,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
describeWorkerPool(),
ModdedGenPool.describeChunkSystem());
if (!sync && !ModdedGenPool.parallelChunkSystem()) {
LOGGER.info("Iris pregen note: this loader uses the vanilla main-thread chunk system, which caps pregen throughput. For Bukkit-level speed on Fabric install C2ME (Concurrent Chunk Management Engine); on servers use Paper.");
ModdedIrisLog.info("Iris pregen note: this loader uses the vanilla main-thread chunk system, which caps pregen throughput. For Bukkit-level speed on Fabric install C2ME (Concurrent Chunk Management Engine); on servers use Paper.");
}
}
@@ -128,7 +126,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
Thread.currentThread().interrupt();
}
}
LOGGER.info("Iris modded pregen done: dim={} completed={} peakInFlight={} finalLimit={}",
ModdedIrisLog.info("Iris modded pregen done: dim={} completed={} peakInFlight={} finalLimit={}",
level.dimension().identifier(), completed.get(), inFlightPeak.get(), adaptiveLimit.get());
if (deferFinalSaveIfRequested()) {
return;
@@ -245,7 +243,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
}
long remainingNanos = deadline - System.nanoTime();
if (remainingNanos <= 0L) {
LOGGER.warn("Iris pregen level save did not complete in time for {}", level.dimension().identifier());
ModdedIrisLog.warn("Iris pregen level save did not complete in time for {}", level.dimension().identifier());
return;
}
long waitMillis = Math.max(1L, Math.min(FINAL_SAVE_POLL_MILLIS,
@@ -260,7 +258,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
continue;
} catch (ExecutionException e) {
Throwable cause = e.getCause() == null ? e : e.getCause();
LOGGER.error("Iris pregen level save failed for {}", level.dimension().identifier(), cause);
ModdedIrisLog.error("Iris pregen level save failed for {}", level.dimension().identifier(), cause);
throw new IllegalStateException("Iris pregen level save failed for "
+ level.dimension().identifier(), cause);
}
@@ -337,7 +335,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
try {
Object result = loadFuture.get(timeoutSeconds, TimeUnit.SECONDS);
if (result instanceof ChunkResult<?> chunkResult && !chunkResult.isSuccess()) {
LOGGER.warn("Iris pregen chunk {},{} returned no chunk: {}", x, z, chunkResult.getError());
ModdedIrisLog.warn("Iris pregen chunk {},{} returned no chunk: {}", x, z, chunkResult.getError());
listener.onChunkFailed(x, z);
return;
}
@@ -364,7 +362,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
// this abort the pregen thread spins hot against the dead chunk source until the JVM dies.
if (level.getServer().isStopped() || !level.getServer().isRunning()) {
if (SERVER_DEAD_LOGGED.compareAndSet(false, true)) {
LOGGER.error("Iris pregen aborting: the server is no longer running (dim={})", level.dimension().identifier());
ModdedIrisLog.error("Iris pregen aborting: the server is no longer running (dim={})", level.dimension().identifier());
}
listener.onChunkFailed(x, z);
ModdedPregenJob.stop();
@@ -401,7 +399,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
return;
}
if (result instanceof ChunkResult<?> chunkResult && !chunkResult.isSuccess()) {
LOGGER.warn("Iris pregen chunk {},{} returned no chunk: {}", x, z, chunkResult.getError());
ModdedIrisLog.warn("Iris pregen chunk {},{} returned no chunk: {}", x, z, chunkResult.getError());
listener.onChunkFailed(x, z);
return;
}
@@ -425,10 +423,10 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
private void logChunkFailure(int x, int z, Throwable failure) {
Throwable cause = unwrap(failure);
if (failureDetailLogged.compareAndSet(false, true)) {
LOGGER.warn("Iris pregen chunk {},{} failed; first failure follows", x, z, cause);
ModdedIrisLog.warn("Iris pregen chunk {},{} failed; first failure follows", x, z, cause);
return;
}
LOGGER.warn("Iris pregen chunk {},{} failed: {}", x, z, cause.toString());
ModdedIrisLog.warn("Iris pregen chunk {},{} failed: {}", x, z, cause.toString());
}
private void markFinished() {
@@ -500,7 +498,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
try {
engine.getMantle().forceCleanupChunk(x, z);
} catch (Throwable e) {
LOGGER.debug("Iris pregen mantle cleanup skipped for {},{}: {}", x, z, e.toString());
ModdedIrisLog.debug("Iris pregen mantle cleanup skipped for {},{}: {}", x, z, e.toString());
}
}
@@ -566,7 +564,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
try {
current = dedicated.pauseWhenEmptySeconds();
} catch (Throwable e) {
LOGGER.warn("Iris pregen could not read pause-when-empty-seconds: {}", e.toString());
ModdedIrisLog.warn("Iris pregen could not read pause-when-empty-seconds: {}", e.toString());
return;
}
if (current <= 0) {
@@ -591,7 +589,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
}
suspendedFrom.set(current);
armCrashRestore();
LOGGER.info("Iris pregen: suspending pause-when-empty (was {}s), restored when the job ends", current);
ModdedIrisLog.info("Iris pregen: suspending pause-when-empty (was {}s), restored when the job ends", current);
}
private void restore() {
@@ -606,9 +604,9 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
}
try {
dedicated.setPauseWhenEmptySeconds(previous);
LOGGER.info("Iris pregen: {} pause-when-empty ({}s)", what, previous);
ModdedIrisLog.info("Iris pregen: {} pause-when-empty ({}s)", what, previous);
} catch (Throwable e) {
LOGGER.error("Iris pregen could not restore pause-when-empty-seconds={}: {}. Set pause-when-empty-seconds={} in server.properties.",
ModdedIrisLog.error("Iris pregen could not restore pause-when-empty-seconds={}: {}. Set pause-when-empty-seconds={} in server.properties.",
previous, e.toString(), previous);
}
}
@@ -655,11 +653,11 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
if (!pauseStillArmed()) {
return;
}
LOGGER.error("Iris pregen is timing out on an empty server while pause-when-empty-seconds is active: the paused server stops ticking. Set pause-when-empty-seconds=0 in server.properties, or keep a player online while pregenerating.");
ModdedIrisLog.error("Iris pregen is timing out on an empty server while pause-when-empty-seconds is active: the paused server stops ticking. Set pause-when-empty-seconds=0 in server.properties, or keep a player online while pregenerating.");
}
private void refuse(int current, String reason) {
LOGGER.error("Iris pregen could not suspend pause-when-empty-seconds={} ({}). The server stops ticking once empty, which stalls pregen: set pause-when-empty-seconds=0 in server.properties, or keep a player online while pregenerating.",
ModdedIrisLog.error("Iris pregen could not suspend pause-when-empty-seconds={} ({}). The server stops ticking once empty, which stalls pregen: set pause-when-empty-seconds=0 in server.properties, or keep a player online while pregenerating.",
current, reason);
}
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.tools.WorldMaintenance;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.mantle.EngineMantle;
@@ -51,8 +52,6 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.phys.AABB;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -65,7 +64,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.ModdedCommandMessages;
public final class ModdedRegen {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int APPLY_AHEAD = 8;
private static final long CHUNK_SLOT_TIMEOUT_MILLIS = 120000L;
private static final long FINAL_APPLY_TIMEOUT_MILLIS = 300000L;
@@ -101,7 +99,7 @@ public final class ModdedRegen {
ModdedRegen job = new ModdedRegen(source, level, generator, engine, centerX, centerZ, radius);
int chunks = (job.radius * 2 + 1) * (job.radius * 2 + 1);
job.ok("Regen started: " + chunks + " chunk(s) around " + centerX + "," + centerZ + ". Deleting and regenerating in place.");
LOGGER.info("Iris regen start: dim={} center={},{} radius={} chunks={}",
ModdedIrisLog.info("Iris regen start: dim={} center={},{} radius={} chunks={}",
level.dimension().identifier(), centerX, centerZ, job.radius, chunks);
Thread thread = new Thread(job::run, "Iris Regenerate");
thread.setDaemon(true);
@@ -117,11 +115,11 @@ public final class ModdedRegen {
List<int[]> targets = ChunkSpiral.centerOut(centerX, centerZ, radius);
int applied = regenerate(targets);
ok("Regen finished: " + applied + "/" + targets.size() + " chunk(s) in " + Form.duration(M.ms() - startedAt, 2));
LOGGER.info("Iris regen done: {}/{} chunks in {}ms", applied, targets.size(), M.ms() - startedAt);
ModdedIrisLog.info("Iris regen done: {}/{} chunks in {}ms", applied, targets.size(), M.ms() - startedAt);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Throwable e) {
LOGGER.error("Iris regen failed", e);
ModdedIrisLog.error("Iris regen failed", e);
fail("Regen failed: " + e);
} finally {
WorldMaintenance.endWorldMaintenance(worldIdentity, "regen");
@@ -155,7 +153,7 @@ public final class ModdedRegen {
int chunkZ = target[1];
if (!inFlight.tryAcquire(CHUNK_SLOT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
aborted.set(true);
LOGGER.error("Iris regen aborted: chunk {},{} waited {}ms for an apply slot ({}/{} done)",
ModdedIrisLog.error("Iris regen aborted: chunk {},{} waited {}ms for an apply slot ({}/{} done)",
chunkX, chunkZ, CHUNK_SLOT_TIMEOUT_MILLIS, completed.get(), total);
fail("Regen aborted: apply pipeline stalled at " + completed.get() + "/" + total + " chunk(s)");
break;
@@ -173,7 +171,7 @@ public final class ModdedRegen {
try {
engine.generate(chunkX << 4, chunkZ << 4, blocks, biomes, false);
} catch (Throwable e) {
LOGGER.error("Iris regen chunk {},{} generation failed", chunkX, chunkZ, e);
ModdedIrisLog.error("Iris regen chunk {},{} generation failed", chunkX, chunkZ, e);
fail("Chunk " + chunkX + "," + chunkZ + " generation FAILED: " + e.getClass().getSimpleName());
completed.incrementAndGet();
inFlight.release();
@@ -190,7 +188,7 @@ public final class ModdedRegen {
success = true;
applied.incrementAndGet();
} catch (Throwable e) {
LOGGER.error("Iris regen chunk {},{} apply failed", chunkX, chunkZ, e);
ModdedIrisLog.error("Iris regen chunk {},{} apply failed", chunkX, chunkZ, e);
fail("Chunk " + chunkX + "," + chunkZ + " apply FAILED: " + e.getClass().getSimpleName());
} finally {
int done = completed.incrementAndGet();
@@ -212,7 +210,7 @@ public final class ModdedRegen {
if (!allApplied.await(FINAL_APPLY_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {
aborted.set(true);
long outstanding = allApplied.getCount();
LOGGER.error("Iris regen aborted: {} of {} chunk(s) did not finish within {}ms",
ModdedIrisLog.error("Iris regen aborted: {} of {} chunk(s) did not finish within {}ms",
outstanding, total, FINAL_APPLY_TIMEOUT_MILLIS);
fail("Regen aborted: " + outstanding + " of " + total + " chunk(s) never finished");
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.core.structure.StructureIndexService;
import art.arcane.iris.engine.framework.Engine;
@@ -40,8 +41,6 @@ import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.List;
@@ -53,7 +52,6 @@ import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
public final class ModdedStructureCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private static final SuggestionProvider<CommandSourceStack> IRIS_STRUCTURE_KEYS = (CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) -> suggestIrisStructureKeys(context, builder);
@@ -213,7 +211,7 @@ public final class ModdedStructureCommands {
piece.getObject().place(piece.getX(), piece.getY(), piece.getZ(), placer, config, rng, null, null, data);
}
} catch (Throwable e) {
LOGGER.error("Iris structure place failed for {}", key, e);
ModdedIrisLog.error("Iris structure place failed for {}", key, e);
ModdedObjectUndo.record(owner, level, placer.undoSnapshot());
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_PLACE_FAILED_PARTIAL_CHANGES_RECORDED_UNDO, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
return 0;
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.gui.GuiHost;
import art.arcane.iris.core.gui.NoiseExplorerGUI;
@@ -63,8 +64,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Relative;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeroturnaround.zip.ZipUtil;
import java.awt.Desktop;
@@ -85,7 +84,6 @@ import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
public final class ModdedStudioCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private static final Pattern PROJECT_NAME = Pattern.compile("[a-z0-9_-]+");
private static final Pattern STUDIO_ID_SANITIZER = Pattern.compile("[^a-z0-9_-]");
@@ -284,7 +282,7 @@ public final class ModdedStudioCommands {
try {
workspace = ModdedWorkspaceGenerator.writeWorkspace(IrisData.get(folder), folder, open);
} catch (Throwable e) {
LOGGER.error("Iris workspace write failed for {}", folder, e);
ModdedIrisLog.error("Iris workspace write failed for {}", folder, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_FAILED_WRITE_WORKSPACE, MessageArgument.untrusted("value", folder.getAbsolutePath()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage()))));
return 0;
}
@@ -299,7 +297,7 @@ public final class ModdedStudioCommands {
try {
Desktop.getDesktop().open(workspace);
} catch (Throwable e) {
LOGGER.error("Iris workspace open failed for {}", workspace, e);
ModdedIrisLog.error("Iris workspace open failed for {}", workspace, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_COULD_NOT_OPEN, MessageArgument.untrusted("value", workspace.getName()), MessageArgument.untrusted("value2", e.getClass().getSimpleName())));
return 0;
}
@@ -380,8 +378,9 @@ public final class ModdedStudioCommands {
try {
File packFolder = new File(ModdedPackCommands.packsRoot(), pack);
if (!new File(packFolder, "dimensions/" + pack + ".json").isFile()) {
server.execute(() -> IrisModdedCommands.fail(source, "Pack '" + pack
+ "' is not installed. Use /iris download pack=overworld or pack=underworld, then restart."));
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(
ModdedCommandMessages.MODDED_STUDIO_COMMANDS_REQUIRED_PACK_IS_NOT_INSTALLED_INSTALL_THEN_RESTART,
MessageArgument.untrusted("pack", pack))));
return;
}
IrisData data = IrisData.get(packFolder);
@@ -393,7 +392,7 @@ public final class ModdedStudioCommands {
try {
ModdedWorkspaceGenerator.writeWorkspace(data, packFolder, true);
} catch (Throwable workspaceError) {
LOGGER.error("Iris workspace write failed for {}", packFolder, workspaceError);
ModdedIrisLog.error("Iris workspace write failed for {}", packFolder, workspaceError);
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(
ModdedCommandMessages.MODDED_STUDIO_COMMANDS_FAILED_WRITE_WORKSPACE,
MessageArgument.untrusted("value", packFolder.getAbsolutePath()),
@@ -407,7 +406,7 @@ public final class ModdedStudioCommands {
}
});
} catch (Throwable e) {
LOGGER.error("Iris studio open failed for {}", pack, e);
ModdedIrisLog.error("Iris studio open failed for {}", pack, e);
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_OPEN_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e)))));
}
}
@@ -417,7 +416,7 @@ public final class ModdedStudioCommands {
try {
handle = ModdedDimensionManager.create(server, dimensionId, pack, pack, seed);
} catch (Throwable e) {
LOGGER.error("Iris console studio injection failed for {} ({})", dimensionId, pack, e);
ModdedIrisLog.error("Iris console studio injection failed for {} ({})", dimensionId, pack, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_INJECTION_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
return;
}
@@ -430,7 +429,7 @@ public final class ModdedStudioCommands {
surface = engine.getMinHeight() + engine.getHeight(8, 8, false) + 2;
}
} catch (Throwable e) {
LOGGER.error("Iris console studio surface probe failed for {}", dimensionId, e);
ModdedIrisLog.error("Iris console studio surface probe failed for {}", dimensionId, e);
}
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_CONSOLE_STUDIO_OPEN_NOW_RUNS_SEED_TRANSIENT_NOT_WRITTEN_IRIS, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("seed", seed)));
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_ENTER_IT_WITH_EXECUTE_RUN_TP_S_8_5_8, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("surface", surface)));
@@ -447,7 +446,7 @@ public final class ModdedStudioCommands {
try {
handle = ModdedDimensionManager.create(server, dimensionId, pack, pack, seed);
} catch (Throwable e) {
LOGGER.error("Iris studio injection failed for {} ({})", dimensionId, pack, e);
ModdedIrisLog.error("Iris studio injection failed for {} ({})", dimensionId, pack, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_INJECTION_FAILED_2, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
return;
}
@@ -460,7 +459,7 @@ public final class ModdedStudioCommands {
surface = engine.getMinHeight() + engine.getHeight(8, 8, false) + 2;
}
} catch (Throwable e) {
LOGGER.error("Iris studio surface probe failed for {}", dimensionId, e);
ModdedIrisLog.error("Iris studio surface probe failed for {}", dimensionId, e);
}
player.teleportTo(studio, 8.5D, surface, 8.5D, java.util.Set.<Relative>of(), player.getYRot(), player.getXRot(), false);
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_OPEN_NOW_RUNS_SEED_USE_IRIS_STUDIO_CLOSE_WHEN, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("seed", seed)));
@@ -480,7 +479,7 @@ public final class ModdedStudioCommands {
try {
ModdedDimensionManager.remove(server, dimensionId, true);
} catch (Throwable e) {
LOGGER.error("Iris studio close failed for {}", dimensionId, e);
ModdedIrisLog.error("Iris studio close failed for {}", dimensionId, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_CLOSE_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
return 0;
}
@@ -553,7 +552,7 @@ public final class ModdedStudioCommands {
surface = engine.getMinHeight() + engine.getHeight(8, 8, false) + 2;
}
} catch (Throwable e) {
LOGGER.error("Iris tpstudio surface probe failed", e);
ModdedIrisLog.error("Iris tpstudio surface probe failed", e);
}
player.teleportTo(studio, 8.5D, surface, 8.5D, java.util.Set.<Relative>of(), player.getYRot(), player.getXRot(), false);
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_TELEPORTED_YOUR_STUDIO, MessageArgument.untrusted("dimensionId", dimensionId)));
@@ -593,22 +592,23 @@ public final class ModdedStudioCommands {
try {
File templateFolder = new File(packsRoot, template);
if (!new File(templateFolder, "dimensions/" + template + ".json").isFile()) {
server.execute(() -> IrisModdedCommands.fail(source, "Template pack '" + template
+ "' is not installed. Install its zip with /iris download link=<zip-url>, then restart."));
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(
ModdedCommandMessages.MODDED_STUDIO_COMMANDS_REQUIRED_PACK_IS_NOT_INSTALLED_INSTALL_THEN_RESTART,
MessageArgument.untrusted("pack", template))));
return;
}
IrisProjectCopier.copyProject(templateFolder, target, template, name);
try {
ModdedWorkspaceGenerator.writeWorkspace(IrisData.get(target), target);
} catch (IOException e) {
LOGGER.error("Iris studio create workspace generation failed for {}", name, e);
ModdedIrisLog.error("Iris studio create workspace generation failed for {}", name, e);
}
server.execute(() -> {
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_CREATED_PROJECT_AT, MessageArgument.untrusted("name", name), MessageArgument.untrusted("value", target.getAbsolutePath())));
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_EDIT_DIMENSIONS_JSON_REST_PACK_VSCODE_WORKSPACE_WITH_JSON_SCHEMA, MessageArgument.untrusted("name", name)));
});
} catch (Throwable e) {
LOGGER.error("Iris studio create failed for {}", name, e);
ModdedIrisLog.error("Iris studio create failed for {}", name, e);
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PROJECT_CREATION_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e)))));
}
}, "Iris Studio Create");
@@ -630,7 +630,7 @@ public final class ModdedStudioCommands {
File result = compilePackage(folder, dimKey);
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACKAGE_COMPILED, MessageArgument.untrusted("value", result.getAbsolutePath()))));
} catch (Throwable e) {
LOGGER.error("Iris package failed for {}", dimKey, e);
ModdedIrisLog.error("Iris package failed for {}", dimKey, e);
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACKAGING_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e)))));
}
}, "Iris Studio Package");
@@ -728,7 +728,7 @@ public final class ModdedStudioCommands {
IO.copyFile(objectFile, new File(folder, "objects/" + objectKey + ".iob"));
hashes.append(IO.hash(objectFile));
} catch (Throwable e) {
LOGGER.error("Iris package failed to copy object {}", objectKey, e);
ModdedIrisLog.error("Iris package failed to copy object {}", objectKey, e);
}
}
@@ -793,7 +793,7 @@ public final class ModdedStudioCommands {
IO.writeAll(new File(folder, category + "/" + key + ".json"), json);
return IO.hash(json);
} catch (Throwable e) {
LOGGER.error("Iris package failed to write {}/{}", category, key, e);
ModdedIrisLog.error("Iris package failed to write {}/{}", category, key, e);
return "";
}
}
@@ -838,7 +838,7 @@ public final class ModdedStudioCommands {
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_RARITY, MessageArgument.untrusted("key", key), MessageArgument.untrusted("rarity", rarity), MessageArgument.untrusted("value", Form.f((double) count.get() / totalTasks * 100, 2))));
}));
} catch (Throwable e) {
LOGGER.error("Iris region sampling failed", e);
ModdedIrisLog.error("Iris region sampling failed", e);
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_REGION_SAMPLING_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()))));
}
}, "Iris Region Sampler");
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.framework.IrisStructureLocator;
import art.arcane.iris.engine.framework.NativeStructureGenerationPolicy;
@@ -31,8 +32,6 @@ import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.levelgen.structure.Structure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashSet;
@@ -44,7 +43,6 @@ import java.util.TreeMap;
import java.util.function.Predicate;
final class ModdedUnregisteredStructures {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private ModdedUnregisteredStructures() {
}
@@ -67,13 +65,13 @@ final class ModdedUnregisteredStructures {
.filter((ExcludedStructure entry) -> entry.status() == ReportStatus.UNPLACED)
.count();
long hidden = excluded.size() - unregistered - unplaced;
LOGGER.info("[Iris goto unregistered] {} structure candidate(s) excluded from /iris goto structure in {}",
ModdedIrisLog.info("[Iris goto unregistered] {} structure candidate(s) excluded from /iris goto structure in {}",
excluded.size(), dimension);
for (ExcludedStructure entry : excluded) {
LOGGER.info("[Iris goto unregistered] [{}] {} - {}",
ModdedIrisLog.info("[Iris goto unregistered] [{}] {} - {}",
entry.status().label(), entry.key(), entry.reason());
}
LOGGER.info("[Iris goto unregistered] Inventory scope is the live registry, this pack's "
ModdedIrisLog.info("[Iris goto unregistered] Inventory scope is the live registry, this pack's "
+ "nativeStructures placements, and structureLoader editable resources. This is deterministic "
+ "eligibility analysis and performs no chunk search; absent unmanaged datapack resources "
+ "cannot be inferred after registry loading.");
@@ -82,7 +80,7 @@ final class ModdedUnregisteredStructures {
+ unregistered + " unregistered, " + unplaced + " unplaced).");
return 1;
} catch (Throwable error) {
LOGGER.error("Iris failed to build the excluded structure report for {}",
ModdedIrisLog.error("Iris failed to build the excluded structure report for {}",
level.dimension().identifier(), error);
IrisModdedCommands.fail(source,
"Iris could not build the excluded structure report; see the server console.");
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.RuntimeUiMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
@@ -42,8 +43,6 @@ import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.item.component.ItemLore;
import net.minecraft.world.item.component.TooltipDisplay;
import net.minecraft.world.level.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.util.List;
@@ -52,7 +51,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
public final class ModdedWandService {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final ConcurrentHashMap<UUID, Selection> SELECTIONS = new ConcurrentHashMap<>();
private static final String WAND_TAG = "iris_wand";
private static final String DUST_TAG = "iris_dust";
@@ -213,7 +211,7 @@ public final class ModdedWandService {
draw(player.level(), player, selection);
}
} catch (Throwable e) {
LOGGER.error("Iris wand selection draw failed", e);
ModdedIrisLog.error("Iris wand selection draw failed", e);
}
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.localization.IrisLanguage;
import art.arcane.iris.core.localization.IrisMessages;
import art.arcane.iris.core.localization.ModdedCommandMessages;
@@ -66,8 +67,6 @@ import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -77,7 +76,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
public final class ModdedWhatCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE =
Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private static final SuggestionProvider<CommandSourceStack> MARKER_TYPES =
@@ -343,7 +341,7 @@ public final class ModdedWhatCommands {
MessageArgument.untrusted("object", object)));
}
} catch (Throwable error) {
LOGGER.error("Iris object lookup failed for /iris what block at {}, {}, {}",
ModdedIrisLog.error("Iris object lookup failed for /iris what block at {}, {}, {}",
pos.getX(), pos.getY(), pos.getZ(), error);
}
}
@@ -486,7 +484,7 @@ public final class ModdedWhatCommands {
private static void markerFailure(CommandSourceStack source,
ModdedScheduler scheduler, MarkerRun run, Throwable error) {
LOGGER.error("Iris marker scan failed for {}", run.marker(), error);
ModdedIrisLog.error("Iris marker scan failed for {}", run.marker(), error);
scheduler.global(() -> {
if (ACTIVE_MARKER_RUNS.remove(run.playerId(), run)) {
IrisModdedCommands.fail(source, IrisLanguage.plain(
@@ -514,7 +512,7 @@ public final class ModdedWhatCommands {
private static void logLookupFailure(CommandSourceStack source,
String operation, Throwable error,
TextKey message) {
LOGGER.error("Iris /what {} lookup failed in {}", operation,
ModdedIrisLog.error("Iris /what {} lookup failed in {}", operation,
source.getLevel().dimension().identifier(), error);
IrisModdedCommands.fail(source, IrisLanguage.plain(
message,
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.core.pack.BrokenPackException;
import art.arcane.iris.core.pack.PackValidationRegistry;
@@ -42,8 +43,6 @@ import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.arguments.IdentifierArgument;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
@@ -57,7 +56,6 @@ import art.arcane.iris.core.localization.ModdedCommandMessages;
import art.arcane.iris.core.localization.RuntimeUiMessages;
import art.arcane.volmlib.util.localization.MessageArgument;
public final class ModdedWorldCommands {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
private static final String DEFAULT_NAMESPACE = "irisworldgen";
private static final long DEFAULT_SEED = 1337L;
@@ -174,8 +172,9 @@ public final class ModdedWorldCommands {
if (packFolder.isDirectory()) {
return enableInstalled(source, server, dimensionId, pack, packDimension, seed);
}
IrisModdedCommands.fail(source, "Pack '" + pack
+ "' is not installed. Use /iris download pack=overworld or pack=underworld, then restart.");
IrisModdedCommands.fail(source, IrisLanguage.plain(
ModdedCommandMessages.MODDED_WORLD_COMMANDS_REQUIRED_PACK_IS_NOT_INSTALLED_INSTALL_THEN_RESTART,
MessageArgument.untrusted("pack", pack)));
return 0;
}
@@ -189,7 +188,7 @@ public final class ModdedWorldCommands {
try {
ModdedDimensionManager.createPersistent(server, dimensionId, pack, packDimension, seed);
} catch (Throwable e) {
LOGGER.error("Iris world injection failed for {} (pack={} dim={})", dimensionId, pack, packDimension, e);
ModdedIrisLog.error("Iris world injection failed for {} (pack={} dim={})", dimensionId, pack, packDimension, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FAILED_INJECT_IRIS_WORLD, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
return 0;
}
@@ -220,7 +219,7 @@ public final class ModdedWorldCommands {
try {
ModdedDimensionManager.createPersistent(server, dimensionId, pack, packDimension, seed);
} catch (Throwable e) {
LOGGER.error("Iris primary world injection failed for {} (pack={} dim={})", dimensionId, pack, packDimension, e);
ModdedIrisLog.error("Iris primary world injection failed for {} (pack={} dim={})", dimensionId, pack, packDimension, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FAILED_INJECT_IRIS_PRIMARY_WORLD, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
return 0;
}
@@ -265,8 +264,9 @@ public final class ModdedWorldCommands {
if (packFolder.isDirectory()) {
return applyMainWorld(source, pack, packDimension, packRaw, seed);
}
IrisModdedCommands.fail(source, "Pack '" + pack
+ "' is not installed. Use /iris download pack=overworld or pack=underworld, then restart.");
IrisModdedCommands.fail(source, IrisLanguage.plain(
ModdedCommandMessages.MODDED_WORLD_COMMANDS_REQUIRED_PACK_IS_NOT_INSTALLED_INSTALL_THEN_RESTART,
MessageArgument.untrusted("pack", pack)));
return 0;
}
@@ -279,7 +279,7 @@ public final class ModdedWorldCommands {
return 0;
}
} catch (Throwable e) {
LOGGER.error("Iris main world pack load failed for {} (dim={})", pack, packDimension, e);
ModdedIrisLog.error("Iris main world pack load failed for {} (dim={})", pack, packDimension, e);
if (PackValidationRegistry.get(pack) == null) {
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_IS_NOT_READY_YET_STILL_LOADING_VALIDATING_TRY_COMMAND, MessageArgument.untrusted("pack", pack)));
return 0;
@@ -384,7 +384,7 @@ public final class ModdedWorldCommands {
try {
removed = ModdedDimensionManager.removePersistent(server, dimensionId, wipeStorage);
} catch (Throwable e) {
LOGGER.error("Iris world removal failed for {}", dimensionId, e);
ModdedIrisLog.error("Iris world removal failed for {}", dimensionId, e);
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FAILED_REMOVE_IRIS_WORLD, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
return 0;
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.service;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.service.EngineMaintenance;
import art.arcane.iris.engine.framework.Engine;
@@ -27,8 +28,6 @@ import art.arcane.iris.modded.ModdedWorldEngines;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.util.project.context.IrisContext;
import net.minecraft.server.MinecraftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
@@ -42,7 +41,6 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public final class ModdedEngineMaintenanceService implements ModdedTickableService {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final long MAINTENANCE_PERIOD_MILLIS = 2_000L;
private static final long SAVE_PERIOD_MILLIS = 60_000L;
private static final long SHUTDOWN_TIMEOUT_SECONDS = 30L;
@@ -120,7 +118,7 @@ public final class ModdedEngineMaintenanceService implements ModdedTickableServi
} catch (RejectedExecutionException exception) {
inFlight.remove(engine);
if (active == service && !active.isShutdown()) {
LOGGER.error("Iris rejected engine maintenance for {}", engineName(engine), exception);
ModdedIrisLog.error("Iris rejected engine maintenance for {}", engineName(engine), exception);
}
}
}
@@ -148,7 +146,7 @@ public final class ModdedEngineMaintenanceService implements ModdedTickableServi
EngineMaintenance.Outcome outcome = EngineMaintenance.run(engine);
if (outcome.unloadedTectonicPlates() > 0) {
LOGGER.debug("Iris unloaded {} tectonic plates in {}ms for {}",
ModdedIrisLog.debug("Iris unloaded {} tectonic plates in {}ms for {}",
outcome.unloadedTectonicPlates(), outcome.unloadDurationMillis(), engineName(engine));
}
} catch (GenerationSessionException exception) {
@@ -156,13 +154,13 @@ public final class ModdedEngineMaintenanceService implements ModdedTickableServi
return;
}
IrisLogging.reportError(exception);
LOGGER.error("Iris engine maintenance session failed for {}", engineName(engine), exception);
ModdedIrisLog.error("Iris engine maintenance session failed for {}", engineName(engine), exception);
} catch (Throwable exception) {
if (EngineMaintenance.isMantleClosed(exception)) {
return;
}
IrisLogging.reportError(exception);
LOGGER.error("Iris engine maintenance failed for {}", engineName(engine), exception);
ModdedIrisLog.error("Iris engine maintenance failed for {}", engineName(engine), exception);
}
}
@@ -180,7 +178,7 @@ public final class ModdedEngineMaintenanceService implements ModdedTickableServi
return;
}
IrisLogging.reportError(exception);
LOGGER.error("Iris engine save failed for {}", engineName(engine), exception);
ModdedIrisLog.error("Iris engine save failed for {}", engineName(engine), exception);
}
}
@@ -212,13 +210,13 @@ public final class ModdedEngineMaintenanceService implements ModdedTickableServi
IllegalStateException failure = new IllegalStateException(
"Iris engine maintenance workers did not stop after shutdownNow");
IrisLogging.reportError(failure);
LOGGER.error("Iris engine maintenance did not terminate; active engine lifecycle leases will block unsafe shutdown", failure);
ModdedIrisLog.error("Iris engine maintenance did not terminate; active engine lifecycle leases will block unsafe shutdown", failure);
return false;
} catch (InterruptedException exception) {
active.shutdownNow();
Thread.currentThread().interrupt();
IrisLogging.reportError(exception);
LOGGER.error("Interrupted while draining Iris engine maintenance", exception);
ModdedIrisLog.error("Interrupted while draining Iris engine maintenance", exception);
return false;
}
}
@@ -18,11 +18,10 @@
package art.arcane.iris.modded.service;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.engine.framework.MeteredCache;
import art.arcane.iris.engine.framework.PreservationRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.ref.WeakReference;
import java.util.List;
@@ -31,7 +30,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
public final class ModdedPreservationService implements ModdedService, PreservationRegistry {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final long DEREFERENCE_INTERVAL_MILLIS = 60000L;
private final List<Thread> threads = new CopyOnWriteArrayList<>();
@@ -107,17 +105,17 @@ public final class ModdedPreservationService implements ModdedService, Preservat
}
try {
thread.interrupt();
LOGGER.info("Iris preservation interrupted thread {}", thread.getName());
ModdedIrisLog.info("Iris preservation interrupted thread {}", thread.getName());
} catch (Throwable error) {
LOGGER.error("Iris preservation failed to interrupt thread {}", thread.getName(), error);
ModdedIrisLog.error("Iris preservation failed to interrupt thread {}", thread.getName(), error);
}
}
for (ExecutorService service : services) {
try {
service.shutdownNow();
LOGGER.info("Iris preservation shut down executor {}", service);
ModdedIrisLog.info("Iris preservation shut down executor {}", service);
} catch (Throwable error) {
LOGGER.error("Iris preservation failed to shut down executor {}", service, error);
ModdedIrisLog.error("Iris preservation failed to shut down executor {}", service, error);
}
}
}
@@ -60,6 +60,6 @@ public final class ModdedSettingsHotloadService implements ModdedTickableService
}
private static File settingsFile() {
return IrisPlatforms.get().dataFile("settings.json");
return IrisPlatforms.get().dataFile("iris.json");
}
}
@@ -18,6 +18,7 @@
package art.arcane.iris.modded.service;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.gui.PregeneratorJob;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.core.tools.WorldMaintenance;
@@ -37,8 +38,6 @@ import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.io.ReactiveFolder;
import art.arcane.volmlib.util.scheduling.ChronoLatch;
import net.minecraft.server.MinecraftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.HashSet;
@@ -52,7 +51,6 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
public final class ModdedStudioHotloadService implements ModdedTickableService, EnginePlatformHooks {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final String STUDIO_DIMENSION_PREFIX = "irisworldgen:studio_";
private static final long POLL_MILLIS = 250L;
private static final long CHECK_LATCH_MILLIS = 1_000L;
@@ -237,7 +235,7 @@ public final class ModdedStudioHotloadService implements ModdedTickableService,
folder.check();
}
} catch (Throwable e) {
LOGGER.error("Iris studio hotload check failed for {}", dimensionId, e);
ModdedIrisLog.error("Iris studio hotload check failed for {}", dimensionId, e);
}
}
@@ -249,9 +247,9 @@ public final class ModdedStudioHotloadService implements ModdedTickableService,
try {
engine.hotloadSilently();
generator.onHotload();
LOGGER.info("Iris studio hotload {} pack={} {}ms", dimensionId, engine.getDimension().getLoadKey(), System.currentTimeMillis() - start);
ModdedIrisLog.info("Iris studio hotload {} pack={} {}ms", dimensionId, engine.getDimension().getLoadKey(), System.currentTimeMillis() - start);
} catch (Throwable e) {
LOGGER.error("Iris studio hotload failed for {}", dimensionId, e);
ModdedIrisLog.error("Iris studio hotload failed for {}", dimensionId, e);
throw new IllegalStateException("Iris studio hotload failed for " + dimensionId, e);
}
}
@@ -275,7 +273,7 @@ public final class ModdedStudioHotloadService implements ModdedTickableService,
IrisData data = engine.getData();
ModdedWorkspaceGenerator.writeWorkspace(data, data.getDataFolder());
} catch (Throwable e) {
LOGGER.error("Iris {} failed for {}", operation, engine.getDimension().getLoadKey(), e);
ModdedIrisLog.error("Iris {} failed for {}", operation, engine.getDimension().getLoadKey(), e);
}
}
@@ -1,5 +1,6 @@
package art.arcane.iris.modded.service;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.modded.ModdedEngineBootstrap;
import art.arcane.iris.modded.ModdedScheduler;
import net.minecraft.core.BlockPos;
@@ -12,8 +13,6 @@ import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
@@ -21,7 +20,6 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
final class ModdedTreeFellerPresentation {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final int MIN_BLOCKS_PER_PULSE = 4;
private static final int MAX_BLOCKS_PER_PULSE = 64;
private static final int TARGET_EROSION_PULSES = 60;
@@ -215,13 +213,13 @@ final class ModdedTreeFellerPresentation {
private void reportEffectFailure(Throwable error) {
if (effectFailureReported.compareAndSet(false, true)) {
LOGGER.error("Iris modded tree-feller presentation failed", error);
ModdedIrisLog.error("Iris modded tree-feller presentation failed", error);
}
}
private void reportDeliveryFailure(Throwable error) {
if (deliveryFailureReported.compareAndSet(false, true)) {
LOGGER.error("Iris modded tree-feller drop delivery failed", error);
ModdedIrisLog.error("Iris modded tree-feller drop delivery failed", error);
}
}
}
@@ -1,5 +1,6 @@
package art.arcane.iris.modded.service;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.service.tree.TreeDefinitionIndex;
import art.arcane.iris.core.service.tree.TreeMarkerTraversal;
@@ -23,8 +24,6 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
@@ -38,7 +37,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
public final class ModdedTreeFellerService implements ModdedTickableService {
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
private static final ThreadLocal<Integer> BREAK_PROBE_DEPTH = ThreadLocal.withInitial(() -> 0);
private final AtomicBoolean enabled = new AtomicBoolean();
@@ -245,7 +243,7 @@ public final class ModdedTreeFellerService implements ModdedTickableService {
(x, y, z) -> markerAt(prepared.engine(), prepared.minimumY(), x, y, z)
);
} catch (Throwable error) {
LOGGER.error("Iris modded tree-feller discovery failed", error);
ModdedIrisLog.error("Iris modded tree-feller discovery failed", error);
discovery = new TreeMarkerTraversal.Discovery(List.of(), false);
}
TreeMarkerTraversal.Discovery resolved = discovery;
@@ -0,0 +1,38 @@
package art.arcane.iris.client;
import art.arcane.iris.spi.protocol.IrisMessage;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class IrisClientHotloadTest {
private static final IrisMessage.DimensionStatus OVERWORLD = new IrisMessage.DimensionStatus(
"overworld",
"pack",
1L,
-64,
320,
true
);
@Test
public void successfulCurrentPackHotloadInvalidatesWorldCaches() {
IrisMessage.StudioHotload hotload = new IrisMessage.StudioHotload("pack", 0, false, "");
assertTrue(IrisClient.shouldInvalidateForHotload(OVERWORLD, hotload));
}
@Test
public void failedOrUnrelatedHotloadRetainsWorldCaches() {
assertFalse(IrisClient.shouldInvalidateForHotload(
OVERWORLD,
new IrisMessage.StudioHotload("pack", 0, true, "failed")
));
assertFalse(IrisClient.shouldInvalidateForHotload(
OVERWORLD,
new IrisMessage.StudioHotload("other", 0, false, "")
));
assertFalse(IrisClient.shouldInvalidateForHotload(null, null));
}
}
@@ -5,7 +5,10 @@ import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
@@ -24,4 +27,49 @@ public class ModdedIrisLogLevelCoverageTest {
String body = source.substring(router, source.indexOf("public static void debug(", router));
assertTrue(body, body.contains("default -> info(message);"));
}
@Test
public void slf4jStyleArgumentsAndTrailingThrowableArePreserved() {
RuntimeException failure = new RuntimeException("broken");
ModdedIrisLog.RenderedLog rendered = ModdedIrisLog.render("chunk {},{} failed", 4, 9, failure);
assertEquals("chunk 4,9 failed", rendered.message());
assertEquals(failure, rendered.error());
}
@Test
public void formattedDebugThrowableUsesTheVisibleDebugRouteWhenEnabled() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded/ModdedIrisLog.java"));
int start = source.indexOf("public static void debug(String format, Object... arguments)");
int end = source.indexOf("public static void info(String message)", start);
assertTrue("formatted debug overload not found", start >= 0);
assertTrue("formatted debug overload boundary not found", end > start);
String body = source.substring(start, end);
assertTrue(body, body.contains("if (!debugEnabled())"));
assertTrue(body, body.contains("LOGGER.info(\"[Iris/DEBUG] \" + clean(rendered.message()), rendered.error())"));
}
@Test
public void moddedProductionUsesTheIrisLogFrontDoor() throws IOException {
Path root = Path.of(System.getProperty("iris.moddedCommonSources"));
try (Stream<Path> files = Files.walk(root)) {
List<Path> bypasses = files
.filter(path -> path.toString().endsWith(".java"))
.filter(path -> !path.getFileName().toString().equals("ModdedIrisLog.java"))
.filter(path -> {
try {
String source = Files.readString(path);
return source.contains("LoggerFactory.getLogger")
|| source.contains("private static final Logger LOGGER");
} catch (IOException unreadable) {
throw new IllegalStateException(unreadable);
}
})
.toList();
assertTrue(bypasses.toString(), bypasses.isEmpty());
}
}
}
@@ -91,7 +91,7 @@ public class ModdedPlatformPathsTest {
File iris = new File(temporaryFolder.getRoot(), "iris");
assertEquals(iris, platform.dataFolder());
assertEquals(new File(iris, "settings.json"), platform.dataFile("settings.json"));
assertEquals(new File(iris, "iris.json"), platform.dataFile("iris.json"));
assertEquals(new File(iris, "parity"), platform.dataFolder("parity"));
}