Merge origin/master into terrain-first hydrology

Brings master's Sentry removal, bound platform classification, Vision
entity toggle, release version and generation context binding onto the
rivers rework while keeping the hydrology system master had removed.
Hydrology files master deleted are restored from the branch, master's
non-hydrology edits are kept, and the modded adapter builds drop the
Sentry dependency with master.

Also removes the ridge_tunnel find selector: no course publishes ridge
bores any more, so it could never return a result.
This commit is contained in:
Brian Neumann-Fopiano
2026-09-02 02:52:08 -04:00
74 changed files with 869 additions and 726 deletions
+10 -12
View File
@@ -64,22 +64,20 @@ content selecting on `#minecraft:is_overworld` and friends.
**Plugin (Paper/Purpur/Leaf/Canvas/Folia/Spigot):** drop the plugin jar into `plugins/` and start **Plugin (Paper/Purpur/Leaf/Canvas/Folia/Spigot):** drop the plugin jar into `plugins/` and start
the server. First boot performs no pack download. Run `/iris download pack=overworld`, the server. First boot performs no pack download. Run `/iris download pack=overworld`,
`/iris download pack=underworld`, or `/iris download link=https://host/path/pack.zip`, waiting for `/iris download pack=underworld`, or `/iris download link=https://host/path/pack.zip`, waiting for
each download to finish before starting another. The shipping Overworld declares Towns & Towers each download to finish before starting another. The current built-in packs declare no external
26.1 and Dungeons & Taverns 5.3.0. With the default automatic ingest enabled, the first restart datapack imports. Restart after download so Minecraft loads their dimension types and biomes.
after download installs those external datapacks and leaves admission restart-required; complete Custom packs that declare `datapackImports` must complete their external-datapack installation and
the ensuing clean restart so Minecraft loads them together with the Iris dimension types and registry restart first. Plain Spigot supports ordinary managed `/iris create`, but not
biomes. If automatic ingest is disabled, run `/iris datapack ingest restart=true` instead and
complete the restart it requests. Plain Spigot supports ordinary managed `/iris create`, but not
the early-bootstrap `/iris replace` path for canonical Overworld, Nether, or End slots. the early-bootstrap `/iris replace` path for canonical Overworld, Nether, or End slots.
**Mod (Fabric/Forge/NeoForge):** drop the mod jar into `mods/` and start the server. The jar is **Mod (Fabric/Forge/NeoForge):** drop the mod jar into `mods/` and start the server. The jar is
self-contained (core, SPI, and required Fabric API modules are bundled). First boot compiles only self-contained (core, SPI, and required Fabric API modules are bundled). First boot compiles only
packs already on disk and never accesses the network. `/iris download` installs a pack atomically packs already on disk and never accesses the network. `/iris download` installs a pack atomically
without stopping the server. Before loading the shipping Overworld, manually place the exact without stopping the server. The current built-in packs declare no external datapack imports.
compatible Towns & Towers 26.1 and Dungeons & Taverns 5.3.0 archives in that save's `datapacks/` Custom packs that declare them require compatible archives in that save's `datapacks/` directory;
directory; modded `/iris datapack ingest` is an explanatory stub and does not install them. Restart modded `/iris datapack ingest` is an explanatory stub and does not install them. Restart only after
once only after the Iris pack and both external datapacks are present. Packs register their custom the Iris pack and all of its inputs are present. Packs register their custom dimension types,
dimension types, height ranges, biomes, and external structure keys during that boot; worlds created height ranges, biomes, and external structure keys during that boot; worlds created
before it run with fallback registry data. before it run with fallback registry data.
**Singleplayer (modded clients):** installed Iris packs appear as selectable World Types on the **Singleplayer (modded clients):** installed Iris packs appear as selectable World Types on the
@@ -237,7 +235,7 @@ Requirements: JDK 25 (set `JAVA_HOME` to it). The Gradle wrapper handles everyth
./gradlew buildAllToOut ./gradlew buildAllToOut
``` ```
builds every platform artifact into `dist/`: builds every platform artifact into the workspace-level `../PluginOuts/` directory:
``` ```
Iris v<version> [CraftBukkit] <mc>.jar Iris v<version> [CraftBukkit] <mc>.jar
-1
View File
@@ -21,7 +21,6 @@ dependencies {
testImplementation('org.mockito:mockito-core:5.23.0') testImplementation('org.mockito:mockito-core:5.23.0')
testImplementation(libs.paper.api) testImplementation(libs.paper.api)
testImplementation(libs.bstats) testImplementation(libs.bstats)
testImplementation(libs.sentry)
testImplementation(project(':core')) testImplementation(project(':core'))
testImplementation(volmLibCoordinate) { testImplementation(volmLibCoordinate) {
transitive = false transitive = false
@@ -423,7 +423,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
return; return;
} }
Bindings.capture(e);
boolean debug = false; boolean debug = false;
if (instance != null) { if (instance != null) {
try { try {
@@ -455,6 +454,8 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
Iris.debug("Exception Logged: " + e.getClass().getSimpleName() + ": " + C.RESET + "" + C.LIGHT_PURPLE + e.getMessage()); Iris.debug("Exception Logged: " + e.getClass().getSimpleName() + ": " + C.RESET + "" + C.LIGHT_PURPLE + e.getMessage());
} }
e.printStackTrace(System.err);
} }
public static void reportError(String context, Throwable e) { public static void reportError(String context, Throwable e) {
@@ -473,7 +474,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
} }
reportError(error); reportError(error);
error.printStackTrace(System.err);
} }
public static void dump() { public static void dump() {
@@ -606,7 +606,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
SimdSupport.install(); SimdSupport.install();
services = new KMap<>(); services = new KMap<>();
BukkitPlatform.hostHud(new HudActionBar(this), new HudBossBarLane()); BukkitPlatform.hostHud(new HudActionBar(this), new HudBossBarLane());
Bindings.setupSentry();
// Explicit, ordered service list: the previous reflective jar scan gave hash-ordered // Explicit, ordered service list: the previous reflective jar scan gave hash-ordered
// enable/disable and paid a full-jar class sweep at boot. Infrastructure first, // enable/disable and paid a full-jar class sweep at boot. Infrastructure first,
// engine/world services next, commands last. // engine/world services next, commands last.
@@ -34,7 +34,6 @@ import art.arcane.iris.engine.IrisEngineMantle;
import art.arcane.iris.engine.framework.Engine; import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.object.IrisDimension; import art.arcane.iris.engine.object.IrisDimension;
import art.arcane.iris.engine.platform.PlatformChunkGenerator; import art.arcane.iris.engine.platform.PlatformChunkGenerator;
import art.arcane.iris.util.project.context.IrisContext;
import art.arcane.iris.util.project.matter.IrisMatterContext; import art.arcane.iris.util.project.matter.IrisMatterContext;
import art.arcane.iris.util.common.director.DirectorExecutor; import art.arcane.iris.util.common.director.DirectorExecutor;
import art.arcane.volmlib.util.director.DirectorOrigin; import art.arcane.volmlib.util.director.DirectorOrigin;
@@ -79,19 +78,6 @@ public class CommandDeveloper implements DirectorExecutor {
.engineStatus(sender()); .engineStatus(sender());
} }
@Director(description = "Send a test exception to sentry", descriptionKey = "iris.director.commanddeveloper.director.send_test_exception_sentry")
public void Sentry() {
Engine engine = engine();
Exception testException = new Exception("This is a test");
if (engine == null) {
Iris.reportError(testException);
return;
}
try (IrisContext.Scope scope = IrisContext.open(engine, engine.getGenerationSessionId(), null)) {
Iris.reportError(testException);
}
}
@Director(description = "Hash generated block output of a fixed area for determinism/identity testing", descriptionKey = "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing", origin = DirectorOrigin.BOTH) @Director(description = "Hash generated block output of a fixed area for determinism/identity testing", descriptionKey = "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing", origin = DirectorOrigin.BOTH)
public void genhash( public void genhash(
@Param(description = "The world to hash", descriptionKey = "iris.director.commanddeveloper.param.world_hash", contextual = true, contextualOverride = true) @Param(description = "The world to hash", descriptionKey = "iris.director.commanddeveloper.param.world_hash", contextual = true, contextualOverride = true)
+1 -3
View File
@@ -166,8 +166,7 @@ dependencies {
libs.lru, libs.lru,
libs.caffeine, libs.caffeine,
libs.dom4j, libs.dom4j,
libs.jaxen, libs.jaxen
libs.sentry
] ]
shared.each { Object notation -> shared.each { Object notation ->
add('bundle', notation) add('bundle', notation)
@@ -275,7 +274,6 @@ tasks.named('shadowJar', ShadowJar).configure {
exclude('art/arcane/iris/platform/bukkit/**') exclude('art/arcane/iris/platform/bukkit/**')
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm') relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm')
relocate('io.sentry', 'art.arcane.iris.shadow.sentry')
// Split-package guard. A co-installed mod that ships any of these at their original coordinates // Split-package guard. A co-installed mod that ships any of these at their original coordinates
// puts two copies of the same package on one module layer, which the loaders reject at boot // puts two copies of the same package on one module layer, which the loaders reject at boot
// (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party // (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party
+1 -3
View File
@@ -165,8 +165,7 @@ dependencies {
libs.lru, libs.lru,
libs.caffeine, libs.caffeine,
libs.dom4j, libs.dom4j,
libs.jaxen, libs.jaxen
libs.sentry
] ]
shared.each { Object notation -> shared.each { Object notation ->
add('bundle', notation) add('bundle', notation)
@@ -267,7 +266,6 @@ tasks.named('shadowJar', ShadowJar).configure {
exclude('art/arcane/iris/platform/bukkit/**') exclude('art/arcane/iris/platform/bukkit/**')
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm') relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm')
relocate('io.sentry', 'art.arcane.iris.shadow.sentry')
// Split-package guard. A co-installed mod that ships any of these at their original coordinates // Split-package guard. A co-installed mod that ships any of these at their original coordinates
// puts two copies of the same package on one module layer, which the loaders reject at boot // puts two copies of the same package on one module layer, which the loaders reject at boot
// (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party // (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party
@@ -331,34 +331,113 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
if (server == null) { if (server == null) {
return null; return null;
} }
// Snapshot, never server.getAllLevels(): this runs off the server thread from data queries. ServerLevel resolved = resolveBoundLevel(server, ModdedServerLevels.levels(server));
for (ServerLevel level : ModdedServerLevels.levels(server)) { if (resolved != null) {
boundLevel = resolved;
}
return resolved;
}
ServerLevel resolveBoundLevel(MinecraftServer server, List<ServerLevel> snapshot) {
for (ServerLevel level : snapshot) {
if (level.getChunkSource().getGenerator() == this) { if (level.getChunkSource().getGenerator() == this) {
boundLevel = level;
return level; return level;
} }
} }
return null; ServerLevel overworld = server.getLevel(Level.OVERWORLD);
return overworld != null && overworld.getChunkSource().getGenerator() == this ? overworld : null;
} }
Engine engine() { Engine engine() {
requireBindingAllowed(); Engine cached = readyEngine();
Engine cached = engine; if (cached != null) {
requireCompletedShutdown(cached);
if (cached != null && !cached.isClosed()) {
return cached; return cached;
} }
ServerLevel level = boundLevel(); ServerLevel level = boundLevel();
if (level == null) { if (level == null) {
throw new IllegalStateException("Iris generator '" + dimensionKey + "' has no bound ServerLevel yet"); throw new IllegalStateException("Iris generator '" + dimensionKey + "' has no bound ServerLevel yet");
} }
return bindEngine(level); return bindGenerationLevel(level);
}
private Engine engine(ResourceKey<Level> levelKey) {
Engine cached = readyEngine();
if (cached != null) {
return cached;
}
ServerLevel level = boundLevel;
if (level == null) {
level = requirePublishedLevel(ModdedEngineBootstrap.currentServer(), levelKey);
} else {
requireGeneratorLevel(level, levelKey);
}
return bindGenerationLevel(level);
}
private Engine engine(ServerLevel generationLevel) {
Engine cached = readyEngine();
if (cached != null) {
return cached;
}
ServerLevel level = boundLevel == null ? generationLevel : boundLevel;
requireGeneratorLevel(level, generationLevel.dimension());
return bindGenerationLevel(level);
}
private Engine readyEngine() {
requireBindingAllowed();
Engine cached = engine;
requireCompletedShutdown(cached);
if (cached != null && !cached.isClosed()) {
return cached;
}
return null;
}
private Engine bindGenerationLevel(ServerLevel level) {
bindLevel(level);
Engine bound = readyEngine();
if (bound == null) {
throw new IllegalStateException("Iris generator '" + dimensionKey
+ "' completed generation binding without a ready engine");
}
return bound;
}
ServerLevel requirePublishedLevel(MinecraftServer server, ResourceKey<Level> levelKey) {
if (server == null) {
throw new IllegalStateException("Iris generator '" + dimensionKey
+ "' cannot resolve level '" + levelKey.identifier() + "': server is unavailable");
}
ServerLevel level = server.getLevel(levelKey);
if (level == null) {
throw new IllegalStateException("Iris generator '" + dimensionKey
+ "' has no published ServerLevel for '" + levelKey.identifier() + "'");
}
requireGeneratorLevel(level, levelKey);
return level;
}
private void requireGeneratorLevel(ServerLevel level, ResourceKey<Level> levelKey) {
if (!levelKey.equals(level.dimension())) {
throw new IllegalStateException("Iris generator '" + dimensionKey + "' resolved level '"
+ level.dimension().identifier() + "' while binding '" + levelKey.identifier() + "'");
}
ChunkGenerator publishedGenerator = level.getChunkSource().getGenerator();
if (publishedGenerator != this) {
throw new IllegalStateException("Published ServerLevel '" + levelKey.identifier()
+ "' does not use Iris generator '" + dimensionKey + "'");
}
} }
synchronized void bindLevel(ServerLevel level) { synchronized void bindLevel(ServerLevel level) {
if (level.getChunkSource().getGenerator() != this) { if (level.getChunkSource().getGenerator() != this) {
throw new IllegalArgumentException("ServerLevel does not use Iris generator '" + dimensionKey + "'"); throw new IllegalArgumentException("ServerLevel does not use Iris generator '" + dimensionKey + "'");
} }
Engine current = engineIfBound();
if (boundLevel == level && current != null && current.getComplex() != null) {
return;
}
requireCompletedShutdown(engine); requireCompletedShutdown(engine);
unloading = false; unloading = false;
Engine bound = bindEngine(level); Engine bound = bindEngine(level);
@@ -853,7 +932,6 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
@Override @Override
public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) { public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) {
Engine current = engine(); Engine current = engine();
// Self-heal for an engine bound through a data-query path instead of bindLevel; a no-op once prepared.
importedFeatures.prepare(current); importedFeatures.prepare(current);
try (GenerationSessionLease lease = requireGenerationLease(current, "modded_biome_decoration"); try (GenerationSessionLease lease = requireGenerationLease(current, "modded_biome_decoration");
IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) { IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) {
@@ -867,7 +945,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
@Override @Override
public void createStructures(RegistryAccess registryAccess, ChunkGeneratorStructureState structureState, StructureManager structureManager, ChunkAccess chunk, StructureTemplateManager templateManager, ResourceKey<Level> levelKey) { public void createStructures(RegistryAccess registryAccess, ChunkGeneratorStructureState structureState, StructureManager structureManager, ChunkAccess chunk, StructureTemplateManager templateManager, ResourceKey<Level> levelKey) {
Engine current = engine(); Engine current = engine(levelKey);
try (GenerationSessionLease lease = requireGenerationLease(current, "modded_create_structures"); try (GenerationSessionLease lease = requireGenerationLease(current, "modded_create_structures");
IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) { IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) {
Map<Structure, StructureStart> previousStarts = new HashMap<>(chunk.getAllStarts()); Map<Structure, StructureStart> previousStarts = new HashMap<>(chunk.getAllStarts());
@@ -891,7 +969,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
@Override @Override
public void createReferences(WorldGenLevel level, StructureManager structureManager, ChunkAccess chunk) { public void createReferences(WorldGenLevel level, StructureManager structureManager, ChunkAccess chunk) {
Engine current = engine(); Engine current = engine(level.getLevel());
try (GenerationSessionLease lease = requireGenerationLease(current, "modded_create_references"); try (GenerationSessionLease lease = requireGenerationLease(current, "modded_create_references");
IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) { IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) {
NativeStructureReferenceRepair.createReferences( NativeStructureReferenceRepair.createReferences(
@@ -590,6 +590,7 @@ public final class ModdedDimensionManager {
boolean loadEventStarted = false; boolean loadEventStarted = false;
try { try {
serverAccess.initializeLevelData(server, level);
generator.bindLevel(level); generator.bindLevel(level);
Handle handle = new Handle(dimensionId, pack, packDimensionKey, seed, level, generator); Handle handle = new Handle(dimensionId, pack, packDimensionKey, seed, level, generator);
ServerLevel previous = serverAccess.putLevelIfAbsent(server, key, level); ServerLevel previous = serverAccess.putLevelIfAbsent(server, key, level);
@@ -113,7 +113,6 @@ public final class ModdedEngineBootstrap {
bindWorldGenerators(server); bindWorldGenerators(server);
services().enableAll(); services().enableAll();
ModdedProtocolHandler.start(server); ModdedProtocolHandler.start(server);
ModdedSentry.start(loader());
} }
private static void bindWorldGenerators(MinecraftServer server) { private static void bindWorldGenerators(MinecraftServer server) {
@@ -194,7 +193,6 @@ public final class ModdedEngineBootstrap {
MultiBurst.burst.close(); MultiBurst.burst.close();
MultiBurst.ioBurst.close(); MultiBurst.ioBurst.close();
}); });
failure = runStopStage(failure, "sentry", ModdedSentry::flush);
failure = runStopStage(failure, "startup state", ModdedStartup::reset); failure = runStopStage(failure, "startup state", ModdedStartup::reset);
failure = runStopStage(failure, "server state", () -> { failure = runStopStage(failure, "server state", () -> {
currentServer = null; currentServer = null;
@@ -47,7 +47,6 @@ public final class ModdedPlatform implements IrisPlatform {
private static final ConcurrentHashMap<String, ErrorThrottle> ERROR_THROTTLES = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<String, ErrorThrottle> ERROR_THROTTLES = new ConcurrentHashMap<>();
private static volatile Consumer<Throwable> ERROR_SINK = null; private static volatile Consumer<Throwable> ERROR_SINK = null;
private static volatile Consumer<Throwable> CAPTURE_SINK = null;
private final ModdedLoader loader; private final ModdedLoader loader;
private final ModdedRegistries registries; private final ModdedRegistries registries;
@@ -67,10 +66,6 @@ public final class ModdedPlatform implements IrisPlatform {
ERROR_SINK = sink; ERROR_SINK = sink;
} }
public static void captureSink(Consumer<Throwable> sink) {
CAPTURE_SINK = sink;
}
public MinecraftServer server() { public MinecraftServer server() {
return ModdedEngineBootstrap.currentServer(); return ModdedEngineBootstrap.currentServer();
} }
@@ -230,9 +225,8 @@ public final class ModdedPlatform implements IrisPlatform {
} }
/** /**
* Throttled per exception signature. A single broken pack rule can fail on every generated chunk, and this * Throttled per exception signature. A single broken pack rule can fail on every generated chunk, so each
* feeds Sentry, so each distinct signature reports its first few occurrences and then only a periodic * distinct signature reports its first few occurrences and then only a periodic suppressed-count summary.
* suppressed-count summary.
*/ */
@Override @Override
public void reportError(Throwable error) { public void reportError(Throwable error) {
@@ -261,14 +255,6 @@ public final class ModdedPlatform implements IrisPlatform {
return; return;
} }
ModdedIrisLog.error(message, error); ModdedIrisLog.error(message, error);
Consumer<Throwable> capture = CAPTURE_SINK;
if (capture != null) {
try {
capture.accept(error);
} catch (Throwable captureFailure) {
ModdedIrisLog.error("Iris error-reporting sink failed", captureFailure);
}
}
} }
static void resetErrorThrottles() { static void resetErrorThrottles() {
@@ -1,81 +0,0 @@
/*
* Iris is a World Generator for Minecraft Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.modded;
import art.arcane.iris.BuildConstants;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.volmlib.util.json.JSONException;
import com.google.gson.JsonSyntaxException;
import io.sentry.Sentry;
import java.util.concurrent.atomic.AtomicBoolean;
public final class ModdedSentry {
private static final String DSN = "http://4cdbb9ac953306529947f4ca1e8e6b26@sentry.volmit.com:8080/2";
private static final long FLUSH_TIMEOUT_MS = 2000L;
private static final AtomicBoolean STARTED = new AtomicBoolean(false);
private ModdedSentry() {
}
public static void start(ModdedLoader loader) {
IrisSettings.IrisSettingsSentry settings = IrisSettings.get().getSentry();
if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) {
return;
}
if (!STARTED.compareAndSet(false, true)) {
return;
}
IrisLogging.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings.");
Sentry.init(options -> {
options.setDsn(DSN);
if (settings.debug) {
options.setDebug(true);
}
options.setAttachServerName(false);
options.setEnableUncaughtExceptionHandler(false);
options.setRelease(loader.modVersion());
options.setEnvironment(BuildConstants.ENVIRONMENT);
options.setBeforeSend((event, hint) -> suppress(event.getThrowable()) ? null : event);
});
Sentry.configureScope(scope -> {
scope.setTag("server", loader.platformName());
scope.setTag("server.mc", loader.minecraftVersion());
scope.setTag("iris.loader", loader.platformName());
scope.setTag("iris.commit", BuildConstants.COMMIT);
});
ModdedPlatform.captureSink(Sentry::captureException);
}
public static void flush() {
if (Sentry.isEnabled()) {
Sentry.flush(FLUSH_TIMEOUT_MS);
Sentry.close();
}
ModdedPlatform.captureSink(null);
STARTED.set(false);
}
private static boolean suppress(Throwable error) {
return (error instanceof IllegalStateException state && "zip file closed".equals(state.getMessage()))
|| error instanceof JSONException
|| error instanceof JsonSyntaxException;
}
}
@@ -31,6 +31,8 @@ public interface ModdedServerAccess {
LevelStorageSource.LevelStorageAccess levelStorage(MinecraftServer server); LevelStorageSource.LevelStorageAccess levelStorage(MinecraftServer server);
void initializeLevelData(MinecraftServer server, ServerLevel level);
ServerLevel putLevel(MinecraftServer server, ResourceKey<Level> key, ServerLevel level); ServerLevel putLevel(MinecraftServer server, ResourceKey<Level> key, ServerLevel level);
ServerLevel putLevelIfAbsent(MinecraftServer server, ResourceKey<Level> key, ServerLevel level); ServerLevel putLevelIfAbsent(MinecraftServer server, ResourceKey<Level> key, ServerLevel level);
@@ -23,7 +23,11 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.level.storage.WorldData;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ConcurrentModificationException; import java.util.ConcurrentModificationException;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@@ -34,6 +38,18 @@ import java.util.function.Consumer;
public final class ModdedServerLevels implements ModdedServerAccess { public final class ModdedServerLevels implements ModdedServerAccess {
private static final int CAPTURE_ATTEMPTS = 16; private static final int CAPTURE_ATTEMPTS = 16;
private static final ClassValue<HostLevelPublication> HOST_LEVEL_PUBLICATIONS = new ClassValue<>() {
@Override
protected HostLevelPublication computeValue(Class<?> type) {
return HostLevelPublication.detect(type, ServerLevel.class);
}
};
private static final ClassValue<HostLevelDataAttachment> HOST_LEVEL_DATA_ATTACHMENTS = new ClassValue<>() {
@Override
protected HostLevelDataAttachment computeValue(Class<?> type) {
return HostLevelDataAttachment.detect(type, PrimaryLevelData.class, ResourceKey.class);
}
};
private static volatile Snapshot snapshot; private static volatile Snapshot snapshot;
private final Consumer<MinecraftServer> levelCacheInvalidator; private final Consumer<MinecraftServer> levelCacheInvalidator;
@@ -43,8 +59,8 @@ public final class ModdedServerLevels implements ModdedServerAccess {
} }
/** /**
* Immutable view of the loaded levels. {@code server.levels} is a plain map mutated on the server * Immutable view of the loaded levels. {@code server.levels} is loader-owned and published on the
* thread, so every off-server-thread reader must iterate this snapshot instead of * server thread, so every off-server-thread reader must iterate this snapshot instead of
* {@code server.getAllLevels()} to avoid ConcurrentModificationException. * {@code server.getAllLevels()} to avoid ConcurrentModificationException.
*/ */
public static List<ServerLevel> levels(MinecraftServer server) { public static List<ServerLevel> levels(MinecraftServer server) {
@@ -137,8 +153,32 @@ public final class ModdedServerLevels implements ModdedServerAccess {
return server.storageSource; return server.storageSource;
} }
@Override
public void initializeLevelData(MinecraftServer server, ServerLevel level) {
Object levelData = level.getLevelData();
HostLevelDataAttachment attachment = HOST_LEVEL_DATA_ATTACHMENTS.get(levelData.getClass());
if (!attachment.supported()) {
return;
}
WorldData worldData = server.getWorldData();
if (!(worldData instanceof PrimaryLevelData rootData)) {
throw new IllegalStateException("Host level data attachment requires PrimaryLevelData, found "
+ worldData.getClass().getName());
}
attachment.attach(levelData, rootData, level.dimension());
}
@Override @Override
public ServerLevel putLevel(MinecraftServer server, ResourceKey<Level> key, ServerLevel level) { public ServerLevel putLevel(MinecraftServer server, ResourceKey<Level> key, ServerLevel level) {
HostLevelPublication hostPublication = HOST_LEVEL_PUBLICATIONS.get(server.getClass());
if (hostPublication.supported()) {
ServerLevel previous = server.levels.get(key);
if (previous != level) {
hostPublication.add(server, level);
capture(server);
}
return previous;
}
ServerLevel previous = server.levels.put(key, level); ServerLevel previous = server.levels.put(key, level);
if (previous != level) { if (previous != level) {
capture(server); capture(server);
@@ -149,6 +189,15 @@ public final class ModdedServerLevels implements ModdedServerAccess {
@Override @Override
public ServerLevel putLevelIfAbsent(MinecraftServer server, ResourceKey<Level> key, ServerLevel level) { public ServerLevel putLevelIfAbsent(MinecraftServer server, ResourceKey<Level> key, ServerLevel level) {
HostLevelPublication hostPublication = HOST_LEVEL_PUBLICATIONS.get(server.getClass());
if (hostPublication.supported()) {
ServerLevel previous = server.levels.get(key);
if (previous == null) {
hostPublication.add(server, level);
capture(server);
}
return previous;
}
ServerLevel previous = server.levels.putIfAbsent(key, level); ServerLevel previous = server.levels.putIfAbsent(key, level);
if (previous == null) { if (previous == null) {
capture(server); capture(server);
@@ -159,6 +208,15 @@ public final class ModdedServerLevels implements ModdedServerAccess {
@Override @Override
public ServerLevel removeLevel(MinecraftServer server, ResourceKey<Level> key) { public ServerLevel removeLevel(MinecraftServer server, ResourceKey<Level> key) {
HostLevelPublication hostPublication = HOST_LEVEL_PUBLICATIONS.get(server.getClass());
if (hostPublication.supported()) {
ServerLevel removed = server.levels.get(key);
if (removed != null) {
hostPublication.remove(server, removed);
capture(server);
}
return removed;
}
ServerLevel removed = server.levels.remove(key); ServerLevel removed = server.levels.remove(key);
if (removed != null) { if (removed != null) {
capture(server); capture(server);
@@ -175,4 +233,94 @@ public final class ModdedServerLevels implements ModdedServerAccess {
private record Snapshot(MinecraftServer server, List<ServerLevel> levels, private record Snapshot(MinecraftServer server, List<ServerLevel> levels,
Map<ResourceKey<Level>, ServerLevel> byKey) { Map<ResourceKey<Level>, ServerLevel> byKey) {
} }
static final class HostLevelPublication {
private final Method addLevel;
private final Method removeLevel;
private HostLevelPublication(Method addLevel, Method removeLevel) {
this.addLevel = addLevel;
this.removeLevel = removeLevel;
}
static HostLevelPublication detect(Class<?> serverType, Class<?> levelType) {
try {
Method addLevel = serverType.getMethod("addLevel", levelType);
Method removeLevel = serverType.getMethod("removeLevel", levelType);
return new HostLevelPublication(addLevel, removeLevel);
} catch (NoSuchMethodException e) {
return new HostLevelPublication(null, null);
}
}
boolean supported() {
return addLevel != null && removeLevel != null;
}
void add(Object server, Object level) {
invoke(addLevel, server, level);
}
void remove(Object server, Object level) {
invoke(removeLevel, server, level);
}
private void invoke(Method method, Object server, Object level) {
try {
method.invoke(server, level);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Iris cannot access host level publication method "
+ method.getName(), e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException runtimeException) {
throw runtimeException;
}
if (cause instanceof Error fatalError) {
throw fatalError;
}
throw new IllegalStateException("Host level publication method " + method.getName()
+ " failed", cause);
}
}
}
static final class HostLevelDataAttachment {
private final Method attach;
private HostLevelDataAttachment(Method attach) {
this.attach = attach;
}
static HostLevelDataAttachment detect(Class<?> levelDataType, Class<?> rootDataType,
Class<?> dimensionKeyType) {
try {
return new HostLevelDataAttachment(levelDataType.getMethod(
"attach", rootDataType, dimensionKeyType));
} catch (NoSuchMethodException e) {
return new HostLevelDataAttachment(null);
}
}
boolean supported() {
return attach != null;
}
void attach(Object levelData, Object rootData, Object dimensionKey) {
try {
attach.invoke(levelData, rootData, dimensionKey);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Iris cannot access host level data attachment method", e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException runtimeException) {
throw runtimeException;
}
if (cause instanceof Error fatalError) {
throw fatalError;
}
throw new IllegalStateException("Host level data attachment failed", cause);
}
}
}
} }
@@ -87,7 +87,7 @@ final class ModdedCommandHelp {
Entry.group("datapack", ModdedHelpMessages.GROUP_DATAPACK_WORLD_DATAPACK_INSTALL_AND_STATUS_HELPERS, "datapacks", "dp"), Entry.group("datapack", ModdedHelpMessages.GROUP_DATAPACK_WORLD_DATAPACK_INSTALL_AND_STATUS_HELPERS, "datapacks", "dp"),
Entry.group("structure", ModdedHelpMessages.GROUP_STRUCTURE_IRIS_STRUCTURE_INDEX_INFO_AND_PLACEMENT_TOOLS, "struct", "str"), Entry.group("structure", ModdedHelpMessages.GROUP_STRUCTURE_IRIS_STRUCTURE_INDEX_INFO_AND_PLACEMENT_TOOLS, "struct", "str"),
Entry.command("goldenhash", "[radius] [threads] [capture|verify]", ModdedHelpMessages.COMMAND_GOLDENHASH_GENERATE_DETERMINISTIC_BLOCK_HASHES_FOR_PARITY_TESTING, "gold"), Entry.command("goldenhash", "[radius] [threads] [capture|verify]", ModdedHelpMessages.COMMAND_GOLDENHASH_GENERATE_DETERMINISTIC_BLOCK_HASHES_FOR_PARITY_TESTING, "gold"),
Entry.group("developer", ModdedHelpMessages.GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_SENTRY_TEST_NETWORK_INTERFACES_REGION_FILE_SCAN, "dev") Entry.group("developer", ModdedHelpMessages.GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_NETWORK_INTERFACES_REGION_FILE_SCAN, "dev")
)); ));
SECTIONS.put("what", List.of( SECTIONS.put("what", List.of(
Entry.command("here", "", ModdedHelpMessages.COMMAND_WHAT_HERE_INSPECT_CURRENT_IRIS_CONTEXT), Entry.command("here", "", ModdedHelpMessages.COMMAND_WHAT_HERE_INSPECT_CURRENT_IRIS_CONTEXT),
@@ -197,7 +197,6 @@ final class ModdedCommandHelp {
SECTIONS.put("struct", SECTIONS.get("structure")); SECTIONS.put("struct", SECTIONS.get("structure"));
SECTIONS.put("str", SECTIONS.get("structure")); SECTIONS.put("str", SECTIONS.get("structure"));
SECTIONS.put("developer", List.of( SECTIONS.put("developer", List.of(
Entry.command("sentry", "", ModdedHelpMessages.COMMAND_SENTRY_SEND_A_TEST_EXCEPTION_TO_THE_IRIS_ERROR_REPORTER),
Entry.command("network", "", ModdedHelpMessages.COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES, "ip") Entry.command("network", "", ModdedHelpMessages.COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES, "ip")
)); ));
SECTIONS.put("dev", SECTIONS.get("developer")); SECTIONS.put("dev", SECTIONS.get("developer"));
@@ -19,7 +19,6 @@
package art.arcane.iris.modded.command; package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog; import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.spi.IrisPlatforms;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
@@ -44,20 +43,12 @@ final class ModdedDeveloperCommands {
static LiteralArgumentBuilder<CommandSourceStack> tree(String name) { static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
return Commands.literal(name).requires(GATE) return Commands.literal(name).requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "developer")) .executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "developer"))
.then(Commands.literal("sentry")
.executes((CommandContext<CommandSourceStack> context) -> sentry(context.getSource())))
.then(Commands.literal("network") .then(Commands.literal("network")
.executes((CommandContext<CommandSourceStack> context) -> network(context.getSource()))) .executes((CommandContext<CommandSourceStack> context) -> network(context.getSource())))
.then(Commands.literal("ip") .then(Commands.literal("ip")
.executes((CommandContext<CommandSourceStack> context) -> network(context.getSource()))); .executes((CommandContext<CommandSourceStack> context) -> network(context.getSource())));
} }
private static int sentry(CommandSourceStack source) {
IrisPlatforms.get().reportError(new Exception("This is an Iris Sentry test exception"));
ModdedCommandFeedback.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DEVELOPER_COMMANDS_DISPATCHED_TEST_EXCEPTION_IRIS_ERROR_REPORTER_SENTRY_IF_ENABLED));
return 1;
}
private static int network(CommandSourceStack source) { private static int network(CommandSourceStack source) {
try { try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
@@ -0,0 +1,150 @@
package art.arcane.iris.modded;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ModdedGenerationBootstrapBindingTest {
private static final String SOURCE_ROOT_PROPERTY = "iris.moddedCommonSources";
@Test
public void publishedLevelRequiresCurrentGeneratorIdentity() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
MinecraftServer server = mock(MinecraftServer.class);
ServerLevel level = mock(ServerLevel.class);
ServerChunkCache chunkSource = mock(ServerChunkCache.class);
when(server.getLevel(Level.OVERWORLD)).thenReturn(level);
when(level.dimension()).thenReturn(Level.OVERWORLD);
when(level.getChunkSource()).thenReturn(chunkSource);
when(chunkSource.getGenerator()).thenReturn(generator);
assertSame(level, generator.requirePublishedLevel(server, Level.OVERWORLD));
ChunkGenerator otherGenerator = mock(ChunkGenerator.class);
when(chunkSource.getGenerator()).thenReturn(otherGenerator);
IllegalStateException mismatch = assertThrows(IllegalStateException.class,
() -> generator.requirePublishedLevel(server, Level.OVERWORLD));
assertTrue(mismatch.getMessage().contains("does not use Iris generator"));
}
@Test
public void publishedLevelRejectsMissingServerAndWorld() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
IllegalStateException missingServer = assertThrows(IllegalStateException.class,
() -> generator.requirePublishedLevel(null, Level.OVERWORLD));
assertTrue(missingServer.getMessage().contains("server is unavailable"));
MinecraftServer server = mock(MinecraftServer.class);
IllegalStateException missingWorld = assertThrows(IllegalStateException.class,
() -> generator.requirePublishedLevel(server, Level.OVERWORLD));
assertTrue(missingWorld.getMessage().contains("no published ServerLevel"));
}
@Test
public void staleSnapshotResolvesOnlyCanonicalOverworldOwnedByGenerator() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
MinecraftServer server = mock(MinecraftServer.class);
ServerLevel overworld = mock(ServerLevel.class);
ServerChunkCache chunkSource = mock(ServerChunkCache.class);
when(server.getLevel(Level.OVERWORLD)).thenReturn(overworld);
when(overworld.getChunkSource()).thenReturn(chunkSource);
when(chunkSource.getGenerator()).thenReturn(generator);
assertSame(overworld, generator.resolveBoundLevel(server, List.of()));
ChunkGenerator otherGenerator = mock(ChunkGenerator.class);
when(chunkSource.getGenerator()).thenReturn(otherGenerator);
assertNull(generator.resolveBoundLevel(server, List.of()));
verify(server, never()).getLevel(Level.NETHER);
}
@Test
public void dynamicLevelStillResolvesFromSnapshotWithoutCanonicalLookup() {
IrisModdedChunkGenerator generator = mock(IrisModdedChunkGenerator.class, CALLS_REAL_METHODS);
MinecraftServer server = mock(MinecraftServer.class);
ServerLevel dynamicLevel = mock(ServerLevel.class);
ServerChunkCache chunkSource = mock(ServerChunkCache.class);
when(dynamicLevel.getChunkSource()).thenReturn(chunkSource);
when(chunkSource.getGenerator()).thenReturn(generator);
assertSame(dynamicLevel, generator.resolveBoundLevel(server, List.of(dynamicLevel)));
verify(server, never()).getLevel(Level.OVERWORLD);
}
@Test
public void firstGenerationStagesProvideAuthoritativeLevelContext() throws IOException {
String source = source("IrisModdedChunkGenerator.java");
String structures = method(source, "public void createStructures(");
String references = method(source, "public void createReferences(");
assertTrue(structures.contains("Engine current = engine(levelKey);"));
assertTrue(references.contains("Engine current = engine(level.getLevel());"));
String publishedBinding = method(source, "private Engine engine(ResourceKey<Level> levelKey)");
assertTrue(publishedBinding.contains("requirePublishedLevel(ModdedEngineBootstrap.currentServer(), levelKey)"));
assertTrue(publishedBinding.contains("return bindGenerationLevel(level);"));
assertFalse(publishedBinding.contains("ModdedServerLevels.level("));
String fullBinding = method(source, "private Engine bindGenerationLevel(ServerLevel level)");
assertTrue(fullBinding.contains("bindLevel(level);"));
assertTrue(fullBinding.contains("Engine bound = readyEngine();"));
String genericBinding = method(source, "Engine engine()");
assertTrue(genericBinding.contains("return bindGenerationLevel(level);"));
}
@Test
public void constructorMixinIsNotPartOfGenerationBootstrap() throws IOException {
String sourceRoot = System.getProperty(SOURCE_ROOT_PROPERTY);
assertTrue(sourceRoot != null && !sourceRoot.isBlank());
Path root = Path.of(sourceRoot);
assertFalse(Files.exists(root.resolve(Path.of("art", "arcane", "iris", "modded", "mixin",
"ServerLevelBindingMixin.java"))));
String mixinConfig = Files.readString(root.getParent().resolve("resources/irisworldgen.entity.mixins.json"));
assertFalse(mixinConfig.contains("ServerLevelBindingMixin"));
}
private String source(String fileName) throws IOException {
String sourceRoot = System.getProperty(SOURCE_ROOT_PROPERTY);
assertTrue(sourceRoot != null && !sourceRoot.isBlank());
return Files.readString(Path.of(sourceRoot, "art", "arcane", "iris", "modded", fileName));
}
private String method(String source, String signature) {
int start = source.indexOf(signature);
assertTrue(start >= 0);
int body = source.indexOf('{', start);
assertTrue(body >= 0);
int depth = 0;
for (int index = body; index < source.length(); index++) {
char token = source.charAt(index);
if (token == '{') {
depth++;
} else if (token == '}') {
depth--;
if (depth == 0) {
return source.substring(start, index + 1);
}
}
}
throw new IllegalArgumentException("Unclosed source contract method: " + signature);
}
}
@@ -0,0 +1,94 @@
package art.arcane.iris.modded;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class ModdedLevelDataAttachmentTest {
@Test
public void detectsAndInvokesHostLevelDataAttachment() {
ModdedServerLevels.HostLevelDataAttachment attachment =
ModdedServerLevels.HostLevelDataAttachment.detect(
AttachedLevelData.class, RootData.class, DimensionKey.class);
AttachedLevelData levelData = new AttachedLevelData();
RootData rootData = new RootData();
DimensionKey dimensionKey = new DimensionKey();
assertTrue(attachment.supported());
attachment.attach(levelData, rootData, dimensionKey);
assertSame(rootData, levelData.rootData);
assertSame(dimensionKey, levelData.dimensionKey);
}
@Test
public void ignoresLevelDataWithoutAttachmentCapability() {
ModdedServerLevels.HostLevelDataAttachment attachment =
ModdedServerLevels.HostLevelDataAttachment.detect(
StandardLevelData.class, RootData.class, DimensionKey.class);
assertFalse(attachment.supported());
}
@Test
public void propagatesHostAttachmentFailureWithoutReflectionWrapper() {
ModdedServerLevels.HostLevelDataAttachment attachment =
ModdedServerLevels.HostLevelDataAttachment.detect(
FailingLevelData.class, RootData.class, DimensionKey.class);
IllegalStateException failure = assertThrows(IllegalStateException.class,
() -> attachment.attach(new FailingLevelData(), new RootData(), new DimensionKey()));
assertNull(failure.getCause());
}
@Test
public void initializesLevelDataBeforeBindingAndPublication() throws IOException {
String source = Files.readString(sourcePath("ModdedDimensionManager.java"));
int construction = source.indexOf("ServerLevel level = new ServerLevel(");
int initialization = source.indexOf("serverAccess.initializeLevelData(server, level);", construction);
int binding = source.indexOf("generator.bindLevel(level);", initialization);
int publication = source.indexOf("serverAccess.putLevelIfAbsent(server, key, level);", binding);
assertTrue(construction >= 0);
assertTrue(initialization > construction);
assertTrue(binding > initialization);
assertTrue(publication > binding);
}
private static Path sourcePath(String fileName) {
return Path.of(System.getProperty("iris.moddedCommonSources"),
"art/arcane/iris/modded", fileName);
}
public static final class AttachedLevelData {
private RootData rootData;
private DimensionKey dimensionKey;
public void attach(RootData rootData, DimensionKey dimensionKey) {
this.rootData = rootData;
this.dimensionKey = dimensionKey;
}
}
public static final class FailingLevelData {
public void attach(RootData rootData, DimensionKey dimensionKey) {
throw new IllegalStateException("attachment failed");
}
}
public static final class StandardLevelData {
}
public static final class RootData {
}
public static final class DimensionKey {
}
}
@@ -0,0 +1,73 @@
package art.arcane.iris.modded;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class ModdedServerLevelsTest {
@Test
public void detectsAndInvokesHostLevelPublicationPair() {
ModdedServerLevels.HostLevelPublication publication =
ModdedServerLevels.HostLevelPublication.detect(PublishingServer.class, PublishedLevel.class);
PublishingServer server = new PublishingServer();
PublishedLevel level = new PublishedLevel();
assertTrue(publication.supported());
publication.add(server, level);
assertSame(level, server.added);
publication.remove(server, level);
assertSame(level, server.removed);
}
@Test
public void rejectsPartialHostLevelPublicationCapability() {
ModdedServerLevels.HostLevelPublication publication =
ModdedServerLevels.HostLevelPublication.detect(AddOnlyServer.class, PublishedLevel.class);
assertFalse(publication.supported());
}
@Test
public void propagatesHostPublicationFailureWithoutReflectionWrapper() {
ModdedServerLevels.HostLevelPublication publication =
ModdedServerLevels.HostLevelPublication.detect(FailingServer.class, PublishedLevel.class);
IllegalStateException failure = assertThrows(IllegalStateException.class,
() -> publication.add(new FailingServer(), new PublishedLevel()));
assertNull(failure.getCause());
}
public static final class PublishingServer {
private PublishedLevel added;
private PublishedLevel removed;
public void addLevel(PublishedLevel level) {
added = level;
}
public void removeLevel(PublishedLevel level) {
removed = level;
}
}
public static final class AddOnlyServer {
public void addLevel(PublishedLevel level) {
}
}
public static final class FailingServer {
public void addLevel(PublishedLevel level) {
throw new IllegalStateException("publication failed");
}
public void removeLevel(PublishedLevel level) {
}
}
public static final class PublishedLevel {
}
}
+1 -3
View File
@@ -135,8 +135,7 @@ dependencies {
libs.lru, libs.lru,
libs.caffeine, libs.caffeine,
libs.dom4j, libs.dom4j,
libs.jaxen, libs.jaxen
libs.sentry
] ]
shared.each { Object notation -> shared.each { Object notation ->
add('bundle', notation) add('bundle', notation)
@@ -243,7 +242,6 @@ tasks.named('shadowJar', ShadowJar).configure {
exclude('art/arcane/iris/platform/bukkit/**') exclude('art/arcane/iris/platform/bukkit/**')
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm') relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm')
relocate('io.sentry', 'art.arcane.iris.shadow.sentry')
// Split-package guard. A co-installed mod that ships any of these at their original coordinates // Split-package guard. A co-installed mod that ships any of these at their original coordinates
// puts two copies of the same package on one module layer, which the loaders reject at boot // puts two copies of the same package on one module layer, which the loaders reject at boot
// (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party // (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party
+15 -50
View File
@@ -1,4 +1,3 @@
import de.undercouch.gradle.tasks.download.Download
import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.compile.JavaCompile
@@ -39,7 +38,6 @@ buildscript {
plugins { plugins {
id 'java' id 'java'
id 'java-library' id 'java-library'
alias(libs.plugins.download)
} }
group = 'art.arcane' group = 'art.arcane'
@@ -75,6 +73,7 @@ String bukkitArtifactName = irisArtifactName('CraftBukkit', bukkitMinecraftRange
String fabricArtifactName = irisArtifactName('Fabric', "${minecraftVersion}+${loaderDisplayVersion(fabricLoaderVersion)}") String fabricArtifactName = irisArtifactName('Fabric', "${minecraftVersion}+${loaderDisplayVersion(fabricLoaderVersion)}")
String forgeArtifactName = irisArtifactName('Forge', "${minecraftVersion}+${loaderDisplayVersion(forgeVersion)}") String forgeArtifactName = irisArtifactName('Forge', "${minecraftVersion}+${loaderDisplayVersion(forgeVersion)}")
String neoForgeArtifactName = irisArtifactName('NeoForge', "${minecraftVersion}+${loaderDisplayVersion(neoForgeVersion)}") String neoForgeArtifactName = irisArtifactName('NeoForge', "${minecraftVersion}+${loaderDisplayVersion(neoForgeVersion)}")
File pluginOutDirectory = layout.projectDirectory.dir('../PluginOuts').asFile
long maximumBukkitArtifactBytes = 7_000_000L long maximumBukkitArtifactBytes = 7_000_000L
apply plugin: ApiGenerator apply plugin: ApiGenerator
@@ -281,12 +280,12 @@ tasks.register('buildBukkit', Copy) {
group = 'iris' group = 'iris'
dependsOn('jar') dependsOn('jar')
from(layout.buildDirectory.file("libs/${bukkitArtifactName}")) from(layout.buildDirectory.file("libs/${bukkitArtifactName}"))
into(layout.projectDirectory.dir('dist')) into(pluginOutDirectory)
doFirst { doFirst {
delete(fileTree(layout.projectDirectory.dir('dist')) { delete(fileTree(pluginOutDirectory) {
include('Iris v* [CraftBukkit] *.jar') include('Iris v* [CraftBukkit] *.jar')
}) })
delete(layout.projectDirectory.file("dist/Iris-${project.version}+mc${minecraftVersion}.jar")) delete(new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}.jar"))
} }
} }
@@ -384,12 +383,12 @@ tasks.register('buildFabric', Copy) {
group = 'iris' group = 'iris'
dependsOn('fabricJar') dependsOn('fabricJar')
from(layout.projectDirectory.file("adapters/fabric/build/libs/${fabricArtifactName}")) from(layout.projectDirectory.file("adapters/fabric/build/libs/${fabricArtifactName}"))
into(layout.projectDirectory.dir('dist')) into(pluginOutDirectory)
doFirst { doFirst {
delete(fileTree(layout.projectDirectory.dir('dist')) { delete(fileTree(pluginOutDirectory) {
include('Iris v* [Fabric] *.jar') include('Iris v* [Fabric] *.jar')
}) })
delete(layout.projectDirectory.file("dist/Iris-${project.version}+mc${minecraftVersion}-fabric.jar")) delete(new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}-fabric.jar"))
} }
} }
@@ -422,12 +421,12 @@ tasks.register('buildForge', Copy) {
group = 'iris' group = 'iris'
dependsOn('forgeJar') dependsOn('forgeJar')
from(layout.projectDirectory.file("adapters/forge/build/libs/${forgeArtifactName}")) from(layout.projectDirectory.file("adapters/forge/build/libs/${forgeArtifactName}"))
into(layout.projectDirectory.dir('dist')) into(pluginOutDirectory)
doFirst { doFirst {
delete(fileTree(layout.projectDirectory.dir('dist')) { delete(fileTree(pluginOutDirectory) {
include('Iris v* [Forge] *.jar') include('Iris v* [Forge] *.jar')
}) })
delete(layout.projectDirectory.file("dist/Iris-${project.version}+mc${minecraftVersion}-forge.jar")) delete(new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}-forge.jar"))
} }
} }
@@ -460,12 +459,12 @@ tasks.register('buildNeoforge', Copy) {
group = 'iris' group = 'iris'
dependsOn('neoforgeJar') dependsOn('neoforgeJar')
from(layout.projectDirectory.file("adapters/neoforge/build/libs/${neoForgeArtifactName}")) from(layout.projectDirectory.file("adapters/neoforge/build/libs/${neoForgeArtifactName}"))
into(layout.projectDirectory.dir('dist')) into(pluginOutDirectory)
doFirst { doFirst {
delete(fileTree(layout.projectDirectory.dir('dist')) { delete(fileTree(pluginOutDirectory) {
include('Iris v* [NeoForge] *.jar') include('Iris v* [NeoForge] *.jar')
}) })
delete(layout.projectDirectory.file("dist/Iris-${project.version}+mc${minecraftVersion}-neoforge.jar")) delete(new File(pluginOutDirectory, "Iris-${project.version}+mc${minecraftVersion}-neoforge.jar"))
} }
} }
@@ -650,10 +649,9 @@ tasks.register('buildAllToOut') {
group = 'iris' group = 'iris'
dependsOn('buildBukkit', 'buildFabric', 'buildForge', 'buildNeoforge', ':spi:jar') dependsOn('buildBukkit', 'buildFabric', 'buildForge', 'buildNeoforge', ':spi:jar')
doLast { doLast {
File dist = layout.projectDirectory.dir('dist').asFile File[] jars = pluginOutDirectory.listFiles((java.io.FileFilter) { File f -> f.name.startsWith('Iris v') && f.name.endsWith('.jar') })
File[] jars = dist.listFiles((java.io.FileFilter) { File f -> f.name.endsWith('.jar') })
println('') println('')
println('=== Iris buildAllToOut -> dist/ ===') println('=== Iris buildAllToOut -> ' + pluginOutDirectory + ' ===')
if (jars != null) { if (jars != null) {
jars.sort { it.name }.each { File f -> jars.sort { it.name }.each { File f ->
println(String.format(' %-60s %8d KB', f.name, (long) (f.length() / 1024))) println(String.format(' %-60s %8d KB', f.name, (long) (f.length() / 1024)))
@@ -725,39 +723,6 @@ tasks.register('irisDev', Copy) {
dependsOn(':core:javadocJar') dependsOn(':core:javadocJar')
} }
def cli = file('sentry-cli.exe')
tasks.register('downloadCli', Download) {
group = 'io.sentry'
src("https://release-registry.services.sentry.io/apps/sentry-cli/latest?response=download&arch=x86_64&platform=${System.getProperty('os.name')}&package=sentry-cli")
dest(cli)
doLast {
cli.setExecutable(true)
}
}
tasks.register('release') {
group = 'io.sentry'
dependsOn('downloadCli')
doLast {
String url = 'http://sentry.volmit.com:8080'
def authToken = project.findProperty('sentry.auth.token') ?: System.getenv('SENTRY_AUTH_TOKEN')
String org = 'sentry'
String projectName = 'iris'
runCommand(cli, '--url', url, '--auth-token', authToken, 'releases', 'new', '-o', org, '-p', projectName, version)
runCommand(cli, '--url', url, '--auth-token', authToken, 'releases', 'set-commits', '-o', org, '-p', projectName, version, '--auto', '--ignore-missing')
//exec(cli, "--url", url, "--auth-token", authToken, "releases", "finalize", "-o", org, "-p", projectName, version)
cli.delete()
}
}
void runCommand(Object... command) {
Process process = new ProcessBuilder(command.collect { it.toString() }).start()
process.inputStream.readLines().each { println(it) }
process.errorStream.readLines().each { println(it) }
process.waitFor()
}
configurations.configureEach { configurations.configureEach {
resolutionStrategy.cacheChangingModulesFor(0, 'seconds') resolutionStrategy.cacheChangingModulesFor(0, 'seconds')
resolutionStrategy.cacheDynamicVersionsFor(0, 'seconds') resolutionStrategy.cacheDynamicVersionsFor(0, 'seconds')
@@ -29,7 +29,6 @@ public final class BukkitArtifactVerifier {
"art/arcane/iris/util/paper/", "art/arcane/iris/util/paper/",
"art/arcane/iris/util/kyori/", "art/arcane/iris/util/kyori/",
"art/arcane/iris/util/metrics/", "art/arcane/iris/util/metrics/",
"art/arcane/iris/util/sentry/",
"art/arcane/iris/util/maven/", "art/arcane/iris/util/maven/",
"art/arcane/iris/util/plexus/", "art/arcane/iris/util/plexus/",
"art/arcane/iris/util/sisu/", "art/arcane/iris/util/sisu/",
-33
View File
@@ -1,5 +1,4 @@
import io.github.slimjar.resolver.data.Mirror import io.github.slimjar.resolver.data.Mirror
import org.gradle.api.Task
import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.compile.JavaCompile
@@ -31,7 +30,6 @@ plugins {
id 'java' id 'java'
id 'java-library' id 'java-library'
alias(libs.plugins.shadow) alias(libs.plugins.shadow)
alias(libs.plugins.sentry)
alias(libs.plugins.slimjar) alias(libs.plugins.slimjar)
} }
@@ -39,8 +37,6 @@ def lib = 'art.arcane.iris.util'
String volmLibCoordinate = providers.gradleProperty('volmLibCoordinate') String volmLibCoordinate = providers.gradleProperty('volmLibCoordinate')
.orElse('com.github.VolmitSoftware:VolmLib:e6574cf814b3dd670385a4d632a63fde2038e186') .orElse('com.github.VolmitSoftware:VolmLib:e6574cf814b3dd670385a4d632a63fde2038e186')
.get() .get()
String sentryAuthToken = findProperty('sentry.auth.token') as String ?: System.getenv('SENTRY_AUTH_TOKEN')
boolean hasSentryAuthToken = sentryAuthToken != null && !sentryAuthToken.isBlank()
/** /**
* Dependencies. * Dependencies.
@@ -97,8 +93,6 @@ dependencies {
slim(libs.adventure.serializer.legacy) slim(libs.adventure.serializer.legacy)
slim(libs.adventure.serializer.plain) slim(libs.adventure.serializer.plain)
slim(libs.bstats) slim(libs.bstats)
slim(libs.sentry)
slim(libs.commons.io) slim(libs.commons.io)
slim(libs.commons.lang3) slim(libs.commons.lang3)
slim(libs.oshi) slim(libs.oshi)
@@ -134,16 +128,6 @@ java {
} }
} }
sentry {
url = 'http://sentry.volmit.com:8080'
autoInstallation.enabled = false
includeSourceContext = true
org = 'sentry'
projectName = 'iris'
authToken = sentryAuthToken
}
slimJar { slimJar {
mirrors = [ mirrors = [
new Mirror( new Mirror(
@@ -158,7 +142,6 @@ slimJar {
relocate('io.papermc.lib', "${lib}.paper") relocate('io.papermc.lib', "${lib}.paper")
relocate('net.kyori', "${lib}.kyori") relocate('net.kyori', "${lib}.kyori")
relocate('org.bstats', "${lib}.metrics") relocate('org.bstats', "${lib}.metrics")
relocate('io.sentry', "${lib}.sentry")
relocate('org.apache.maven', "${lib}.maven") relocate('org.apache.maven', "${lib}.maven")
relocate('org.codehaus.plexus', "${lib}.plexus") relocate('org.codehaus.plexus', "${lib}.plexus")
relocate('org.eclipse.sisu', "${lib}.sisu") relocate('org.eclipse.sisu', "${lib}.sisu")
@@ -464,22 +447,6 @@ tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.Shadow
} }
} }
tasks.named('sentryCollectSourcesJava').configure {
dependsOn(generateTemplates)
}
tasks.named('generateSentryBundleIdJava').configure {
dependsOn(generateTemplates)
}
tasks.matching { Task task ->
task.name.startsWith('sentry') || task.name.startsWith('generateSentry')
}.configureEach {
onlyIf {
hasSentryAuthToken
}
}
rootProject.tasks.matching { rootProject.tasks.matching {
it.name == 'prepareKotlinBuildScriptModel' it.name == 'prepareKotlinBuildScriptModel'
}.configureEach { }.configureEach {
-2
View File
@@ -187,5 +187,3 @@ art/arcane/iris/util/project/matter/IrisMatterSupport.java
art/arcane/iris/util/project/matter/WorldMatter.java art/arcane/iris/util/project/matter/WorldMatter.java
art/arcane/iris/util/project/matter/slices/EntityMatter.java art/arcane/iris/util/project/matter/slices/EntityMatter.java
art/arcane/iris/util/project/matter/slices/TileMatter.java art/arcane/iris/util/project/matter/slices/TileMatter.java
art/arcane/iris/util/project/sentry/Attachments.java
art/arcane/iris/util/project/sentry/ServerID.java
@@ -47,7 +47,6 @@ public class IrisSettings {
private IrisSettingsStudio studio = new IrisSettingsStudio(); private IrisSettingsStudio studio = new IrisSettingsStudio();
private IrisSettingsPerformance performance = new IrisSettingsPerformance(); private IrisSettingsPerformance performance = new IrisSettingsPerformance();
private IrisSettingsPregen pregen = new IrisSettingsPregen(); private IrisSettingsPregen pregen = new IrisSettingsPregen();
private IrisSettingsSentry sentry = new IrisSettingsSentry();
private IrisSettingsTreeFeller treeFeller = new IrisSettingsTreeFeller(); private IrisSettingsTreeFeller treeFeller = new IrisSettingsTreeFeller();
public static int getThreadCount(int c) { public static int getThreadCount(int c) {
@@ -182,7 +181,6 @@ public class IrisSettings {
studio = studio == null ? new IrisSettingsStudio() : studio; studio = studio == null ? new IrisSettingsStudio() : studio;
performance = performance == null ? new IrisSettingsPerformance() : performance; performance = performance == null ? new IrisSettingsPerformance() : performance;
pregen = pregen == null ? new IrisSettingsPregen() : pregen; pregen = pregen == null ? new IrisSettingsPregen() : pregen;
sentry = sentry == null ? new IrisSettingsSentry() : sentry;
treeFeller = treeFeller == null ? new IrisSettingsTreeFeller() : treeFeller; treeFeller = treeFeller == null ? new IrisSettingsTreeFeller() : treeFeller;
} }
@@ -340,13 +338,6 @@ public class IrisSettings {
} }
} }
@Data
public static class IrisSettingsSentry {
public boolean includeServerId = true;
public boolean disableAutoReporting = false;
public boolean debug = false;
}
@Data @Data
public static class IrisSettingsGUI { public static class IrisSettingsGUI {
public boolean useServerLaunchedGuis = true; public boolean useServerLaunchedGuis = true;
@@ -38,10 +38,6 @@ public final class DirectorCommandMessages {
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count",
"Get Loaded TectonicPlates Count" "Get Loaded TectonicPlates Count"
); );
public static final TextKey COMMAND_DEVELOPER_DIRECTOR_SEND_TEST_EXCEPTION_SENTRY = TextKey.of(
"iris.director.commanddeveloper.director.send_test_exception_sentry",
"Send a test exception to sentry"
);
public static final TextKey COMMAND_DEVELOPER_DIRECTOR_HASH_GENERATED_BLOCK_OUTPUT_FIXED_AREA_DETERMINISM_IDENTITY_TESTING = TextKey.of( public static final TextKey COMMAND_DEVELOPER_DIRECTOR_HASH_GENERATED_BLOCK_OUTPUT_FIXED_AREA_DETERMINISM_IDENTITY_TESTING = TextKey.of(
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing",
"Hash generated block output of a fixed area for determinism/identity testing" "Hash generated block output of a fixed area for determinism/identity testing"
@@ -876,7 +872,6 @@ public final class DirectorCommandMessages {
COMMAND_DATAPACK_PARAM_DATAPACK_ID_FOLDER_NAME_SHOWN_BY_IRIS_DATAPACK_LIST, COMMAND_DATAPACK_PARAM_DATAPACK_ID_FOLDER_NAME_SHOWN_BY_IRIS_DATAPACK_LIST,
COMMAND_DEVELOPER_DIRECTOR_IRIS_WORLD_MANAGER, COMMAND_DEVELOPER_DIRECTOR_IRIS_WORLD_MANAGER,
COMMAND_DEVELOPER_DIRECTOR_GET_LOADED_TECTONICPLATES_COUNT, COMMAND_DEVELOPER_DIRECTOR_GET_LOADED_TECTONICPLATES_COUNT,
COMMAND_DEVELOPER_DIRECTOR_SEND_TEST_EXCEPTION_SENTRY,
COMMAND_DEVELOPER_DIRECTOR_HASH_GENERATED_BLOCK_OUTPUT_FIXED_AREA_DETERMINISM_IDENTITY_TESTING, COMMAND_DEVELOPER_DIRECTOR_HASH_GENERATED_BLOCK_OUTPUT_FIXED_AREA_DETERMINISM_IDENTITY_TESTING,
COMMAND_DEVELOPER_PARAM_WORLD_HASH, COMMAND_DEVELOPER_PARAM_WORLD_HASH,
COMMAND_DEVELOPER_PARAM_RADIUS_CHUNKS_AROUND_CENTER, COMMAND_DEVELOPER_PARAM_RADIUS_CHUNKS_AROUND_CENTER,
@@ -503,10 +503,6 @@ public final class ModdedCommandMessages {
"iris.modded.moddeddatapackcommands.message_2", "iris.modded.moddeddatapackcommands.message_2",
" - " + "{name}" " - " + "{name}"
); );
public static final TextKey MODDED_DEVELOPER_COMMANDS_DISPATCHED_TEST_EXCEPTION_IRIS_ERROR_REPORTER_SENTRY_IF_ENABLED = TextKey.of(
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled",
"Dispatched a test exception to the Iris error reporter (Sentry if enabled)."
);
public static final TextKey MODDED_DEVELOPER_COMMANDS_MESSAGE = TextKey.of( public static final TextKey MODDED_DEVELOPER_COMMANDS_MESSAGE = TextKey.of(
"iris.modded.moddeddevelopercommands.message", "iris.modded.moddeddevelopercommands.message",
" " + "{value}" " " + "{value}"
@@ -1369,7 +1365,6 @@ public final class ModdedCommandMessages {
MODDED_DATAPACK_COMMANDS_MODRINTH_INGEST_IS_BUKKIT_ONLY_INSTALL_THESE_MANUALLY_INTO_WORLD, MODDED_DATAPACK_COMMANDS_MODRINTH_INGEST_IS_BUKKIT_ONLY_INSTALL_THESE_MANUALLY_INTO_WORLD,
MODDED_DATAPACK_COMMANDS_INSTALLED_WORLD_DATAPACKS, MODDED_DATAPACK_COMMANDS_INSTALLED_WORLD_DATAPACKS,
MODDED_DATAPACK_COMMANDS_MESSAGE_2, MODDED_DATAPACK_COMMANDS_MESSAGE_2,
MODDED_DEVELOPER_COMMANDS_DISPATCHED_TEST_EXCEPTION_IRIS_ERROR_REPORTER_SENTRY_IF_ENABLED,
MODDED_DEVELOPER_COMMANDS_MESSAGE, MODDED_DEVELOPER_COMMANDS_MESSAGE,
MODDED_DEVELOPER_COMMANDS_NETWORK_SCAN_FAILED, MODDED_DEVELOPER_COMMANDS_NETWORK_SCAN_FAILED,
MODDED_GOLDEN_HASH_GOLDENHASH_SCAN_IS_ALREADY_RUNNING, MODDED_GOLDEN_HASH_GOLDENHASH_SCAN_IS_ALREADY_RUNNING,
@@ -98,9 +98,9 @@ public final class ModdedHelpMessages {
"iris.modded.help.entry.command.goldenhash", "iris.modded.help.entry.command.goldenhash",
"Generate deterministic block hashes for parity testing" "Generate deterministic block hashes for parity testing"
); );
public static final TextKey GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_SENTRY_TEST_NETWORK_INTERFACES_REGION_FILE_SCAN = TextKey.of( public static final TextKey GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_NETWORK_INTERFACES_REGION_FILE_SCAN = TextKey.of(
"iris.modded.help.entry.group.developer", "iris.modded.help.entry.group.developer",
"Developer diagnostics: Sentry test, network interfaces, region-file scan" "Developer diagnostics: network interfaces and region-file scan"
); );
public static final TextKey COMMAND_BIOME_FIND_AN_IRIS_BIOME = TextKey.of( public static final TextKey COMMAND_BIOME_FIND_AN_IRIS_BIOME = TextKey.of(
"iris.modded.help.entry.command.biome", "iris.modded.help.entry.command.biome",
@@ -346,10 +346,6 @@ public final class ModdedHelpMessages {
"iris.modded.help.entry.command.verify", "iris.modded.help.entry.command.verify",
"Report native and Iris structure reachability in the current dimension" "Report native and Iris structure reachability in the current dimension"
); );
public static final TextKey COMMAND_SENTRY_SEND_A_TEST_EXCEPTION_TO_THE_IRIS_ERROR_REPORTER = TextKey.of(
"iris.modded.help.entry.command.sentry",
"Send a test exception to the Iris error reporter"
);
public static final TextKey COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES = TextKey.of( public static final TextKey COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES = TextKey.of(
"iris.modded.help.entry.command.network", "iris.modded.help.entry.command.network",
"List network interfaces and their addresses" "List network interfaces and their addresses"
@@ -443,7 +439,7 @@ public final class ModdedHelpMessages {
GROUP_DATAPACK_WORLD_DATAPACK_INSTALL_AND_STATUS_HELPERS, GROUP_DATAPACK_WORLD_DATAPACK_INSTALL_AND_STATUS_HELPERS,
GROUP_STRUCTURE_IRIS_STRUCTURE_INDEX_INFO_AND_PLACEMENT_TOOLS, GROUP_STRUCTURE_IRIS_STRUCTURE_INDEX_INFO_AND_PLACEMENT_TOOLS,
COMMAND_GOLDENHASH_GENERATE_DETERMINISTIC_BLOCK_HASHES_FOR_PARITY_TESTING, COMMAND_GOLDENHASH_GENERATE_DETERMINISTIC_BLOCK_HASHES_FOR_PARITY_TESTING,
GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_SENTRY_TEST_NETWORK_INTERFACES_REGION_FILE_SCAN, GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_NETWORK_INTERFACES_REGION_FILE_SCAN,
COMMAND_BIOME_FIND_AN_IRIS_BIOME, COMMAND_BIOME_FIND_AN_IRIS_BIOME,
COMMAND_REGION_FIND_AN_IRIS_REGION, COMMAND_REGION_FIND_AN_IRIS_REGION,
COMMAND_OBJECT_FIND_AN_OBJECT_PLACEMENT, COMMAND_OBJECT_FIND_AN_OBJECT_PLACEMENT,
@@ -505,7 +501,6 @@ public final class ModdedHelpMessages {
COMMAND_IMPORT_EXPLAIN_BUKKIT_STRUCTURE_IMPORT_WORKFLOW, COMMAND_IMPORT_EXPLAIN_BUKKIT_STRUCTURE_IMPORT_WORKFLOW,
COMMAND_CAPTURE_EXPLAIN_BUKKIT_STRUCTURE_CAPTURE_WORKFLOW, COMMAND_CAPTURE_EXPLAIN_BUKKIT_STRUCTURE_CAPTURE_WORKFLOW,
COMMAND_VERIFY_REPORT_NATIVE_AND_IRIS_STRUCTURE_REACHABILITY_IN_THE_CURRENT_DIMENSION, COMMAND_VERIFY_REPORT_NATIVE_AND_IRIS_STRUCTURE_REACHABILITY_IN_THE_CURRENT_DIMENSION,
COMMAND_SENTRY_SEND_A_TEST_EXCEPTION_TO_THE_IRIS_ERROR_REPORTER,
COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES, COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES,
COMMAND_WHAT_HERE_INSPECT_CURRENT_IRIS_CONTEXT, COMMAND_WHAT_HERE_INSPECT_CURRENT_IRIS_CONTEXT,
COMMAND_WHAT_BIOME_INSPECT_CURRENT_BIOME, COMMAND_WHAT_BIOME_INSPECT_CURRENT_BIOME,
@@ -18,7 +18,6 @@
package art.arcane.iris.engine; package art.arcane.iris.engine;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.core.IrisSettings; import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.core.tools.WorldMaintenance; import art.arcane.iris.core.tools.WorldMaintenance;
@@ -34,6 +33,7 @@ import art.arcane.iris.engine.mantle.components.MantleHydrologyComponent;
import art.arcane.iris.engine.mantle.components.IrisStructureComponent; import art.arcane.iris.engine.mantle.components.IrisStructureComponent;
import art.arcane.iris.engine.object.IrisDimension; import art.arcane.iris.engine.object.IrisDimension;
import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.iris.util.project.matter.IrisMatterContext; import art.arcane.iris.util.project.matter.IrisMatterContext;
import art.arcane.iris.util.project.matter.IrisMatterSupport; import art.arcane.iris.util.project.matter.IrisMatterSupport;
@@ -53,7 +53,6 @@ import art.arcane.iris.util.common.format.C;
import art.arcane.volmlib.util.matter.IrisMatter; import art.arcane.volmlib.util.matter.IrisMatter;
import art.arcane.volmlib.util.matter.Matter; import art.arcane.volmlib.util.matter.Matter;
import art.arcane.volmlib.util.matter.MatterSlice; import art.arcane.volmlib.util.matter.MatterSlice;
import art.arcane.iris.platform.bukkit.BukkitPlatform;
import art.arcane.iris.util.common.parallel.HyperLock; import art.arcane.iris.util.common.parallel.HyperLock;
import art.arcane.iris.util.common.parallel.MultiBurst; import art.arcane.iris.util.common.parallel.MultiBurst;
import lombok.AccessLevel; import lombok.AccessLevel;
@@ -76,7 +75,6 @@ import java.util.function.Supplier;
@ToString(exclude = "engine") @ToString(exclude = "engine")
public class IrisEngineMantle implements EngineMantle { public class IrisEngineMantle implements EngineMantle {
public static final String STORAGE_FOLDER_NAME = "mantle-hydrology"; public static final String STORAGE_FOLDER_NAME = "mantle-hydrology";
private static final boolean BUKKIT_PRESENT = IrisMatterSupport.isBukkitPresent();
private final Engine engine; private final Engine engine;
private final Mantle<Matter> mantle; private final Mantle<Matter> mantle;
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
@@ -260,10 +258,7 @@ public class IrisEngineMantle implements EngineMantle {
if (value instanceof PlatformBlockState) { if (value instanceof PlatformBlockState) {
return PlatformBlockState.class; return PlatformBlockState.class;
} }
if (BUKKIT_PRESENT) { return IrisPlatforms.get().classifyMantleValue(value);
return BukkitPlatform.classifyMantleValue(value);
}
return value.getClass();
} }
@Override @Override
@@ -43,21 +43,11 @@ final class DecoratorCore {
private static final String WEEPING_VINES_PLANT = "minecraft:weeping_vines_plant"; private static final String WEEPING_VINES_PLANT = "minecraft:weeping_vines_plant";
private static final String TWISTING_VINES = "minecraft:twisting_vines"; private static final String TWISTING_VINES = "minecraft:twisting_vines";
private static final String TWISTING_VINES_PLANT = "minecraft:twisting_vines_plant"; private static final String TWISTING_VINES_PLANT = "minecraft:twisting_vines_plant";
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static volatile PlatformBlockState weepingVines; private static volatile PlatformBlockState weepingVines;
private static volatile PlatformBlockState weepingVinesPlant; private static volatile PlatformBlockState weepingVinesPlant;
private static volatile PlatformBlockState twistingVines; private static volatile PlatformBlockState twistingVines;
private static volatile PlatformBlockState twistingVinesPlant; private static volatile PlatformBlockState twistingVinesPlant;
private static boolean detectBukkit() {
try {
Class.forName("org.bukkit.Bukkit", false, DecoratorCore.class.getClassLoader());
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
static final ThreadLocal<PlaceOpts> SCRATCH_OPTS = ThreadLocal.withInitial(PlaceOpts::new); static final ThreadLocal<PlaceOpts> SCRATCH_OPTS = ThreadLocal.withInitial(PlaceOpts::new);
static final class PlaceOpts { static final class PlaceOpts {
@@ -391,9 +381,9 @@ final class DecoratorCore {
if (!B.isVineBlock(b)) { if (!B.isVineBlock(b)) {
return b; return b;
} }
if (!BUKKIT_PRESENT) { DecoratorPlatformHooks.FaceFixer fixer = DecoratorPlatformHooks.faceFixer();
DecoratorPlatformHooks.FaceFixer fixer = DecoratorPlatformHooks.faceFixer(); if (fixer != null) {
return fixer == null ? b : fixer.fixFaces(b, hunk, rX, rZ, x, y, z, mantle); return fixer.fixFaces(b, hunk, rX, rZ, x, y, z, mantle);
} }
BlockData rawB = (BlockData) b.nativeHandle(); BlockData rawB = (BlockData) b.nativeHandle();
BlockData cloned = rawB.clone(); BlockData cloned = rawB.clone();
@@ -447,9 +437,9 @@ final class DecoratorCore {
if (!B.canPlaceOnto(decorator, surface)) { if (!B.canPlaceOnto(decorator, surface)) {
return false; return false;
} }
if (!BUKKIT_PRESENT) { DecoratorPlatformHooks.SurfaceSturdiness sturdiness = DecoratorPlatformHooks.surfaceSturdiness();
DecoratorPlatformHooks.SurfaceSturdiness sturdiness = DecoratorPlatformHooks.surfaceSturdiness(); if (sturdiness != null) {
return sturdiness == null ? B.isSolid(surface) : sturdiness.canGoOn(surface); return sturdiness.canGoOn(surface);
} }
return ((BlockData) surface.nativeHandle()).isFaceSturdy(BlockFace.UP, BlockSupport.FULL); return ((BlockData) surface.nativeHandle()).isFaceSturdy(BlockFace.UP, BlockSupport.FULL);
} }
@@ -19,7 +19,6 @@ public record HydrologyFeatureQuery(Set<HydrologyFeatureType> types, String prof
HydrologyFeatureType.MOUTH HydrologyFeatureType.MOUTH
); );
private static final Set<HydrologyFeatureType> UNDERGROUND = Set.of( private static final Set<HydrologyFeatureType> UNDERGROUND = Set.of(
HydrologyFeatureType.RIDGE_BORE,
HydrologyFeatureType.UNDERGROUND_POOL, HydrologyFeatureType.UNDERGROUND_POOL,
HydrologyFeatureType.UNDERGROUND_DROP, HydrologyFeatureType.UNDERGROUND_DROP,
HydrologyFeatureType.SINKHOLE HydrologyFeatureType.SINKHOLE
@@ -94,7 +93,6 @@ public record HydrologyFeatureQuery(Set<HydrologyFeatureType> types, String prof
builtIns.put("coastal_grotto", Set.of(HydrologyFeatureType.COASTAL_GROTTO)); builtIns.put("coastal_grotto", Set.of(HydrologyFeatureType.COASTAL_GROTTO));
builtIns.put("inland_grotto", Set.of(HydrologyFeatureType.INLAND_GROTTO)); builtIns.put("inland_grotto", Set.of(HydrologyFeatureType.INLAND_GROTTO));
builtIns.put("mouth", Set.of(HydrologyFeatureType.MOUTH)); builtIns.put("mouth", Set.of(HydrologyFeatureType.MOUTH));
builtIns.put("ridge_tunnel", Set.of(HydrologyFeatureType.RIDGE_BORE));
builtIns.put("deep", DEEP); builtIns.put("deep", DEEP);
builtIns.put("pool", Set.of(HydrologyFeatureType.STANDING_POOL)); builtIns.put("pool", Set.of(HydrologyFeatureType.STANDING_POOL));
return Collections.unmodifiableMap(builtIns); return Collections.unmodifiableMap(builtIns);
@@ -9,7 +9,6 @@ import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
public final class BlockDataMergeSupport { public final class BlockDataMergeSupport {
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static volatile StateMerger PLATFORM_MERGER = null; private static volatile StateMerger PLATFORM_MERGER = null;
private BlockDataMergeSupport() { private BlockDataMergeSupport() {
@@ -29,31 +28,15 @@ public final class BlockDataMergeSupport {
PLATFORM_MERGER = merger; PLATFORM_MERGER = merger;
} }
private static boolean detectBukkit() {
try {
Class.forName("org.bukkit.Bukkit", false, BlockDataMergeSupport.class.getClassLoader());
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
static PlatformBlockState merge(PlatformBlockState base, PlatformBlockState update) { static PlatformBlockState merge(PlatformBlockState base, PlatformBlockState update) {
if (!BUKKIT_PRESENT) { StateMerger merger = PLATFORM_MERGER;
StateMerger merger = requirePlatformMerger(PLATFORM_MERGER); if (merger != null) {
return merger.merge(base, update); return merger.merge(base, update);
} }
BlockData merged = merge((BlockData) base.nativeHandle(), (BlockData) update.nativeHandle(), BukkitBlockResolution::get); BlockData merged = merge((BlockData) base.nativeHandle(), (BlockData) update.nativeHandle(), BukkitBlockResolution::get);
return merged == null ? null : BukkitBlockState.of(merged); return merged == null ? null : BukkitBlockState.of(merged);
} }
static StateMerger requirePlatformMerger(StateMerger merger) {
if (merger == null) {
throw new IllegalStateException("No platform block-state merger is bound");
}
return merger;
}
static BlockData merge(BlockData base, BlockData update, Function<String, BlockData> resolver) { static BlockData merge(BlockData base, BlockData update, Function<String, BlockData> resolver) {
try { try {
return base.merge(update); return base.merge(update);
@@ -53,7 +53,6 @@ import java.util.Set;
@Desc("Configures rotation for iris") @Desc("Configures rotation for iris")
@Data @Data
public class IrisObjectRotation { public class IrisObjectRotation {
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static volatile StateRotator PLATFORM_ROTATOR = null; private static volatile StateRotator PLATFORM_ROTATOR = null;
public interface StateRotator { public interface StateRotator {
@@ -70,15 +69,6 @@ public class IrisObjectRotation {
PLATFORM_ROTATOR = rotator; PLATFORM_ROTATOR = rotator;
} }
private static boolean detectBukkit() {
try {
Class.forName("org.bukkit.Bukkit", false, IrisObjectRotation.class.getClassLoader());
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
private static final class Faces { private static final class Faces {
private static final List<BlockFace> WALL_FACES = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); private static final List<BlockFace> WALL_FACES = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
} }
@@ -298,8 +288,8 @@ public class IrisObjectRotation {
return null; return null;
} }
if (!BUKKIT_PRESENT) { StateRotator rotator = PLATFORM_ROTATOR;
StateRotator rotator = requirePlatformRotator(PLATFORM_ROTATOR); if (rotator != null) {
return rotator.rotate(this, state, spinx, spiny, spinz); return rotator.rotate(this, state, spinx, spiny, spinz);
} }
@@ -313,13 +303,6 @@ public class IrisObjectRotation {
return rotated == null ? null : BukkitBlockState.of(rotated); return rotated == null ? null : BukkitBlockState.of(rotated);
} }
static StateRotator requirePlatformRotator(StateRotator rotator) {
if (rotator == null) {
throw new IllegalStateException("No platform block-state rotator is bound");
}
return rotator;
}
private static boolean canRotateBlockData(BlockData data) { private static boolean canRotateBlockData(BlockData data) {
return data instanceof Directional return data instanceof Directional
|| data instanceof Rotatable || data instanceof Rotatable
@@ -45,9 +45,9 @@ import java.util.stream.StreamSupport;
/** /**
* Bukkit-only pre-key tile format. Unreachable from the modded loaders: every entry point is * Bukkit-only pre-key tile format. Unreachable from the modded loaders: every entry point is
* either Bukkit-typed ({@link #fromBukkit(BlockState)}, reached only from * either Bukkit-typed ({@link #fromBukkit(BlockState)}, reached only from
* {@link TileData#getTileState(Block, boolean)} and the Bukkit structure importer) or sits behind * {@link TileData#getTileState(Block, boolean)} and the Bukkit structure importer) or follows the
* the {@code BUKKIT_PRESENT} short-circuit in {@link TileData#read(DataInputStream)}, which hands * bound platform-reader path in {@link TileData#read(DataInputStream)}, which returns before this
* off to the bound platform reader before this class is ever referenced. The nested handler types * class is ever referenced. The nested handler types
* therefore keep their raw Bukkit fields. * therefore keep their raw Bukkit fields.
*/ */
@ToString @ToString
@@ -64,7 +64,6 @@ public class TileData implements Cloneable {
* never part of that walk. Bounded by the number of distinct material keys a pack can name. * never part of that walk. Bounded by the number of distinct material keys a pack can name.
*/ */
private static final Map<String, Material> RESOLVED_MATERIALS = new ConcurrentHashMap<>(); private static final Map<String, Material> RESOLVED_MATERIALS = new ConcurrentHashMap<>();
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static volatile TileReader PLATFORM_READER = null; private static volatile TileReader PLATFORM_READER = null;
private static volatile TileFactory PLATFORM_FACTORY = null; private static volatile TileFactory PLATFORM_FACTORY = null;
@@ -96,15 +95,6 @@ public class TileData implements Cloneable {
PLATFORM_FACTORY = factory; PLATFORM_FACTORY = factory;
} }
private static boolean detectBukkit() {
try {
Class.forName("org.bukkit.Bukkit", false, TileData.class.getClassLoader());
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
/** /**
* The block key this tile belongs to, stored as text so the field type never drags * The block key this tile belongs to, stored as text so the field type never drags
* org.bukkit.Material onto a Gson field walk or into generated equals/hashCode/toString. * org.bukkit.Material onto a Gson field walk or into generated equals/hashCode/toString.
@@ -147,8 +137,9 @@ public class TileData implements Cloneable {
} }
public static TileData of(PlatformBlockState state, KMap<String, Object> properties) { public static TileData of(PlatformBlockState state, KMap<String, Object> properties) {
if (!BUKKIT_PRESENT) { TileFactory factory = PLATFORM_FACTORY;
return requirePlatformFactory(PLATFORM_FACTORY).create(state, properties); if (factory != null) {
return factory.create(state, properties);
} }
Object handle = state.nativeHandle(); Object handle = state.nativeHandle();
if (!(handle instanceof BlockData blockData)) { if (!(handle instanceof BlockData blockData)) {
@@ -158,8 +149,9 @@ public class TileData implements Cloneable {
} }
public static TileData read(DataInputStream in) throws IOException { public static TileData read(DataInputStream in) throws IOException {
if (!BUKKIT_PRESENT) { TileReader reader = PLATFORM_READER;
return requirePlatformReader(PLATFORM_READER).read(in); if (reader != null) {
return reader.read(in);
} }
if (!in.markSupported()) if (!in.markSupported())
throw new IOException("Mark not supported"); throw new IOException("Mark not supported");
@@ -215,20 +207,6 @@ public class TileData implements Cloneable {
return resolved; return resolved;
} }
static TileFactory requirePlatformFactory(TileFactory factory) {
if (factory == null) {
throw new IllegalStateException("No platform tile-data factory is bound");
}
return factory;
}
static TileReader requirePlatformReader(TileReader reader) throws IOException {
if (reader == null) {
throw new IOException("No platform tile-data reader is bound");
}
return reader;
}
public boolean isApplicable(BlockData data) { public boolean isApplicable(BlockData data) {
Material resolved = resolveMaterial(); Material resolved = resolveMaterial();
return resolved != null && data.getMaterial() == resolved; return resolved != null && data.getMaterial() == resolved;
@@ -175,7 +175,8 @@ public final class BukkitPlatform implements IrisPlatform {
return BukkitBiome.of((Biome) biome); return BukkitBiome.of((Biome) biome);
} }
public static Class<?> classifyMantleValue(Object value) { @Override
public Class<?> classifyMantleValue(Object value) {
if (value instanceof World) { if (value instanceof World) {
return World.class; return World.class;
} }
@@ -191,6 +192,11 @@ public final class BukkitPlatform implements IrisPlatform {
return value.getClass(); return value.getClass();
} }
@Override
public boolean supportsMatterWorldIo() {
return true;
}
public static void unregisterListener(Object candidate) { public static void unregisterListener(Object candidate) {
if (candidate instanceof Listener listener) { if (candidate instanceof Listener listener) {
volmitPlugin().unregisterListener(listener); volmitPlugin().unregisterListener(listener);
@@ -1,23 +1,10 @@
package art.arcane.iris.util.common.misc; package art.arcane.iris.util.common.misc;
import art.arcane.iris.util.project.sentry.Attachments;
import art.arcane.iris.util.project.sentry.IrisLogger;
import art.arcane.iris.util.project.sentry.ServerID;
import com.google.gson.JsonSyntaxException;
import art.arcane.iris.BuildConstants; import art.arcane.iris.BuildConstants;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.platform.bukkit.BukkitPlatform;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.nms.INMS;
import art.arcane.iris.core.safeguard.IrisSafeguard;
import art.arcane.iris.core.tools.IrisToolbelt; import art.arcane.iris.core.tools.IrisToolbelt;
import art.arcane.iris.engine.platform.PlatformChunkGenerator; import art.arcane.iris.engine.platform.PlatformChunkGenerator;
import art.arcane.iris.util.project.context.IrisContext;
import art.arcane.volmlib.util.json.JSONException;
import art.arcane.iris.util.common.plugin.VolmitPlugin; import art.arcane.iris.util.common.plugin.VolmitPlugin;
import art.arcane.iris.util.common.scheduling.J; import art.arcane.iris.util.common.scheduling.J;
import io.sentry.Sentry;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bstats.charts.DrilldownPie; import org.bstats.charts.DrilldownPie;
import org.bstats.charts.SingleLineChart; import org.bstats.charts.SingleLineChart;
@@ -29,56 +16,6 @@ import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class Bindings { public class Bindings {
public static void capture(Throwable throwable) {
Sentry.captureException(throwable);
}
public static void setupSentry() {
var settings = IrisSettings.get().getSentry();
if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) return;
IrisLogging.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings.");
IrisLogging.info("Your server ID is: " + ServerID.getId());
Sentry.init(options -> {
options.setDsn("http://4cdbb9ac953306529947f4ca1e8e6b26@sentry.volmit.com:8080/2");
if (settings.debug) {
options.setLogger(new IrisLogger());
options.setDebug(true);
}
options.setAttachServerName(false);
options.setEnableUncaughtExceptionHandler(false);
options.setRelease(BukkitPlatform.plugin().getDescription().getVersion());
options.setEnvironment(BuildConstants.ENVIRONMENT);
options.setBeforeSend((event, hint) -> {
if (suppress(event.getThrowable())) return null;
event.setTag("iris.safeguard", IrisSafeguard.mode().getId());
event.setTag("iris.nms", INMS.get().getClass().getCanonicalName());
var context = IrisContext.get();
if (context != null) event.getContexts().set("engine", context.asContext());
event.getContexts().set("safeguard", IrisSafeguard.asContext());
return event;
});
});
Sentry.configureScope(scope -> {
if (settings.includeServerId) scope.setUser(ServerID.asUser());
scope.addAttachment(Attachments.PLUGINS);
scope.addAttachment(Attachments.SAFEGUARD);
scope.setTag("server", Bukkit.getVersion());
scope.setTag("server.type", Bukkit.getName());
scope.setTag("server.api", Bukkit.getBukkitVersion());
scope.setTag("iris.commit", BuildConstants.COMMIT);
});
}
private static boolean suppress(Throwable e) {
return (e instanceof IllegalStateException ex && "zip file closed".equals(ex.getMessage()))
|| e instanceof JSONException
|| e instanceof JsonSyntaxException;
}
// bstats.org plugin id // bstats.org plugin id
private static final int BSTATS_PLUGIN_ID = 24220; private static final int BSTATS_PLUGIN_ID = 24220;
@@ -87,7 +24,7 @@ public class Bindings {
return; return;
} }
J.s(() -> { J.s(() -> {
var metrics = new Metrics(plugin, BSTATS_PLUGIN_ID); Metrics metrics = new Metrics(plugin, BSTATS_PLUGIN_ID);
metrics.addCustomChart(new SingleLineChart("custom_dimensions", () -> Bukkit.getWorlds() metrics.addCustomChart(new SingleLineChart("custom_dimensions", () -> Bukkit.getWorlds()
.stream() .stream()
.filter(IrisToolbelt::isIrisWorld) .filter(IrisToolbelt::isIrisWorld)
@@ -100,7 +37,7 @@ public class Bindings {
.map(PlatformChunkGenerator::getEngine) .map(PlatformChunkGenerator::getEngine)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toMap(engine -> engine.getDimension().getLoadKey(), engine -> { .collect(Collectors.toMap(engine -> engine.getDimension().getLoadKey(), engine -> {
var hash32 = engine.getHash32().getNow(null); Long hash32 = engine.getHash32().getNow(null);
if (hash32 == null) return Map.of(); if (hash32 == null) return Map.of();
int version = engine.getDimension().getVersion(); int version = engine.getDimension().getVersion();
String checksum = Long.toHexString(hash32); String checksum = Long.toHexString(hash32);
@@ -121,7 +121,7 @@ public class J {
} }
public static void aBukkit(Runnable a) { public static void aBukkit(Runnable a) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
IrisPlatforms.get().scheduler().async(a); IrisPlatforms.get().scheduler().async(a);
} }
@@ -186,7 +186,7 @@ public class J {
} }
public static boolean isFolia() { public static boolean isFolia() {
return BUKKIT_PRESENT && FoliaScheduler.isFolia(Bukkit.getServer()); return usesBukkitScheduler() && FoliaScheduler.isFolia(Bukkit.getServer());
} }
public static boolean isPrimaryThread() { public static boolean isPrimaryThread() {
@@ -345,7 +345,7 @@ public class J {
return false; return false;
} }
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (!IrisPlatforms.isBound()) { if (!IrisPlatforms.isBound()) {
return false; return false;
} }
@@ -416,7 +416,7 @@ public class J {
public static void cancelPluginTasks() { public static void cancelPluginTasks() {
cancelTrackedRepeatingTasks(); cancelTrackedRepeatingTasks();
if (!BukkitPlatform.hasPlugin()) { if (!usesBukkitScheduler() || !BukkitPlatform.hasPlugin()) {
return; return;
} }
@@ -442,7 +442,7 @@ public class J {
} }
public static void s(Runnable r) { public static void s(Runnable r) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
IrisPlatforms.get().scheduler().global(r); IrisPlatforms.get().scheduler().global(r);
} }
@@ -566,7 +566,7 @@ public class J {
} }
public static void s(Runnable r, int delay) { public static void s(Runnable r, int delay) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
IrisPlatforms.get().scheduler().laterGlobal(r, delay); IrisPlatforms.get().scheduler().laterGlobal(r, delay);
} }
@@ -667,7 +667,7 @@ public class J {
} }
public static void a(Runnable r, int delay) { public static void a(Runnable r, int delay) {
if (!BUKKIT_PRESENT) { if (!usesBukkitScheduler()) {
if (IrisPlatforms.isBound()) { if (IrisPlatforms.isBound()) {
if (delay <= 0) { if (delay <= 0) {
IrisPlatforms.get().scheduler().async(r); IrisPlatforms.get().scheduler().async(r);
@@ -772,11 +772,17 @@ public class J {
} }
private static boolean isPluginEnabled() { private static boolean isPluginEnabled() {
return BUKKIT_PRESENT && BukkitPlatform.hasPlugin() && Bukkit.getPluginManager().isPluginEnabled(BukkitPlatform.plugin()); return usesBukkitScheduler() && BukkitPlatform.hasPlugin() && Bukkit.getPluginManager().isPluginEnabled(BukkitPlatform.plugin());
} }
private static boolean canSchedule() { private static boolean canSchedule() {
return BUKKIT_PRESENT ? isPluginEnabled() : IrisPlatforms.isBound(); return usesBukkitScheduler() ? isPluginEnabled() : IrisPlatforms.isBound();
}
static boolean usesBukkitScheduler() {
return BUKKIT_PRESENT
&& IrisPlatforms.isBound()
&& "bukkit".equalsIgnoreCase(IrisPlatforms.get().platformName());
} }
private static long ticksToMilliseconds(int ticks) { private static long ticksToMilliseconds(int ticks) {
@@ -38,25 +38,11 @@ import art.arcane.iris.util.common.math.IrisBlockVector;
import java.io.File; import java.io.File;
public final class IrisMatterSupport { public final class IrisMatterSupport {
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static boolean registered; private static boolean registered;
private IrisMatterSupport() { private IrisMatterSupport() {
} }
public static boolean isBukkitPresent() {
return BUKKIT_PRESENT;
}
private static boolean detectBukkit() {
try {
Class.forName("org.bukkit.World", false, IrisMatterSupport.class.getClassLoader());
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
public static synchronized void ensureRegistered() { public static synchronized void ensureRegistered() {
if (registered) { if (registered) {
return; return;
@@ -21,7 +21,7 @@ package art.arcane.iris.util.project.matter.slices;
import art.arcane.iris.platform.bukkit.BukkitPlatform; import art.arcane.iris.platform.bukkit.BukkitPlatform;
import art.arcane.iris.core.nms.INMS; import art.arcane.iris.core.nms.INMS;
import art.arcane.iris.engine.object.IrisPosition; import art.arcane.iris.engine.object.IrisPosition;
import art.arcane.iris.util.project.matter.IrisMatterSupport; import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.volmlib.util.collection.KList; import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.collection.KMap; import art.arcane.volmlib.util.collection.KMap;
import art.arcane.volmlib.util.data.Varint; import art.arcane.volmlib.util.data.Varint;
@@ -53,7 +53,7 @@ public class EntityMatter extends RawMatter<MatterEntityGroup> {
public EntityMatter(int width, int height, int depth) { public EntityMatter(int width, int height, int depth) {
super(width, height, depth, MatterEntityGroup.class); super(width, height, depth, MatterEntityGroup.class);
if (IrisMatterSupport.isBukkitPresent()) { if (IrisPlatforms.isBound() && IrisPlatforms.get().supportsMatterWorldIo()) {
registerBukkitIO(); registerBukkitIO();
} }
} }
@@ -20,7 +20,7 @@ package art.arcane.iris.util.project.matter.slices;
import art.arcane.iris.engine.object.TileData; import art.arcane.iris.engine.object.TileData;
import art.arcane.iris.util.project.matter.IrisMatterSupport; import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.util.project.matter.TileWrapper; import art.arcane.iris.util.project.matter.TileWrapper;
import art.arcane.volmlib.util.data.palette.Palette; import art.arcane.volmlib.util.data.palette.Palette;
import art.arcane.volmlib.util.matter.Sliced; import art.arcane.volmlib.util.matter.Sliced;
@@ -42,7 +42,7 @@ public class TileMatter extends RawMatter<TileWrapper> {
public TileMatter(int width, int height, int depth) { public TileMatter(int width, int height, int depth) {
super(width, height, depth, TileWrapper.class); super(width, height, depth, TileWrapper.class);
if (IrisMatterSupport.isBukkitPresent()) { if (IrisPlatforms.isBound() && IrisPlatforms.get().supportsMatterWorldIo()) {
registerBukkitIO(); registerBukkitIO();
} }
} }
@@ -1,43 +0,0 @@
package art.arcane.iris.util.project.sentry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import art.arcane.iris.core.safeguard.IrisSafeguard;
import art.arcane.volmlib.util.collection.KMap;
import io.sentry.Attachment;
import org.bukkit.Bukkit;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Callable;
public class Attachments {
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
public static final Attachment PLUGINS = jsonProvider(Attachments::plugins, "plugins.json");
public static final Attachment SAFEGUARD = jsonProvider(IrisSafeguard::asAttachment, "safeguard.json");
public static Attachment json(Object object, String name) {
return new Attachment(GSON.toJson(object).getBytes(StandardCharsets.UTF_8), name, "application/json", "event.attachment", true);
}
public static Attachment jsonProvider(Callable<Object> object, String name) {
return new Attachment(() -> GSON.toJson(object.call()).getBytes(StandardCharsets.UTF_8), name, "application/json", "event.attachment", true);
}
private static KMap<String, Object> plugins() {
KMap<String, String> enabled = new KMap<>();
KMap<String, String> disabled = new KMap<>();
var pm = Bukkit.getPluginManager();
for (var plugin : pm.getPlugins()) {
if (plugin.isEnabled()) {
enabled.put(plugin.getName(), plugin.getDescription().getVersion());
} else {
disabled.put(plugin.getName(), plugin.getDescription().getVersion());
}
}
return new KMap<String, Object>()
.qput("enabled", enabled)
.qput("disabled", disabled);
}
}
@@ -1,47 +0,0 @@
package art.arcane.iris.util.project.sentry;
import art.arcane.iris.spi.IrisLogging;
import io.sentry.ILogger;
import io.sentry.SentryLevel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.PrintWriter;
import java.io.StringWriter;
public class IrisLogger implements ILogger {
@Override
public void log(@NotNull SentryLevel level, @NotNull String message, @Nullable Object... args) {
IrisLogging.msg(String.format("%s: %s", level, String.format(message, args)));
}
@Override
public void log(@NotNull SentryLevel level, @NotNull String message, @Nullable Throwable throwable) {
if (throwable == null) {
log(level, message);
} else {
IrisLogging.msg(String.format("%s: %s\n%s", level, String.format(message, throwable), captureStackTrace(throwable)));
}
}
@Override
public void log(@NotNull SentryLevel level, @Nullable Throwable throwable, @NotNull String message, @Nullable Object... args) {
if (throwable == null) {
log(level, message, args);
} else {
IrisLogging.msg(String.format("%s: %s\n%s", level, String.format(message, throwable), captureStackTrace(throwable)));
}
}
@Override
public boolean isEnabled(@Nullable SentryLevel level) {
return true;
}
private @NotNull String captureStackTrace(@NotNull Throwable throwable) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
throwable.printStackTrace(printWriter);
return stringWriter.toString();
}
}
@@ -1,65 +0,0 @@
package art.arcane.iris.util.project.sentry;
import art.arcane.volmlib.util.io.IO;
import io.sentry.protocol.User;
import lombok.SneakyThrows;
import org.bukkit.Bukkit;
import oshi.SystemInfo;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class ServerID {
private static final class Holder {
private static final String ID = calculate();
}
public static String getId() {
return Holder.ID;
}
public static User asUser() {
User u = new User();
u.setId(Holder.ID);
return u;
}
@SneakyThrows
private static String calculate() {
Digest md = new Digest();
md.update(System.getProperty("java.vm.name"));
md.update(System.getProperty("java.vm.version"));
md.update(new SystemInfo().getHardware().getProcessor().toString());
md.update(Runtime.getRuntime().maxMemory());
for (var p : Bukkit.getPluginManager().getPlugins()) {
md.update(p.getName());
}
return IO.bytesToHex(md.digest());
}
private static final class Digest {
private final MessageDigest md = MessageDigest.getInstance("SHA-256");
private final byte[] buffer = new byte[8];
private final ByteBuffer wrapped = ByteBuffer.wrap(buffer);
private Digest() throws NoSuchAlgorithmException {
}
public void update(String string) {
if (string == null) return;
md.update(string.getBytes(StandardCharsets.UTF_8));
}
public void update(long Long) {
wrapped.putLong(0, Long);
md.update(buffer, 0, 8);
}
public byte[] digest() {
return md.digest();
}
}
}
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Der Modrinth-Import ist nur unter Bukkit verfügbar; installiere diese Datapacks bei Bedarf manuell unter world/datapacks.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Der Modrinth-Import ist nur unter Bukkit verfügbar; installiere diese Datapacks bei Bedarf manuell unter world/datapacks.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Installierte Weltdatenpakete: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Installierte Weltdatenpakete: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Eine Testausnahme wurde an den Iris-Fehlerreporter gesendet (Sentry, falls aktiviert).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Netzwerk-Scan fehlgeschlagen: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Netzwerk-Scan fehlgeschlagen: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Es läuft bereits ein GoldenHash-Scan.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Es läuft bereits ein GoldenHash-Scan.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Die Datapack-ID (Ordnername) wird angezeigt von /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Die Datapack-ID (Ordnername) wird angezeigt von /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris-Weltverwaltung", "iris.director.commanddeveloper.director.iris_world_manager": "Iris-Weltverwaltung",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Anzahl geladener TectonicPlates abrufen", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Anzahl geladener TectonicPlates abrufen",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Eine Testausnahme an Sentry senden",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Generierte Blockausgabe eines festen Bereichs für Determinismus- und Identitätstests hashen", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Generierte Blockausgabe eines festen Bereichs für Determinismus- und Identitätstests hashen",
"iris.director.commanddeveloper.param.world_hash": "Die zu hashende Welt", "iris.director.commanddeveloper.param.world_hash": "Die zu hashende Welt",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Radius in Chunks um die Mitte", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Radius in Chunks um die Mitte",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Hilfen für Installation und Status von Welt-Datapacks", "iris.modded.help.entry.group.datapack": "Hilfen für Installation und Status von Welt-Datapacks",
"iris.modded.help.entry.group.structure": "Werkzeuge für Iris-Strukturindex, Informationen und Platzierung", "iris.modded.help.entry.group.structure": "Werkzeuge für Iris-Strukturindex, Informationen und Platzierung",
"iris.modded.help.entry.command.goldenhash": "Generieren Sie deterministische Block-Hashes für Paritätstests", "iris.modded.help.entry.command.goldenhash": "Generieren Sie deterministische Block-Hashes für Paritätstests",
"iris.modded.help.entry.group.developer": "Entwicklerdiagnostik: Sentry-Test, Netzwerkschnittstellen, Region-Datei-Scan", "iris.modded.help.entry.group.developer": "Entwicklerdiagnostik: Netzwerkschnittstellen und Region-Datei-Scan",
"iris.modded.help.entry.command.biome": "Ein Iris-Biom finden", "iris.modded.help.entry.command.biome": "Ein Iris-Biom finden",
"iris.modded.help.entry.command.region": "Eine Iris-Region finden", "iris.modded.help.entry.command.region": "Eine Iris-Region finden",
"iris.modded.help.entry.command.object": "Finden Sie eine Objektplatzierung", "iris.modded.help.entry.command.object": "Finden Sie eine Objektplatzierung",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Bukkit-Ablauf für den Strukturimport erklären", "iris.modded.help.entry.command.import": "Bukkit-Ablauf für den Strukturimport erklären",
"iris.modded.help.entry.command.capture": "Bukkit-Ablauf für die Strukturerfassung erklären", "iris.modded.help.entry.command.capture": "Bukkit-Ablauf für die Strukturerfassung erklären",
"iris.modded.help.entry.command.verify": "Erreichbarkeit nativer und Iris-Strukturen in der aktuellen Dimension anzeigen", "iris.modded.help.entry.command.verify": "Erreichbarkeit nativer und Iris-Strukturen in der aktuellen Dimension anzeigen",
"iris.modded.help.entry.command.sentry": "Eine Testausnahme an den Iris-Fehlerbericht senden",
"iris.modded.help.entry.command.network": "Liste der Netzwerkschnittstellen und ihrer Adressen", "iris.modded.help.entry.command.network": "Liste der Netzwerkschnittstellen und ihrer Adressen",
"iris.runtime.progress.finding_regions": "Regionen werden gesucht", "iris.runtime.progress.finding_regions": "Regionen werden gesucht",
"iris.runtime.progress.converting": "Umwandlung", "iris.runtime.progress.converting": "Umwandlung",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "La ingesta de Modrinth solo está disponible en Bukkit; instala estos datapacks manualmente en world/datapacks si es necesario.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "La ingesta de Modrinth solo está disponible en Bukkit; instala estos datapacks manualmente en world/datapacks si es necesario.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Datapacks del mundo instalados: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Datapacks del mundo instalados: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Se envió una excepción de prueba al sistema de informes de errores de Iris (Sentry si está habilitado).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "El escaneo de red falló: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "El escaneo de red falló: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Ya hay un análisis GoldenHash en curso.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Ya hay un análisis GoldenHash en curso.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "El id del datapack (nombre de carpeta) que muestra /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "El id del datapack (nombre de carpeta) que muestra /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Gestor de mundos de Iris", "iris.director.commanddeveloper.director.iris_world_manager": "Gestor de mundos de Iris",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Obtener el número de TectonicPlates cargadas", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Obtener el número de TectonicPlates cargadas",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Enviar una excepción de prueba a Sentry",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Calcular el hash de los bloques generados en un área fija para comprobar el determinismo y la identidad", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Calcular el hash de los bloques generados en un área fija para comprobar el determinismo y la identidad",
"iris.director.commanddeveloper.param.world_hash": "El mundo cuyo hash se calculará", "iris.director.commanddeveloper.param.world_hash": "El mundo cuyo hash se calculará",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Radio en chunks alrededor del centro", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Radio en chunks alrededor del centro",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Herramientas de instalación y estado de datapacks del mundo", "iris.modded.help.entry.group.datapack": "Herramientas de instalación y estado de datapacks del mundo",
"iris.modded.help.entry.group.structure": "Herramientas de índice, información y colocación de estructuras de Iris", "iris.modded.help.entry.group.structure": "Herramientas de índice, información y colocación de estructuras de Iris",
"iris.modded.help.entry.command.goldenhash": "Generar hashes de bloques deterministas para pruebas de paridad", "iris.modded.help.entry.command.goldenhash": "Generar hashes de bloques deterministas para pruebas de paridad",
"iris.modded.help.entry.group.developer": "Diagnósticos para desarrolladores: prueba de Sentry, interfaces de red y análisis de archivos de región", "iris.modded.help.entry.group.developer": "Diagnósticos para desarrolladores: interfaces de red y análisis de archivos de región",
"iris.modded.help.entry.command.biome": "Buscar un bioma de Iris", "iris.modded.help.entry.command.biome": "Buscar un bioma de Iris",
"iris.modded.help.entry.command.region": "Buscar una región de Iris", "iris.modded.help.entry.command.region": "Buscar una región de Iris",
"iris.modded.help.entry.command.object": "Buscar la colocación de un objeto", "iris.modded.help.entry.command.object": "Buscar la colocación de un objeto",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Explicar el flujo de importación de estructuras de Bukkit", "iris.modded.help.entry.command.import": "Explicar el flujo de importación de estructuras de Bukkit",
"iris.modded.help.entry.command.capture": "Explicar el flujo de captura de estructuras de Bukkit", "iris.modded.help.entry.command.capture": "Explicar el flujo de captura de estructuras de Bukkit",
"iris.modded.help.entry.command.verify": "Informar de la accesibilidad de estructuras nativas y de Iris en la dimensión actual", "iris.modded.help.entry.command.verify": "Informar de la accesibilidad de estructuras nativas y de Iris en la dimensión actual",
"iris.modded.help.entry.command.sentry": "Enviar una excepción de prueba al sistema de informes de errores de Iris",
"iris.modded.help.entry.command.network": "Listar las interfaces de red y sus direcciones", "iris.modded.help.entry.command.network": "Listar las interfaces de red y sus direcciones",
"iris.runtime.progress.finding_regions": "Buscando regiones", "iris.runtime.progress.finding_regions": "Buscando regiones",
"iris.runtime.progress.converting": "Convirtiendo", "iris.runtime.progress.converting": "Convirtiendo",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth ingest on Bukkit-vain; asenna nämä käsin world/datapacks tarvittaessa.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth ingest on Bukkit-vain; asenna nämä käsin world/datapacks tarvittaessa.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Asennetut maailman datapaketit: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Asennetut maailman datapaketit: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Lähetti testipoikkeuksen Iris virheilmoittaja (Sentry, jos käytössä).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Verkkoskannaus epäonnistui: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Verkkoskannaus epäonnistui: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Kultahaskanneri on jo käynnissä.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Kultahaskanneri on jo käynnissä.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Datapaketin tunniste (kansionimi) /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Datapaketin tunniste (kansionimi) /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Maailmanjohtaja", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Maailmanjohtaja",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Hae Ladattu TectonicPlates Lukumäärä", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Hae Ladattu TectonicPlates Lukumäärä",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Lähetä testipoikkeus vartijalle",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hashin tuottama lohkon tuotos kiinteällä alueella determinismi-/identiteettitestausta varten", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hashin tuottama lohkon tuotos kiinteällä alueella determinismi-/identiteettitestausta varten",
"iris.director.commanddeveloper.param.world_hash": "Maailma hasista", "iris.director.commanddeveloper.param.world_hash": "Maailma hasista",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Radius palasina keskellä", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Radius palasina keskellä",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "maailman datapaketin asennus- ja tilaapurit", "iris.modded.help.entry.group.datapack": "maailman datapaketin asennus- ja tilaapurit",
"iris.modded.help.entry.group.structure": "Iris rakenneindeksi, tiedot ja työvälineet", "iris.modded.help.entry.group.structure": "Iris rakenneindeksi, tiedot ja työvälineet",
"iris.modded.help.entry.command.goldenhash": "Luo deterministinen lohkon hashes pariteettitestaus", "iris.modded.help.entry.command.goldenhash": "Luo deterministinen lohkon hashes pariteettitestaus",
"iris.modded.help.entry.group.developer": "Kehittäjän diagnostiikka: Sentry-testi, verkkoliitännät, aluetiedostojen skannaus", "iris.modded.help.entry.group.developer": "Kehittäjän diagnostiikka: verkkoliitännät ja aluetiedostojen skannaus",
"iris.modded.help.entry.command.biome": "Etsi Iris bome", "iris.modded.help.entry.command.biome": "Etsi Iris bome",
"iris.modded.help.entry.command.region": "Etsi Iris alue", "iris.modded.help.entry.command.region": "Etsi Iris alue",
"iris.modded.help.entry.command.object": "Etsi kohteen sijoitus", "iris.modded.help.entry.command.object": "Etsi kohteen sijoitus",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Selitä Bukkit rakenteen mukainen työnkulku", "iris.modded.help.entry.command.import": "Selitä Bukkit rakenteen mukainen työnkulku",
"iris.modded.help.entry.command.capture": "Selitä Bukkit rakenteen kaappaustyövirta", "iris.modded.help.entry.command.capture": "Selitä Bukkit rakenteen kaappaustyövirta",
"iris.modded.help.entry.command.verify": "Ilmoita syntyperäinen ja Iris rakenteen saavutettavuus nykyisessä ulottuvuudessa", "iris.modded.help.entry.command.verify": "Ilmoita syntyperäinen ja Iris rakenteen saavutettavuus nykyisessä ulottuvuudessa",
"iris.modded.help.entry.command.sentry": "Lähetä testi poikkeus Iris virheraportointi",
"iris.modded.help.entry.command.network": "Listaa verkkoliittymät ja niiden osoitteet", "iris.modded.help.entry.command.network": "Listaa verkkoliittymät ja niiden osoitteet",
"iris.runtime.progress.finding_regions": "Alueet", "iris.runtime.progress.finding_regions": "Alueet",
"iris.runtime.progress.converting": "Muunnetaan", "iris.runtime.progress.converting": "Muunnetaan",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "L'ingestion Modrinth est réservée à Bukkit ; installez ces datapacks manuellement dans world/datapacks si nécessaire.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "L'ingestion Modrinth est réservée à Bukkit ; installez ces datapacks manuellement dans world/datapacks si nécessaire.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Datapacks du monde installés : {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Datapacks du monde installés : {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Une exception de test a été envoyée au système de rapports d'erreurs Iris (Sentry s'il est activé).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "La numérisation réseau a échoué : {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "La numérisation réseau a échoué : {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Une analyse GoldenHash est déjà en cours.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Une analyse GoldenHash est déjà en cours.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "L'id du datapack (nom du dossier) affiché par /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "L'id du datapack (nom du dossier) affiché par /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Gestionnaire de mondes Iris", "iris.director.commanddeveloper.director.iris_world_manager": "Gestionnaire de mondes Iris",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Obtenir le nombre de TectonicPlates chargées", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Obtenir le nombre de TectonicPlates chargées",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Envoyer une exception de test à Sentry",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Calculer le hash des blocs générés dans une zone fixe afin de tester le déterminisme et l'identité", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Calculer le hash des blocs générés dans une zone fixe afin de tester le déterminisme et l'identité",
"iris.director.commanddeveloper.param.world_hash": "Le monde dont le hash sera calculé", "iris.director.commanddeveloper.param.world_hash": "Le monde dont le hash sera calculé",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Rayon en chunks autour du centre", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Rayon en chunks autour du centre",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Outils d'installation et d'état des datapacks du monde", "iris.modded.help.entry.group.datapack": "Outils d'installation et d'état des datapacks du monde",
"iris.modded.help.entry.group.structure": "Outils d'index, d'informations et de placement des structures Iris", "iris.modded.help.entry.group.structure": "Outils d'index, d'informations et de placement des structures Iris",
"iris.modded.help.entry.command.goldenhash": "Générer des hashes de blocs déterministes pour les tests de parité", "iris.modded.help.entry.command.goldenhash": "Générer des hashes de blocs déterministes pour les tests de parité",
"iris.modded.help.entry.group.developer": "Diagnostics développeur : test Sentry, interfaces réseau et analyse des fichiers de région", "iris.modded.help.entry.group.developer": "Diagnostics développeur : interfaces réseau et analyse des fichiers de région",
"iris.modded.help.entry.command.biome": "Rechercher un biome Iris", "iris.modded.help.entry.command.biome": "Rechercher un biome Iris",
"iris.modded.help.entry.command.region": "Rechercher une région Iris", "iris.modded.help.entry.command.region": "Rechercher une région Iris",
"iris.modded.help.entry.command.object": "Rechercher le placement d'un objet", "iris.modded.help.entry.command.object": "Rechercher le placement d'un objet",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Expliquer le flux d'importation des structures Bukkit", "iris.modded.help.entry.command.import": "Expliquer le flux d'importation des structures Bukkit",
"iris.modded.help.entry.command.capture": "Expliquer le flux de capture des structures Bukkit", "iris.modded.help.entry.command.capture": "Expliquer le flux de capture des structures Bukkit",
"iris.modded.help.entry.command.verify": "Afficher l'accessibilité des structures natives et Iris dans la dimension actuelle", "iris.modded.help.entry.command.verify": "Afficher l'accessibilité des structures natives et Iris dans la dimension actuelle",
"iris.modded.help.entry.command.sentry": "Envoyer une exception de test au rapporteur d'erreurs Iris",
"iris.modded.help.entry.command.network": "Lister les interfaces réseau et leurs adresses", "iris.modded.help.entry.command.network": "Lister les interfaces réseau et leurs adresses",
"iris.runtime.progress.finding_regions": "Recherche des régions", "iris.runtime.progress.finding_regions": "Recherche des régions",
"iris.runtime.progress.converting": "Conversion", "iris.runtime.progress.converting": "Conversion",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth טעינה Bukkit- רק; להתקין אותם באופן ידני world/datapacks אם צריך.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth טעינה Bukkit- רק; להתקין אותם באופן ידני world/datapacks אם צריך.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "התקנת חבילות נתונים עולמיות: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "התקנת חבילות נתונים עולמיות: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "נשלחה חריגת בדיקה אל מדווח השגיאות של Iris (Sentry אם מופעל).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "סריקות רשת נכשלות: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "סריקות רשת נכשלות: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "סריקת זהב כבר פועלת.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "סריקת זהב כבר פועלת.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "חבילת הנתונים id (שם כפול) מוצג על ידי /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "חבילת הנתונים id (שם כפול) מוצג על ידי /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris מנהל עולמי", "iris.director.commanddeveloper.director.iris_world_manager": "Iris מנהל עולמי",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "קבל טעון TectonicPlates הרוזן", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "קבל טעון TectonicPlates הרוזן",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "שלח יוצא מן הבחינה לשולח",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "האש יצרה פלט בלוק של אזור קבוע עבור בדיקות determin / זהות", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "האש יצרה פלט בלוק של אזור קבוע עבור בדיקות determin / זהות",
"iris.director.commanddeveloper.param.world_hash": "העולם שיש", "iris.director.commanddeveloper.param.world_hash": "העולם שיש",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "רדינוס בחלקים סביב המרכז", "iris.director.commanddeveloper.param.radius_chunks_around_center": "רדינוס בחלקים סביב המרכז",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "חבילת נתונים עולמית להתקין ועוזרי סטטוס", "iris.modded.help.entry.group.datapack": "חבילת נתונים עולמית להתקין ועוזרי סטטוס",
"iris.modded.help.entry.group.structure": "Iris מדד מבנה, מידע וכלי מיקום", "iris.modded.help.entry.group.structure": "Iris מדד מבנה, מידע וכלי מיקום",
"iris.modded.help.entry.command.goldenhash": "לייצר בלוק determins עבור מבחן תאימות", "iris.modded.help.entry.command.goldenhash": "לייצר בלוק determins עבור מבחן תאימות",
"iris.modded.help.entry.group.developer": "אבחון למפתחים: בדיקת Sentry, ממשקי רשת וסריקת קובצי אזור", "iris.modded.help.entry.group.developer": "אבחון למפתחים: ממשקי רשת וסריקת קובצי אזור",
"iris.modded.help.entry.command.biome": "מצא Iris ביו", "iris.modded.help.entry.command.biome": "מצא Iris ביו",
"iris.modded.help.entry.command.region": "מצא Iris האזור האזורי", "iris.modded.help.entry.command.region": "מצא Iris האזור האזורי",
"iris.modded.help.entry.command.object": "מצא מיקום אובייקט", "iris.modded.help.entry.command.object": "מצא מיקום אובייקט",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "להסביר Bukkit ייבוא תהליך עבודה", "iris.modded.help.entry.command.import": "להסביר Bukkit ייבוא תהליך עבודה",
"iris.modded.help.entry.command.capture": "להסביר Bukkit מבנה לכידת עבודה", "iris.modded.help.entry.command.capture": "להסביר Bukkit מבנה לכידת עבודה",
"iris.modded.help.entry.command.verify": "דו\"ח Native ו- Iris מגיע לשיאות במימד הנוכחי", "iris.modded.help.entry.command.verify": "דו\"ח Native ו- Iris מגיע לשיאות במימד הנוכחי",
"iris.modded.help.entry.command.sentry": "שלח יוצא דופן במבחן Iris עיתונאי טעות",
"iris.modded.help.entry.command.network": "ממשקי רשת וכתובות", "iris.modded.help.entry.command.network": "ממשקי רשת וכתובות",
"iris.runtime.progress.finding_regions": "מציאת אזורים", "iris.runtime.progress.finding_regions": "מציאת אזורים",
"iris.runtime.progress.converting": "המרת", "iris.runtime.progress.converting": "המרת",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "L'importazione da Modrinth è disponibile solo su Bukkit; se necessario, installa manualmente questi datapack in world/datapacks.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "L'importazione da Modrinth è disponibile solo su Bukkit; se necessario, installa manualmente questi datapack in world/datapacks.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Datapack installati nel mondo: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Datapack installati nel mondo: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "È stata inviata un'eccezione di prova al sistema di segnalazione errori di Iris (Sentry se abilitato).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "La scansione di rete non è riuscita: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "La scansione di rete non è riuscita: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "È già in esecuzione una scansione GoldenHash.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "È già in esecuzione una scansione GoldenHash.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Il datapack id (nome della cartella) indicato da /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Il datapack id (nome della cartella) indicato da /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Gestore dei mondi Iris", "iris.director.commanddeveloper.director.iris_world_manager": "Gestore dei mondi Iris",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Ottieni il numero di TectonicPlates caricate", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Ottieni il numero di TectonicPlates caricate",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Invia un'eccezione di prova a Sentry",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Calcola l'hash dei blocchi generati in un'area fissa per test di determinismo e identità", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Calcola l'hash dei blocchi generati in un'area fissa per test di determinismo e identità",
"iris.director.commanddeveloper.param.world_hash": "Il mondo di cui calcolare l'hash", "iris.director.commanddeveloper.param.world_hash": "Il mondo di cui calcolare l'hash",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Radio in chunk intorno al centro", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Radio in chunk intorno al centro",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Installazione e stato dei datapack del mondo", "iris.modded.help.entry.group.datapack": "Installazione e stato dei datapack del mondo",
"iris.modded.help.entry.group.structure": "Iris struttura indice, info e strumenti di posizionamento", "iris.modded.help.entry.group.structure": "Iris struttura indice, info e strumenti di posizionamento",
"iris.modded.help.entry.command.goldenhash": "Genera blocchi deterministici per prove di parità", "iris.modded.help.entry.command.goldenhash": "Genera blocchi deterministici per prove di parità",
"iris.modded.help.entry.group.developer": "Diagnostica degli sviluppatori: Test di Sentry, interfacce di rete, scansione dei file regionali", "iris.modded.help.entry.group.developer": "Diagnostica degli sviluppatori: interfacce di rete e scansione dei file regionali",
"iris.modded.help.entry.command.biome": "Trova un bioma Iris", "iris.modded.help.entry.command.biome": "Trova un bioma Iris",
"iris.modded.help.entry.command.region": "Trova una regione Iris", "iris.modded.help.entry.command.region": "Trova una regione Iris",
"iris.modded.help.entry.command.object": "Trova un posizionamento degli oggetti", "iris.modded.help.entry.command.object": "Trova un posizionamento degli oggetti",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Spiega il flusso Bukkit per l'importazione delle strutture", "iris.modded.help.entry.command.import": "Spiega il flusso Bukkit per l'importazione delle strutture",
"iris.modded.help.entry.command.capture": "Spiega il flusso Bukkit per l'acquisizione delle strutture", "iris.modded.help.entry.command.capture": "Spiega il flusso Bukkit per l'acquisizione delle strutture",
"iris.modded.help.entry.command.verify": "Mostra la raggiungibilità delle strutture native e Iris nella dimensione corrente", "iris.modded.help.entry.command.verify": "Mostra la raggiungibilità delle strutture native e Iris nella dimensione corrente",
"iris.modded.help.entry.command.sentry": "Invia un'eccezione di prova al sistema di segnalazione errori Iris",
"iris.modded.help.entry.command.network": "Elenca le interfacce di rete e i loro indirizzi", "iris.modded.help.entry.command.network": "Elenca le interfacce di rete e i loro indirizzi",
"iris.runtime.progress.finding_regions": "Ricerca delle regioni", "iris.runtime.progress.finding_regions": "Ricerca delle regioni",
"iris.runtime.progress.converting": "Conversione", "iris.runtime.progress.converting": "Conversione",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth の取り込みは Bukkit 専用です。必要に応じて world/datapacks に手動でインストールしてください。", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth の取り込みは Bukkit 専用です。必要に応じて world/datapacks に手動でインストールしてください。",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "インストール済みのワールドデータパック: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "インストール済みのワールドデータパック: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "テスト例外を Iris のエラーレポーターに送信しました(有効な場合は Sentry)。",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "ネットワークスキャン失敗: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "ネットワークスキャン失敗: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "GoldenHash スキャンはすでに実行中です。", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "GoldenHash スキャンはすでに実行中です。",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "/iris datapack list に表示されるデータパック ID(フォルダー名)", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "/iris datapack list に表示されるデータパック ID(フォルダー名)",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris ワールドマネージャー", "iris.director.commanddeveloper.director.iris_world_manager": "Iris ワールドマネージャー",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "読み込み済み TectonicPlates の数を取得します", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "読み込み済み TectonicPlates の数を取得します",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Sentry へテスト例外を送信します",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "固定範囲で生成されたブロック出力をハッシュ化し、決定性と一致性を検証します", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "固定範囲で生成されたブロック出力をハッシュ化し、決定性と一致性を検証します",
"iris.director.commanddeveloper.param.world_hash": "ハッシュ化するワールド", "iris.director.commanddeveloper.param.world_hash": "ハッシュ化するワールド",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "中心からの半径(チャンク単位)", "iris.director.commanddeveloper.param.radius_chunks_around_center": "中心からの半径(チャンク単位)",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "ワールドデータパックのインストールと状態確認を支援します", "iris.modded.help.entry.group.datapack": "ワールドデータパックのインストールと状態確認を支援します",
"iris.modded.help.entry.group.structure": "Iris 構造物のインデックス、情報、配置ツールです", "iris.modded.help.entry.group.structure": "Iris 構造物のインデックス、情報、配置ツールです",
"iris.modded.help.entry.command.goldenhash": "互換性テスト用に決定論的なブロックハッシュを生成します", "iris.modded.help.entry.command.goldenhash": "互換性テスト用に決定論的なブロックハッシュを生成します",
"iris.modded.help.entry.group.developer": "開発者の診断: Sentryテスト、ネットワーク インターフェイス、地域 ファイル スキャン", "iris.modded.help.entry.group.developer": "開発者診断: ネットワークインターフェースとリージョンファイルのスキャン",
"iris.modded.help.entry.command.biome": "Iris バイオームを検索します", "iris.modded.help.entry.command.biome": "Iris バイオームを検索します",
"iris.modded.help.entry.command.region": "Iris リージョンを検索します", "iris.modded.help.entry.command.region": "Iris リージョンを検索します",
"iris.modded.help.entry.command.object": "オブジェクト配置を検索します", "iris.modded.help.entry.command.object": "オブジェクト配置を検索します",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Bukkit の構造物インポート手順を説明します", "iris.modded.help.entry.command.import": "Bukkit の構造物インポート手順を説明します",
"iris.modded.help.entry.command.capture": "Bukkit の構造物キャプチャ手順を説明します", "iris.modded.help.entry.command.capture": "Bukkit の構造物キャプチャ手順を説明します",
"iris.modded.help.entry.command.verify": "現在のディメンションでネイティブ構造物と Iris 構造物が到達可能か報告します", "iris.modded.help.entry.command.verify": "現在のディメンションでネイティブ構造物と Iris 構造物が到達可能か報告します",
"iris.modded.help.entry.command.sentry": "Iris エラーレポーターへテスト例外を送信します",
"iris.modded.help.entry.command.network": "ネットワークインターフェースとアドレスを一覧表示します", "iris.modded.help.entry.command.network": "ネットワークインターフェースとアドレスを一覧表示します",
"iris.runtime.progress.finding_regions": "リージョンを検索中", "iris.runtime.progress.finding_regions": "リージョンを検索中",
"iris.runtime.progress.converting": "変換中", "iris.runtime.progress.converting": "変換中",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth 수집는 Bukkit-만; 수동으로 설치 world/datapacks 필요한 경우.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth 수집는 Bukkit-만; 수동으로 설치 world/datapacks 필요한 경우.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "설치된 세계 데이터 팩: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "설치된 세계 데이터 팩: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "테스트 예외를 Iris 오류 보고기로 전송했습니다(Sentry가 활성화된 경우).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "네트워크 검사 실패: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "네트워크 검사 실패: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "황금빛 검사는 이미 달리고 있습니다.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "황금빛 검사는 이미 달리고 있습니다.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "/iris datapack list에 표시되는 데이터 팩 ID(폴더 이름)", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "/iris datapack list에 표시되는 데이터 팩 ID(폴더 이름)",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris 월드 관리자", "iris.director.commanddeveloper.director.iris_world_manager": "Iris 월드 관리자",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "로드된 TectonicPlates 수를 가져옵니다", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "로드된 TectonicPlates 수를 가져옵니다",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Sentry로 테스트 예외를 보냅니다",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "고정 영역의 생성 블록 출력을 해시해 결정성과 일치성을 검사합니다", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "고정 영역의 생성 블록 출력을 해시해 결정성과 일치성을 검사합니다",
"iris.director.commanddeveloper.param.world_hash": "해시할 월드", "iris.director.commanddeveloper.param.world_hash": "해시할 월드",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "중심 기준 반경(청크 단위)", "iris.director.commanddeveloper.param.radius_chunks_around_center": "중심 기준 반경(청크 단위)",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "월드 데이터 팩 설치와 상태 확인 도구입니다", "iris.modded.help.entry.group.datapack": "월드 데이터 팩 설치와 상태 확인 도구입니다",
"iris.modded.help.entry.group.structure": "Iris 구조물 인덱스, 정보, 배치 도구입니다", "iris.modded.help.entry.group.structure": "Iris 구조물 인덱스, 정보, 배치 도구입니다",
"iris.modded.help.entry.command.goldenhash": "동일성 검사용 결정적 블록 해시를 생성합니다", "iris.modded.help.entry.command.goldenhash": "동일성 검사용 결정적 블록 해시를 생성합니다",
"iris.modded.help.entry.group.developer": "개발자 진단: Sentry 테스트, 네트워크 인터페이스, 리전 파일 검사", "iris.modded.help.entry.group.developer": "개발자 진단: 네트워크 인터페이스와 리전 파일 검사",
"iris.modded.help.entry.command.biome": "Iris 바이옴을 찾습니다", "iris.modded.help.entry.command.biome": "Iris 바이옴을 찾습니다",
"iris.modded.help.entry.command.region": "Iris 리전을 찾습니다", "iris.modded.help.entry.command.region": "Iris 리전을 찾습니다",
"iris.modded.help.entry.command.object": "오브젝트 배치를 찾습니다", "iris.modded.help.entry.command.object": "오브젝트 배치를 찾습니다",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Bukkit 구조물 가져오기 절차를 설명합니다", "iris.modded.help.entry.command.import": "Bukkit 구조물 가져오기 절차를 설명합니다",
"iris.modded.help.entry.command.capture": "Bukkit 구조물 캡처 절차를 설명합니다", "iris.modded.help.entry.command.capture": "Bukkit 구조물 캡처 절차를 설명합니다",
"iris.modded.help.entry.command.verify": "현재 차원의 네이티브 및 Iris 구조물 도달 가능성을 보고합니다", "iris.modded.help.entry.command.verify": "현재 차원의 네이티브 및 Iris 구조물 도달 가능성을 보고합니다",
"iris.modded.help.entry.command.sentry": "Iris 오류 보고기로 테스트 예외를 보냅니다",
"iris.modded.help.entry.command.network": "네트워크 인터페이스와 주소를 나열합니다", "iris.modded.help.entry.command.network": "네트워크 인터페이스와 주소를 나열합니다",
"iris.runtime.progress.finding_regions": "지역 찾기", "iris.runtime.progress.finding_regions": "지역 찾기",
"iris.runtime.progress.converting": "변환 중", "iris.runtime.progress.converting": "변환 중",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth vartoti Bukkit-tik; įdiegti šiuos rankiniu būdu į world/datapacks jei reikia.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth vartoti Bukkit-tik; įdiegti šiuos rankiniu būdu į world/datapacks jei reikia.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Įdiegti pasauliniai duomenys: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Įdiegti pasauliniai duomenys: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Bandomoji išimtis išsiųsta į Iris klaidų pranešimų sistemą (Sentry, jei įjungta).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Tinklo skenavimas nepavyko: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Tinklo skenavimas nepavyko: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Auksinis skenavimas jau veikia.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Auksinis skenavimas jau veikia.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Datapack id (aplanko pavadinimas) rodo /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Datapack id (aplanko pavadinimas) rodo /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Pasaulio vadybininkas", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Pasaulio vadybininkas",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Įkelti TectonicPlates Skaičius", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Įkelti TectonicPlates Skaičius",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Siųsti bandymo išimtį Sentry",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Stacionarios zonos sukauptas bloko išvestis determinizmui / tapatumo bandymams", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Stacionarios zonos sukauptas bloko išvestis determinizmui / tapatumo bandymams",
"iris.director.commanddeveloper.param.world_hash": "Pasaulis, kuriam reikia maišyti", "iris.director.commanddeveloper.param.world_hash": "Pasaulis, kuriam reikia maišyti",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Spindulys į gabaliukus aplink centrą", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Spindulys į gabaliukus aplink centrą",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "World datapack įdiegti ir būsenos pagalbininkai", "iris.modded.help.entry.group.datapack": "World datapack įdiegti ir būsenos pagalbininkai",
"iris.modded.help.entry.group.structure": "Iris struktūros indeksas, informacija ir diegimo įrankiai", "iris.modded.help.entry.group.structure": "Iris struktūros indeksas, informacija ir diegimo įrankiai",
"iris.modded.help.entry.command.goldenhash": "Sugeneruoti deterministinius bloko smūgius pariteto bandymams", "iris.modded.help.entry.command.goldenhash": "Sugeneruoti deterministinius bloko smūgius pariteto bandymams",
"iris.modded.help.entry.group.developer": "Kūrėjo diagnostika: Sentry testas, tinklo sąsajos, regionų failų nuskaitymas", "iris.modded.help.entry.group.developer": "Kūrėjo diagnostika: tinklo sąsajos ir regionų failų nuskaitymas",
"iris.modded.help.entry.command.biome": "Rasti Iris biomas", "iris.modded.help.entry.command.biome": "Rasti Iris biomas",
"iris.modded.help.entry.command.region": "Rasti Iris regionas", "iris.modded.help.entry.command.region": "Rasti Iris regionas",
"iris.modded.help.entry.command.object": "Rasti objekto vietą", "iris.modded.help.entry.command.object": "Rasti objekto vietą",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Paaiškinti Bukkit struktūra importo darbo eiga", "iris.modded.help.entry.command.import": "Paaiškinti Bukkit struktūra importo darbo eiga",
"iris.modded.help.entry.command.capture": "Paaiškinti Bukkit struktūros surinkimo darbų srautas", "iris.modded.help.entry.command.capture": "Paaiškinti Bukkit struktūros surinkimo darbų srautas",
"iris.modded.help.entry.command.verify": "Pranešti vietos ir Iris struktūros pasiekiamumas dabartiniame matmenyje", "iris.modded.help.entry.command.verify": "Pranešti vietos ir Iris struktūros pasiekiamumas dabartiniame matmenyje",
"iris.modded.help.entry.command.sentry": "Siųsti bandymo išimtį Iris klaidų reporteris",
"iris.modded.help.entry.command.network": "Išvardyti tinklo sąsajas ir jų adresus", "iris.modded.help.entry.command.network": "Išvardyti tinklo sąsajas ir jų adresus",
"iris.runtime.progress.finding_regions": "Ieškomi regionai", "iris.runtime.progress.finding_regions": "Ieškomi regionai",
"iris.runtime.progress.converting": "Konvertuojama", "iris.runtime.progress.converting": "Konvertuojama",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth Inname is Bukkit-alleen; installeer deze handmatig in world/datapacks indien nodig.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth Inname is Bukkit-alleen; installeer deze handmatig in world/datapacks indien nodig.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Geïnstalleerde werelddatapacks: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Geïnstalleerde werelddatapacks: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Een testuitzondering is naar de Iris-foutrapportage verzonden (Sentry indien ingeschakeld).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Netwerkscan mislukt: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Netwerkscan mislukt: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Een Goldenhash scan loopt al.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Een Goldenhash scan loopt al.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Het datapack id (mapnaam) getoond door /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Het datapack id (mapnaam) getoond door /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Wereldmanager", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Wereldmanager",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Laden TectonicPlates Aantal", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Laden TectonicPlates Aantal",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Stuur een test uitzondering naar de wachtdienst",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hash gegenereerde blokuitgang van een vaste zone voor determinisme/identiteitstest", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hash gegenereerde blokuitgang van een vaste zone voor determinisme/identiteitstest",
"iris.director.commanddeveloper.param.world_hash": "De wereld te hash", "iris.director.commanddeveloper.param.world_hash": "De wereld te hash",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Straal in stukjes rond het centrum", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Straal in stukjes rond het centrum",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "World Datapack installatie en status helpers", "iris.modded.help.entry.group.datapack": "World Datapack installatie en status helpers",
"iris.modded.help.entry.group.structure": "Iris structuurindex, info- en plaatsingsinstrumenten", "iris.modded.help.entry.group.structure": "Iris structuurindex, info- en plaatsingsinstrumenten",
"iris.modded.help.entry.command.goldenhash": "Genereer deterministische blokhashes voor pariteitstests", "iris.modded.help.entry.command.goldenhash": "Genereer deterministische blokhashes voor pariteitstests",
"iris.modded.help.entry.group.developer": "Ontwikkelaardiagnostiek: Sentry test, netwerk interfaces, regio-bestand scan", "iris.modded.help.entry.group.developer": "Ontwikkelaardiagnostiek: netwerkinterfaces en regio-bestandsscan",
"iris.modded.help.entry.command.biome": "Zoek een Iris biom", "iris.modded.help.entry.command.biome": "Zoek een Iris biom",
"iris.modded.help.entry.command.region": "Zoek een Iris regio", "iris.modded.help.entry.command.region": "Zoek een Iris regio",
"iris.modded.help.entry.command.object": "Een objectplaatsing zoeken", "iris.modded.help.entry.command.object": "Een objectplaatsing zoeken",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Leg uit Bukkit structuur import workflow", "iris.modded.help.entry.command.import": "Leg uit Bukkit structuur import workflow",
"iris.modded.help.entry.command.capture": "Leg uit Bukkit structuur capture workflow", "iris.modded.help.entry.command.capture": "Leg uit Bukkit structuur capture workflow",
"iris.modded.help.entry.command.verify": "Native en Iris Bereikbaarheid van de structuur in de huidige dimensie", "iris.modded.help.entry.command.verify": "Native en Iris Bereikbaarheid van de structuur in de huidige dimensie",
"iris.modded.help.entry.command.sentry": "Stuur een testuitzondering naar de Iris foutverslaggever",
"iris.modded.help.entry.command.network": "Lijst van netwerkinterfaces en hun adressen", "iris.modded.help.entry.command.network": "Lijst van netwerkinterfaces en hun adressen",
"iris.runtime.progress.finding_regions": "Regio's vinden", "iris.runtime.progress.finding_regions": "Regio's vinden",
"iris.runtime.progress.converting": "Converteren", "iris.runtime.progress.converting": "Converteren",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth jeśli Bukkit-tylko; zainstalować je ręcznie world/datapacks w razie potrzeby.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth jeśli Bukkit-tylko; zainstalować je ręcznie world/datapacks w razie potrzeby.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Zainstalowane world datapacks: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Zainstalowane world datapacks: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Wysłano wyjątek testowy do systemu raportowania błędów Iris (Sentry, jeśli jest włączony).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Skanowanie sieci nie powiodło się: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Skanowanie sieci nie powiodło się: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Skaner już działa.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Skaner już działa.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Identyfikator datapack (nazwa folderu) pokazany przez /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Identyfikator datapack (nazwa folderu) pokazany przez /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Światowy menedżer", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Światowy menedżer",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Napełnij TectonicPlates Licz", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Napełnij TectonicPlates Licz",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Wyślij wyjątek testowy do wartownika",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Wygenerowane przez Hasha wyjście blokowe stałego obszaru do celów badania determinizmu / tożsamości", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Wygenerowane przez Hasha wyjście blokowe stałego obszaru do celów badania determinizmu / tożsamości",
"iris.director.commanddeveloper.param.world_hash": "Świat, by się zahaczyć", "iris.director.commanddeveloper.param.world_hash": "Świat, by się zahaczyć",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Promień w chunkach wokół centrum", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Promień w chunkach wokół centrum",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Narzędzia instalacji i stanu datapacków świata", "iris.modded.help.entry.group.datapack": "Narzędzia instalacji i stanu datapacków świata",
"iris.modded.help.entry.group.structure": "Iris indeks struktury, narzędzia informacyjne i umieszczania", "iris.modded.help.entry.group.structure": "Iris indeks struktury, narzędzia informacyjne i umieszczania",
"iris.modded.help.entry.command.goldenhash": "Generowanie hash bloku deterministycznego do badania parytetu", "iris.modded.help.entry.command.goldenhash": "Generowanie hash bloku deterministycznego do badania parytetu",
"iris.modded.help.entry.group.developer": "Diagnostyka deweloperska: test Sentry, interfejsy sieciowe, skan plików regionów", "iris.modded.help.entry.group.developer": "Diagnostyka deweloperska: interfejsy sieciowe i skan plików regionów",
"iris.modded.help.entry.command.biome": "Znajdź Iris biom", "iris.modded.help.entry.command.biome": "Znajdź Iris biom",
"iris.modded.help.entry.command.region": "Znajdź Iris regiony", "iris.modded.help.entry.command.region": "Znajdź Iris regiony",
"iris.modded.help.entry.command.object": "Znajdź lokalizację obiektu", "iris.modded.help.entry.command.object": "Znajdź lokalizację obiektu",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Wyjaśnij Bukkit struktura importu pracy", "iris.modded.help.entry.command.import": "Wyjaśnij Bukkit struktura importu pracy",
"iris.modded.help.entry.command.capture": "Wyjaśnij Bukkit structure catch workflow", "iris.modded.help.entry.command.capture": "Wyjaśnij Bukkit structure catch workflow",
"iris.modded.help.entry.command.verify": "Zgłoś rodzime i Iris stabilność struktury w obecnym wymiarze", "iris.modded.help.entry.command.verify": "Zgłoś rodzime i Iris stabilność struktury w obecnym wymiarze",
"iris.modded.help.entry.command.sentry": "Wyślij wyjątek testowy do Iris zgłaszający błędy",
"iris.modded.help.entry.command.network": "Lista interfejsów sieciowych i ich adresów", "iris.modded.help.entry.command.network": "Lista interfejsów sieciowych i ich adresów",
"iris.runtime.progress.finding_regions": "Znalezienie regionów", "iris.runtime.progress.finding_regions": "Znalezienie regionów",
"iris.runtime.progress.converting": "Konwersja", "iris.runtime.progress.converting": "Konwersja",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth ingerir é Bukkit- somente; instale estes manualmente em world/datapacks se necessário.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth ingerir é Bukkit- somente; instale estes manualmente em world/datapacks se necessário.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Pacotes de dados mundiais instalados: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Pacotes de dados mundiais instalados: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Foi enviada uma exceção de teste para o sistema de relatórios de erros do Iris (Sentry, se estiver ativado).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Falha na verificação da rede: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Falha na verificação da rede: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Já está a ser feito um exame ao Goldenhash.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Já está a ser feito um exame ao Goldenhash.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "O ID do pacote de dados (nome da pasta) mostrado por /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "O ID do pacote de dados (nome da pasta) mostrado por /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Gestor Mundial", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Gestor Mundial",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Obter Carregado TectonicPlates Contagem", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Obter Carregado TectonicPlates Contagem",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Enviar uma exceção de teste para o sentinela",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Saída de bloco gerada por hash de uma área fixa para testes de determinismo/identidade", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Saída de bloco gerada por hash de uma área fixa para testes de determinismo/identidade",
"iris.director.commanddeveloper.param.world_hash": "O mundo para hash", "iris.director.commanddeveloper.param.world_hash": "O mundo para hash",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Raio em chunks ao redor do centro", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Raio em chunks ao redor do centro",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Mundial datapack install e status helpers", "iris.modded.help.entry.group.datapack": "Mundial datapack install e status helpers",
"iris.modded.help.entry.group.structure": "Iris índice de estrutura, informações e ferramentas de colocação", "iris.modded.help.entry.group.structure": "Iris índice de estrutura, informações e ferramentas de colocação",
"iris.modded.help.entry.command.goldenhash": "Gerar hashes de blocos determinísticos para testes de paridade", "iris.modded.help.entry.command.goldenhash": "Gerar hashes de blocos determinísticos para testes de paridade",
"iris.modded.help.entry.group.developer": "Diagnóstico de programador: teste do Sentry, interfaces de rede e análise de ficheiros de região", "iris.modded.help.entry.group.developer": "Diagnóstico de programador: interfaces de rede e análise de ficheiros de região",
"iris.modded.help.entry.command.biome": "Procurar um Iris bioma", "iris.modded.help.entry.command.biome": "Procurar um Iris bioma",
"iris.modded.help.entry.command.region": "Procurar um Iris região", "iris.modded.help.entry.command.region": "Procurar um Iris região",
"iris.modded.help.entry.command.object": "Encontrar uma colocação de objeto", "iris.modded.help.entry.command.object": "Encontrar uma colocação de objeto",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Explicar Bukkit workflow de importação da estrutura", "iris.modded.help.entry.command.import": "Explicar Bukkit workflow de importação da estrutura",
"iris.modded.help.entry.command.capture": "Explicar Bukkit workflow de captura da estrutura", "iris.modded.help.entry.command.capture": "Explicar Bukkit workflow de captura da estrutura",
"iris.modded.help.entry.command.verify": "Relatório nativo e Iris capacidade de alcance da estrutura na dimensão atual", "iris.modded.help.entry.command.verify": "Relatório nativo e Iris capacidade de alcance da estrutura na dimensão atual",
"iris.modded.help.entry.command.sentry": "Enviar uma excepção de teste para o Iris repórter de erro",
"iris.modded.help.entry.command.network": "Listar as interfaces de rede e os seus endereços", "iris.modded.help.entry.command.network": "Listar as interfaces de rede e os seus endereços",
"iris.runtime.progress.finding_regions": "Regiões de pesquisa", "iris.runtime.progress.finding_regions": "Regiões de pesquisa",
"iris.runtime.progress.converting": "Conversão", "iris.runtime.progress.converting": "Conversão",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth глотать - это Bukkit-только; установить эти вручную в world/datapacks при необходимости.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth глотать - это Bukkit-только; установить эти вручную в world/datapacks при необходимости.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Установка мировых пакетов данных: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Установка мировых пакетов данных: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Тестовое исключение отправлено в систему отчётов об ошибках Iris (Sentry, если включён).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Сканирование сети не удалось: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Сканирование сети не удалось: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Сканирование Goldhash уже запущено.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Сканирование Goldhash уже запущено.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "ID пакета данных (название папки), показанный /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "ID пакета данных (название папки), показанный /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Мировой менеджер", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Мировой менеджер",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Заряжайся TectonicPlates граф", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Заряжайся TectonicPlates граф",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Отправить тестовое исключение для часового",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hash генерируется блок выход фиксированной области для детерминизма/идентификации тестирования", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hash генерируется блок выход фиксированной области для детерминизма/идентификации тестирования",
"iris.director.commanddeveloper.param.world_hash": "Мир для хеширования", "iris.director.commanddeveloper.param.world_hash": "Мир для хеширования",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Радиус в чанках вокруг центра", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Радиус в чанках вокруг центра",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Установка Мировой пакет данных и статус помощников", "iris.modded.help.entry.group.datapack": "Установка Мировой пакет данных и статус помощников",
"iris.modded.help.entry.group.structure": "Iris Индекс структуры, информация и инструменты размещения", "iris.modded.help.entry.group.structure": "Iris Индекс структуры, информация и инструменты размещения",
"iris.modded.help.entry.command.goldenhash": "Генерировать детерминированные хэши блоков для тестирования паритета", "iris.modded.help.entry.command.goldenhash": "Генерировать детерминированные хэши блоков для тестирования паритета",
"iris.modded.help.entry.group.developer": "Диагностика разработчиков: тест Sentry, сетевые интерфейсы, региональное сканирование файлов", "iris.modded.help.entry.group.developer": "Диагностика разработчиков: сетевые интерфейсы и сканирование файлов регионов",
"iris.modded.help.entry.command.biome": "Найти Iris биом", "iris.modded.help.entry.command.biome": "Найти Iris биом",
"iris.modded.help.entry.command.region": "Найти Iris регион", "iris.modded.help.entry.command.region": "Найти Iris регион",
"iris.modded.help.entry.command.object": "Найти объект размещения", "iris.modded.help.entry.command.object": "Найти объект размещения",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Объяснять Bukkit Структура импортного рабочего процесса", "iris.modded.help.entry.command.import": "Объяснять Bukkit Структура импортного рабочего процесса",
"iris.modded.help.entry.command.capture": "Объяснять Bukkit Структура захвата рабочего процесса", "iris.modded.help.entry.command.capture": "Объяснять Bukkit Структура захвата рабочего процесса",
"iris.modded.help.entry.command.verify": "Сообщение родного и Iris Достижимость структуры в текущем измерении", "iris.modded.help.entry.command.verify": "Сообщение родного и Iris Достижимость структуры в текущем измерении",
"iris.modded.help.entry.command.sentry": "Отправить тестовое исключение из Iris репортер ошибок",
"iris.modded.help.entry.command.network": "Список сетевых интерфейсов и их адреса", "iris.modded.help.entry.command.network": "Список сетевых интерфейсов и их адреса",
"iris.runtime.progress.finding_regions": "Поиск регионов", "iris.runtime.progress.finding_regions": "Поиск регионов",
"iris.runtime.progress.converting": "преобразовывать", "iris.runtime.progress.converting": "преобразовывать",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth Ingest is ingest BukkitSadece; bunları manuel olarak yükleme world/datapacks Gerekirse.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth Ingest is ingest BukkitSadece; bunları manuel olarak yükleme world/datapacks Gerekirse.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Bağlantılı dünya veri paketleri: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Bağlantılı dünya veri paketleri: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Iris hata raporlayıcısına bir test istisnası gönderildi (etkinse Sentry).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Ağ tarama başarısız oldu: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Ağ tarama başarısız oldu: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Altınhash tarama zaten çalışıyor.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Altınhash tarama zaten çalışıyor.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Datapack id (folder adı) tarafından gösterilen /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Datapack id (folder adı) tarafından gösterilen /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Dünya Yöneticisi", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Dünya Yöneticisi",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Yükleme alın TectonicPlates Kont", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Yükleme alın TectonicPlates Kont",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Gönderilen bir test istisnaı gönder",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hash, determinism/identity test için sabit bir bölgenin blok çıktısını üretti", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Hash, determinism/identity test için sabit bir bölgenin blok çıktısını üretti",
"iris.director.commanddeveloper.param.world_hash": "Dünyanın sahip olması", "iris.director.commanddeveloper.param.world_hash": "Dünyanın sahip olması",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Radius merkez çevresinde", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Radius merkez çevresinde",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Dünya veri paketi ve statü yardımcıları", "iris.modded.help.entry.group.datapack": "Dünya veri paketi ve statü yardımcıları",
"iris.modded.help.entry.group.structure": "Iris Yapı indeksi, bilgi ve yerleştirme araçları", "iris.modded.help.entry.group.structure": "Iris Yapı indeksi, bilgi ve yerleştirme araçları",
"iris.modded.help.entry.command.goldenhash": "Genrate deterministic blok parity testi için vardır", "iris.modded.help.entry.command.goldenhash": "Genrate deterministic blok parity testi için vardır",
"iris.modded.help.entry.group.developer": "Geliştirici tanıları: Sentry testi, ağ arabirimleri, bölge-file tarama", "iris.modded.help.entry.group.developer": "Geliştirici tanıları: ağ arabirimleri ve bölge dosyası taraması",
"iris.modded.help.entry.command.biome": "Bir an bulun Iris Biyome", "iris.modded.help.entry.command.biome": "Bir an bulun Iris Biyome",
"iris.modded.help.entry.command.region": "Bir an bulun Iris Bölge bölgesi", "iris.modded.help.entry.command.region": "Bir an bulun Iris Bölge bölgesi",
"iris.modded.help.entry.command.object": "Bir nesne yerleşimi bulun", "iris.modded.help.entry.command.object": "Bir nesne yerleşimi bulun",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Açık Açıklama Bukkit Yapı import iş akışı", "iris.modded.help.entry.command.import": "Açık Açıklama Bukkit Yapı import iş akışı",
"iris.modded.help.entry.command.capture": "Açık Açıklama Bukkit Yapı yakalama", "iris.modded.help.entry.command.capture": "Açık Açıklama Bukkit Yapı yakalama",
"iris.modded.help.entry.command.verify": "Rapor yerli ve Iris Yapı mevcut boyutta erişilebilirlik", "iris.modded.help.entry.command.verify": "Rapor yerli ve Iris Yapı mevcut boyutta erişilebilirlik",
"iris.modded.help.entry.command.sentry": "Bir test istisnaı gönderin Iris hata muhabiri",
"iris.modded.help.entry.command.network": "Liste ağ arabirimleri ve adresleri", "iris.modded.help.entry.command.network": "Liste ağ arabirimleri ve adresleri",
"iris.runtime.progress.finding_regions": "Bölgeleri bulmak", "iris.runtime.progress.finding_regions": "Bölgeleri bulmak",
"iris.runtime.progress.converting": "Dönüştürmek", "iris.runtime.progress.converting": "Dönüştürmek",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth Ăn là Bukkit-Chỉ; cài đặt những điều này bằng tay vào world/datapacks nếu cần thiết.", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth Ăn là Bukkit-Chỉ; cài đặt những điều này bằng tay vào world/datapacks nếu cần thiết.",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "Bộ dữ liệu thế giới đã cài đặt: {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "Bộ dữ liệu thế giới đã cài đặt: {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "Đã gửi một ngoại lệ thử nghiệm đến trình báo lỗi Iris (Sentry nếu được bật).",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "Việc quét mạng bị lỗi: {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "Việc quét mạng bị lỗi: {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Chụp cắt lớp vàng đã chạy rồi.", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "Chụp cắt lớp vàng đã chạy rồi.",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Mã nhận diện dữ liệu (tên thư mục) được hiển thị bởi /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "Mã nhận diện dữ liệu (tên thư mục) được hiển thị bởi /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris Quản lý thế giới", "iris.director.commanddeveloper.director.iris_world_manager": "Iris Quản lý thế giới",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Đã nạp TectonicPlates Số lượng", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "Đã nạp TectonicPlates Số lượng",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "Name",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Đã tạo ra khối kết xuất của một khu vực cố định để thử nghiệm chủ nghĩa xác định/không xác định", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "Đã tạo ra khối kết xuất của một khu vực cố định để thử nghiệm chủ nghĩa xác định/không xác định",
"iris.director.commanddeveloper.param.world_hash": "♪ Thế giới sẽ khô cằn ♪", "iris.director.commanddeveloper.param.world_hash": "♪ Thế giới sẽ khô cằn ♪",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Bán kính trong mảng xung quanh trung tâm", "iris.director.commanddeveloper.param.radius_chunks_around_center": "Bán kính trong mảng xung quanh trung tâm",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "Name", "iris.modded.help.entry.group.datapack": "Name",
"iris.modded.help.entry.group.structure": "Iris chỉ mục cấu trúc, thông tin và công cụ định vị", "iris.modded.help.entry.group.structure": "Iris chỉ mục cấu trúc, thông tin và công cụ định vị",
"iris.modded.help.entry.command.goldenhash": "Tạo ra khối quyết định để kiểm tra cân bằng", "iris.modded.help.entry.command.goldenhash": "Tạo ra khối quyết định để kiểm tra cân bằng",
"iris.modded.help.entry.group.developer": "Chẩn đoán dành cho nhà phát triển: kiểm tra Sentry, giao diện mạng và quét tệp vùng", "iris.modded.help.entry.group.developer": "Chẩn đoán dành cho nhà phát triển: giao diện mạng và quét tệp vùng",
"iris.modded.help.entry.command.biome": "Tìm một Iris sinh học", "iris.modded.help.entry.command.biome": "Tìm một Iris sinh học",
"iris.modded.help.entry.command.region": "Tìm một Iris vùng", "iris.modded.help.entry.command.region": "Tìm một Iris vùng",
"iris.modded.help.entry.command.object": "Tìm một vị trí đối tượng", "iris.modded.help.entry.command.object": "Tìm một vị trí đối tượng",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "Giải thích Bukkit Comment", "iris.modded.help.entry.command.import": "Giải thích Bukkit Comment",
"iris.modded.help.entry.command.capture": "Giải thích Bukkit Name", "iris.modded.help.entry.command.capture": "Giải thích Bukkit Name",
"iris.modded.help.entry.command.verify": "Báo cáo bản địa và Iris cấu trúc khả năng chạm tới trong chiều không gian hiện tại", "iris.modded.help.entry.command.verify": "Báo cáo bản địa và Iris cấu trúc khả năng chạm tới trong chiều không gian hiện tại",
"iris.modded.help.entry.command.sentry": "Gửi một ngoại lệ thử nghiệm đến Iris Thông báo lỗi",
"iris.modded.help.entry.command.network": "Liệt kê các giao diện mạng và địa chỉ của chúng", "iris.modded.help.entry.command.network": "Liệt kê các giao diện mạng và địa chỉ của chúng",
"iris.runtime.progress.finding_regions": "Tìm vùng", "iris.runtime.progress.finding_regions": "Tìm vùng",
"iris.runtime.progress.converting": "Chuyển đổi", "iris.runtime.progress.converting": "Chuyển đổi",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth 摄入是 Bukkit- 只安装; 手动安装到 world/datapacks 如果需要的话。", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth 摄入是 Bukkit- 只安装; 手动安装到 world/datapacks 如果需要的话。",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "安装的世界数据包 : {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "安装的世界数据包 : {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "已向 Iris 错误报告器发送测试异常(若已启用 Sentry)。",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "网络扫描失败 : {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "网络扫描失败 : {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "金色扫描已经运行中 。", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "金色扫描已经运行中 。",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "数据包 id (文件夹名称) 显示于 /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "数据包 id (文件夹名称) 显示于 /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris 世界经理", "iris.director.commanddeveloper.director.iris_world_manager": "Iris 世界经理",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "加载 TectonicPlates 计数", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "加载 TectonicPlates 计数",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "向哨兵发送测试例外",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "用于确定/识别测试的固定区域的散列输出", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "用于确定/识别测试的固定区域的散列输出",
"iris.director.commanddeveloper.param.world_hash": "散开的世界", "iris.director.commanddeveloper.param.world_hash": "散开的世界",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "半径为中心周围的块", "iris.director.commanddeveloper.param.radius_chunks_around_center": "半径为中心周围的块",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "世界数据包安装和状态工具", "iris.modded.help.entry.group.datapack": "世界数据包安装和状态工具",
"iris.modded.help.entry.group.structure": "Iris 结构索引、信息和放置工具", "iris.modded.help.entry.group.structure": "Iris 结构索引、信息和放置工具",
"iris.modded.help.entry.command.goldenhash": "为一致性测试生成确定性方块哈希", "iris.modded.help.entry.command.goldenhash": "为一致性测试生成确定性方块哈希",
"iris.modded.help.entry.group.developer": "开发者诊断:Sentry 测试、网络接口和区域文件扫描", "iris.modded.help.entry.group.developer": "开发者诊断:网络接口和区域文件扫描",
"iris.modded.help.entry.command.biome": "查找 Iris 群系", "iris.modded.help.entry.command.biome": "查找 Iris 群系",
"iris.modded.help.entry.command.region": "查找 Iris 区域", "iris.modded.help.entry.command.region": "查找 Iris 区域",
"iris.modded.help.entry.command.object": "查找对象放置", "iris.modded.help.entry.command.object": "查找对象放置",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "说明 Bukkit 结构导入流程", "iris.modded.help.entry.command.import": "说明 Bukkit 结构导入流程",
"iris.modded.help.entry.command.capture": "说明 Bukkit 结构捕获流程", "iris.modded.help.entry.command.capture": "说明 Bukkit 结构捕获流程",
"iris.modded.help.entry.command.verify": "报告当前维度中原生结构和 Iris 结构的可达性", "iris.modded.help.entry.command.verify": "报告当前维度中原生结构和 Iris 结构的可达性",
"iris.modded.help.entry.command.sentry": "向 Iris 错误报告器发送测试异常",
"iris.modded.help.entry.command.network": "列出网络接口及其地址", "iris.modded.help.entry.command.network": "列出网络接口及其地址",
"iris.runtime.progress.finding_regions": "寻找区域", "iris.runtime.progress.finding_regions": "寻找区域",
"iris.runtime.progress.converting": "转换", "iris.runtime.progress.converting": "转换",
+1 -4
View File
@@ -429,7 +429,6 @@
"iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth 攝入是 Bukkit- 只安裝; 手動安裝到 world/datapacks 如果需要的話。", "iris.modded.moddeddatapackcommands.modrinth_ingest_is_bukkit_only_install_these_manually_into_world": "Modrinth 攝入是 Bukkit- 只安裝; 手動安裝到 world/datapacks 如果需要的話。",
"iris.modded.moddeddatapackcommands.installed_world_datapacks": "安裝的世界資料包 : {value}", "iris.modded.moddeddatapackcommands.installed_world_datapacks": "安裝的世界資料包 : {value}",
"iris.modded.moddeddatapackcommands.message_2": " - {name}", "iris.modded.moddeddatapackcommands.message_2": " - {name}",
"iris.modded.moddeddevelopercommands.dispatched_test_exception_iris_error_reporter_sentry_if_enabled": "已向 Iris 錯誤報告器傳送測試例外(若已啟用 Sentry)。",
"iris.modded.moddeddevelopercommands.message": " {value}", "iris.modded.moddeddevelopercommands.message": " {value}",
"iris.modded.moddeddevelopercommands.network_scan_failed": "網路掃描失敗 : {value}", "iris.modded.moddeddevelopercommands.network_scan_failed": "網路掃描失敗 : {value}",
"iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "金色掃描已經執行中 。", "iris.modded.moddedgoldenhash.goldenhash_scan_is_already_running": "金色掃描已經執行中 。",
@@ -620,7 +619,6 @@
"iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "資料包 id (資料夾名稱) 顯示於 /iris datapack list", "iris.director.commanddatapack.param.datapack_id_folder_name_shown_by_iris_datapack_list": "資料包 id (資料夾名稱) 顯示於 /iris datapack list",
"iris.director.commanddeveloper.director.iris_world_manager": "Iris 世界經理", "iris.director.commanddeveloper.director.iris_world_manager": "Iris 世界經理",
"iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "載入 TectonicPlates 計數", "iris.director.commanddeveloper.director.get_loaded_tectonicplates_count": "載入 TectonicPlates 計數",
"iris.director.commanddeveloper.director.send_test_exception_sentry": "向哨兵傳送測試例外",
"iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "用於確定/識別測試的固定區域的雜湊輸出", "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing": "用於確定/識別測試的固定區域的雜湊輸出",
"iris.director.commanddeveloper.param.world_hash": "散開的世界", "iris.director.commanddeveloper.param.world_hash": "散開的世界",
"iris.director.commanddeveloper.param.radius_chunks_around_center": "半徑為中心周圍的塊", "iris.director.commanddeveloper.param.radius_chunks_around_center": "半徑為中心周圍的塊",
@@ -850,7 +848,7 @@
"iris.modded.help.entry.group.datapack": "世界資料包安裝和狀態工具", "iris.modded.help.entry.group.datapack": "世界資料包安裝和狀態工具",
"iris.modded.help.entry.group.structure": "Iris 結構索引、資訊和放置工具", "iris.modded.help.entry.group.structure": "Iris 結構索引、資訊和放置工具",
"iris.modded.help.entry.command.goldenhash": "為一致性測試生成確定性方塊雜湊", "iris.modded.help.entry.command.goldenhash": "為一致性測試生成確定性方塊雜湊",
"iris.modded.help.entry.group.developer": "開發者診斷:Sentry 測試、網路介面和區域檔案掃描", "iris.modded.help.entry.group.developer": "開發者診斷:網路介面和區域檔案掃描",
"iris.modded.help.entry.command.biome": "尋找 Iris 生態域", "iris.modded.help.entry.command.biome": "尋找 Iris 生態域",
"iris.modded.help.entry.command.region": "尋找 Iris 區域", "iris.modded.help.entry.command.region": "尋找 Iris 區域",
"iris.modded.help.entry.command.object": "尋找物件放置", "iris.modded.help.entry.command.object": "尋找物件放置",
@@ -912,7 +910,6 @@
"iris.modded.help.entry.command.import": "說明 Bukkit 結構匯入流程", "iris.modded.help.entry.command.import": "說明 Bukkit 結構匯入流程",
"iris.modded.help.entry.command.capture": "說明 Bukkit 結構擷取流程", "iris.modded.help.entry.command.capture": "說明 Bukkit 結構擷取流程",
"iris.modded.help.entry.command.verify": "回報目前維度中原生結構和 Iris 結構的可達性", "iris.modded.help.entry.command.verify": "回報目前維度中原生結構和 Iris 結構的可達性",
"iris.modded.help.entry.command.sentry": "向 Iris 錯誤回報器傳送測試例外",
"iris.modded.help.entry.command.network": "列出網路介面及其位址", "iris.modded.help.entry.command.network": "列出網路介面及其位址",
"iris.runtime.progress.finding_regions": "尋找區域", "iris.runtime.progress.finding_regions": "尋找區域",
"iris.runtime.progress.converting": "轉換", "iris.runtime.progress.converting": "轉換",
@@ -55,7 +55,7 @@ public class IrisLanguageTest {
+ "|\\b[A-Za-z0-9_*{}.-]+\\.(?:json|toml|ya?ml|jar|nbt|iob|properties|log|zip)\\b" + "|\\b[A-Za-z0-9_*{}.-]+\\.(?:json|toml|ya?ml|jar|nbt|iob|properties|log|zip)\\b"
); );
private static final Pattern PROPER_NAME = Pattern.compile( private static final Pattern PROPER_NAME = Pattern.compile(
"\\b(?:IrisDimensions|Iris|Minecraft|CraftBukkit|Bukkit|Paper|Folia|Fabric|NeoForge|Forge|Modrinth|GitHub|VSCode|Brigadier|Mantle|MiniMessage|Adventure|Sentry|NMS|NBT|JSON|TOML|YAML|GUI|HUD|TPS|MSPT|FPS|CPU|GPU|RAM|JAR|API|UUID|BUD|ETA|HD|LQ|ms)\\b" "\\b(?:IrisDimensions|Iris|Minecraft|CraftBukkit|Bukkit|Paper|Folia|Fabric|NeoForge|Forge|Modrinth|GitHub|VSCode|Brigadier|Mantle|MiniMessage|Adventure|NMS|NBT|JSON|TOML|YAML|GUI|HUD|TPS|MSPT|FPS|CPU|GPU|RAM|JAR|API|UUID|BUD|ETA|HD|LQ|ms)\\b"
); );
private static final List<String> IRIS_PRODUCT_NAMES = List.of( private static final List<String> IRIS_PRODUCT_NAMES = List.of(
"Iris Vision", "Iris Vision",
@@ -66,7 +66,6 @@ public class IrisLanguageTest {
"ResourceManager", "ResourceManager",
"GoldenHash", "GoldenHash",
"IGenData", "IGenData",
"Sentry",
"TectonicPlates" "TectonicPlates"
); );
private static final Pattern MARKER_DEBRIS = Pattern.compile("(?:⟬|⟭|\\b(?:XQ|QZ)[A-Z0-9_]*\\b|[\\uE000-\\uF8FF])"); private static final Pattern MARKER_DEBRIS = Pattern.compile("(?:⟬|⟭|\\b(?:XQ|QZ)[A-Z0-9_]*\\b|[\\uE000-\\uF8FF])");
@@ -1090,8 +1090,6 @@ public class PackHydrologyValidatorTest {
"inland_grotto", "inland_grotto",
"inland-grotto", "inland-grotto",
"mouth", "mouth",
"ridge_tunnel",
"ridge-tunnel",
"deep" "deep"
)) { )) {
File pack = pack(""" File pack = pack("""
@@ -47,7 +47,7 @@ public class IrisEnginePlatformHookIsolationTest {
); );
@Test @Test
public void sharedGeneratorHotPathsDoNotLinkBukkitImplementations() throws IOException { public void sharedGeneratorHotPathsDoNotLinkBukkitImplementations() throws IOException, ClassNotFoundException {
assertNoClassLinks(IrisEngine.class, BUKKIT_ENGINE_CLASSES); assertNoClassLinks(IrisEngine.class, BUKKIT_ENGINE_CLASSES);
assertNoClassLinks(EngineBackgroundTasks.class, BUKKIT_ENGINE_CLASSES); assertNoClassLinks(EngineBackgroundTasks.class, BUKKIT_ENGINE_CLASSES);
assertNoClassLinks(EngineDataStore.class, BUKKIT_ENGINE_CLASSES); assertNoClassLinks(EngineDataStore.class, BUKKIT_ENGINE_CLASSES);
@@ -56,6 +56,8 @@ public class IrisEnginePlatformHookIsolationTest {
assertNoClassLinks(EngineRuntimeBuilder.class, BUKKIT_ENGINE_CLASSES); assertNoClassLinks(EngineRuntimeBuilder.class, BUKKIT_ENGINE_CLASSES);
assertNoClassLinks(EngineShutdownSequence.class, BUKKIT_ENGINE_CLASSES); assertNoClassLinks(EngineShutdownSequence.class, BUKKIT_ENGINE_CLASSES);
assertNoClassLinks(EngineTickRegistry.class, BUKKIT_ENGINE_CLASSES); assertNoClassLinks(EngineTickRegistry.class, BUKKIT_ENGINE_CLASSES);
assertNoClassLinks(IrisEngineMantle.class, BUKKIT_ENGINE_CLASSES);
assertNoClassLinks(Class.forName(IrisEngineMantle.class.getName() + "$1"), BUKKIT_ENGINE_CLASSES);
assertNoClassLinks(Engine.class, ENGINE_POLICY_CLASSES); assertNoClassLinks(Engine.class, ENGINE_POLICY_CLASSES);
assertNoClassLinks(EngineMode.class, PLATFORM_POLICY_CLASSES); assertNoClassLinks(EngineMode.class, PLATFORM_POLICY_CLASSES);
assertNoClassLinks(EngineMantle.class, PLATFORM_POLICY_CLASSES); assertNoClassLinks(EngineMantle.class, PLATFORM_POLICY_CLASSES);
@@ -63,7 +65,8 @@ public class IrisEnginePlatformHookIsolationTest {
} }
private static void assertNoClassLinks(Class<?> type, List<String> forbiddenClasses) throws IOException { private static void assertNoClassLinks(Class<?> type, List<String> forbiddenClasses) throws IOException {
InputStream stream = type.getResourceAsStream(type.getSimpleName() + ".class"); String resourceName = type.getName().substring(type.getName().lastIndexOf('.') + 1) + ".class";
InputStream stream = type.getResourceAsStream(resourceName);
assertNotNull(stream); assertNotNull(stream);
String bytecode; String bytecode;
try (InputStream input = stream) { try (InputStream input = stream) {
@@ -429,6 +429,28 @@ public class DecoratorCoreTest {
assertEquals("minecraft:twisting_vines", DecoratorCore.stackedVineKey(vine, 3, 2)); assertEquals("minecraft:twisting_vines", DecoratorCore.stackedVineKey(vine, 3, 2));
} }
@Test
public void boundDecoratorHooksWinWhenBukkitClassesArePresent() {
PlatformBlockState vine = mock(PlatformBlockState.class);
PlatformBlockState fixed = mock(PlatformBlockState.class);
PlatformBlockState decorator = mock(PlatformBlockState.class);
PlatformBlockState surface = mock(PlatformBlockState.class);
Hunk<PlatformBlockState> output = Hunk.newArrayHunk(1, 1, 1);
DecoratorPlatformHooks.FaceFixer faceFixer = mock(DecoratorPlatformHooks.FaceFixer.class);
DecoratorPlatformHooks.SurfaceSturdiness sturdiness = mock(DecoratorPlatformHooks.SurfaceSturdiness.class);
when(vine.isVineBlock()).thenReturn(true);
when(faceFixer.fixFaces(vine, output, 0, 0, 0, 0, 0, null)).thenReturn(fixed);
when(decorator.canPlaceOnto(surface)).thenReturn(true);
when(sturdiness.canGoOn(surface)).thenReturn(true);
DecoratorPlatformHooks.Bindings previous = DecoratorPlatformHooks.bind(faceFixer, sturdiness);
try {
assertSame(fixed, DecoratorCore.fixFacesForHunk(vine, output, 0, 0, 0, 0, 0, null));
assertTrue(DecoratorCore.canGoOn(decorator, surface));
} finally {
DecoratorPlatformHooks.restore(previous);
}
}
private PlatformBlockState airState() { private PlatformBlockState airState() {
PlatformBlockState air = mock(PlatformBlockState.class); PlatformBlockState air = mock(PlatformBlockState.class);
when(air.isAir()).thenReturn(true); when(air.isAir()).thenReturn(true);
@@ -496,7 +496,7 @@ public class HydrologyModelTest {
@Test @Test
public void featureQuerySuggestionsIncludeConfiguredDeepFluidsWithoutHardcodedProfiles() { public void featureQuerySuggestionsIncludeConfiguredDeepFluidsWithoutHardcodedProfiles() {
List<String> suggestions = HydrologyFeatureQuery.suggestions( List<String> suggestions = HydrologyFeatureQuery.suggestions(
List.of("acid", "deep_lava", "acid", "surface", "ridge-tunnel") List.of("acid", "deep_lava", "acid", "surface", "coastal-grotto")
); );
assertEquals(List.of( assertEquals(List.of(
@@ -508,7 +508,6 @@ public class HydrologyModelTest {
"coastal_grotto", "coastal_grotto",
"inland_grotto", "inland_grotto",
"mouth", "mouth",
"ridge_tunnel",
"deep", "deep",
"pool", "pool",
"acid", "acid",
@@ -527,7 +526,6 @@ public class HydrologyModelTest {
"coastal_grotto", "coastal_grotto",
"inland_grotto", "inland_grotto",
"mouth", "mouth",
"ridge_tunnel",
"deep", "deep",
"pool" "pool"
); );
@@ -538,6 +536,8 @@ public class HydrologyModelTest {
assertTrue(keyword, HydrologyFeatureQuery.isReservedKeyword(keyword.replace('_', '-'))); assertTrue(keyword, HydrologyFeatureQuery.isReservedKeyword(keyword.replace('_', '-')));
} }
assertFalse(HydrologyFeatureQuery.isReservedKeyword("acid")); assertFalse(HydrologyFeatureQuery.isReservedKeyword("acid"));
assertFalse(HydrologyFeatureQuery.isReservedKeyword("ridge_tunnel"));
assertFalse(HydrologyFeatureQuery.isReservedKeyword("ridge-tunnel"));
assertFalse(HydrologyFeatureQuery.isReservedKeyword(null)); assertFalse(HydrologyFeatureQuery.isReservedKeyword(null));
assertEquals(Set.of(HydrologyFeatureType.SINKHOLE), HydrologyFeatureQuery.parse("sinkhole").types()); assertEquals(Set.of(HydrologyFeatureType.SINKHOLE), HydrologyFeatureQuery.parse("sinkhole").types());
} }
@@ -1,42 +1,74 @@
package art.arcane.iris.engine.object; package art.arcane.iris.engine.object;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.volmlib.util.collection.KMap;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class PlatformStateHookContractTest { public class PlatformStateHookContractTest {
@Test @Test
public void missingPlatformRotatorFailsLoudly() { public void boundRotatorWinsWhenBukkitClassesArePresent() {
IllegalStateException error = assertThrows(IllegalStateException.class, PlatformBlockState source = mock(PlatformBlockState.class);
() -> IrisObjectRotation.requirePlatformRotator(null)); PlatformBlockState rotated = mock(PlatformBlockState.class);
IrisObjectRotation.StateRotator hook = mock(IrisObjectRotation.StateRotator.class);
assertEquals("No platform block-state rotator is bound", error.getMessage()); IrisObjectRotation rotation = new IrisObjectRotation();
when(hook.rotate(rotation, source, 1, 2, 3)).thenReturn(rotated);
IrisObjectRotation.StateRotator previous = IrisObjectRotation.bindPlatformRotator(hook);
try {
assertSame(rotated, rotation.rotate(source, 1, 2, 3));
} finally {
IrisObjectRotation.restorePlatformRotator(previous);
}
} }
@Test @Test
public void missingPlatformMergerFailsLoudly() { public void boundMergerWinsWhenBukkitClassesArePresent() {
IllegalStateException error = assertThrows(IllegalStateException.class, PlatformBlockState base = mock(PlatformBlockState.class);
() -> BlockDataMergeSupport.requirePlatformMerger(null)); PlatformBlockState update = mock(PlatformBlockState.class);
PlatformBlockState merged = mock(PlatformBlockState.class);
assertEquals("No platform block-state merger is bound", error.getMessage()); BlockDataMergeSupport.StateMerger hook = mock(BlockDataMergeSupport.StateMerger.class);
when(hook.merge(base, update)).thenReturn(merged);
BlockDataMergeSupport.StateMerger previous = BlockDataMergeSupport.bindPlatformMerger(hook);
try {
assertSame(merged, BlockDataMergeSupport.merge(base, update));
} finally {
BlockDataMergeSupport.restorePlatformMerger(previous);
}
} }
@Test @Test
public void missingPlatformTileFactoryFailsLoudly() { public void boundTileFactoryWinsWhenBukkitClassesArePresent() {
IllegalStateException error = assertThrows(IllegalStateException.class, PlatformBlockState state = mock(PlatformBlockState.class);
() -> TileData.requirePlatformFactory(null)); KMap<String, Object> properties = new KMap<>();
TileData expected = mock(TileData.class);
assertEquals("No platform tile-data factory is bound", error.getMessage()); TileData.TileFactory hook = mock(TileData.TileFactory.class);
when(hook.create(state, properties)).thenReturn(expected);
TileData.TileFactory previous = TileData.bindPlatformFactory(hook);
try {
assertSame(expected, TileData.of(state, properties));
} finally {
TileData.restorePlatformFactory(previous);
}
} }
@Test @Test
public void missingPlatformTileReaderFailsLoudly() { public void boundTileReaderWinsWhenBukkitClassesArePresent() throws IOException {
IOException error = assertThrows(IOException.class, TileData expected = mock(TileData.class);
() -> TileData.requirePlatformReader(null)); TileData.TileReader hook = mock(TileData.TileReader.class);
DataInputStream input = new DataInputStream(new ByteArrayInputStream(new byte[0]));
assertEquals("No platform tile-data reader is bound", error.getMessage()); when(hook.read(input)).thenReturn(expected);
TileData.TileReader previous = TileData.bindPlatformReader(hook);
try {
assertSame(expected, TileData.read(input));
} finally {
TileData.restorePlatformReader(previous);
}
} }
} }
@@ -26,7 +26,9 @@ import art.arcane.iris.spi.PlatformRegistries;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.junit.Assume; import org.junit.Assume;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@@ -102,6 +104,16 @@ public class BukkitSpiConformanceTest {
assertSame(BukkitBlockState.of(first), BukkitBlockState.of(second)); assertSame(BukkitBlockState.of(first), BukkitBlockState.of(second));
} }
@Test
public void mantleValuesUseStableBukkitInterfaceSlices() {
BukkitPlatform platform = new BukkitPlatform();
assertTrue(platform.supportsMatterWorldIo());
assertSame(World.class, platform.classifyMantleValue(mock(World.class)));
assertSame(BlockData.class, platform.classifyMantleValue(blockData("minecraft:stone")));
assertSame(Entity.class, platform.classifyMantleValue(mock(Entity.class)));
assertSame(String.class, platform.classifyMantleValue("value"));
}
@Test @Test
public void blockStateKeyMatchesCanonicalString() { public void blockStateKeyMatchesCanonicalString() {
BlockData data = blockData("iristest:key_block[facing=north,lit=true]"); BlockData data = blockData("iristest:key_block[facing=north,lit=true]");
@@ -0,0 +1,55 @@
package art.arcane.iris.util.common.scheduling;
import art.arcane.iris.spi.IrisPlatform;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.iris.spi.PlatformScheduler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class JHybridPlatformTest {
@Before
public void clearPlatform() {
IrisPlatforms.unbind();
}
@After
public void cleanup() {
J.cancelTrackedRepeatingTasks();
IrisPlatforms.unbind();
}
@Test
public void boundBukkitIdentitySelectsBukkitScheduler() {
IrisPlatform platform = mock(IrisPlatform.class);
when(platform.platformName()).thenReturn("bukkit");
IrisPlatforms.bind(platform);
assertTrue(J.usesBukkitScheduler());
}
@Test
public void hybridHostRepeaterUsesBoundModdedScheduler() {
IrisPlatform platform = mock(IrisPlatform.class);
PlatformScheduler scheduler = mock(PlatformScheduler.class);
when(platform.platformName()).thenReturn("neoforge");
when(platform.scheduler()).thenReturn(scheduler);
IrisPlatforms.bind(platform);
assertFalse(J.usesBukkitScheduler());
int taskId = J.ar(() -> {
}, 1);
assertNotEquals(-1, taskId);
verify(scheduler).laterGlobal(any(Runnable.class), eq(1));
}
}
@@ -0,0 +1,46 @@
package art.arcane.iris.util.project.matter.slices;
import art.arcane.iris.spi.IrisPlatform;
import art.arcane.iris.spi.IrisPlatforms;
import org.bukkit.World;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class IrisMatterPlatformSelectionTest {
@Test
public void hybridClasspathDoesNotEnableBukkitMatterIoForModdedPlatform() {
IrisPlatform platform = mock(IrisPlatform.class);
withPlatform(platform, () -> {
assertNull(new EntityMatter().readFrom(World.class));
assertNull(new TileMatter().readFrom(World.class));
});
}
@Test
public void bukkitPlatformCapabilityEnablesBukkitMatterIo() {
IrisPlatform platform = mock(IrisPlatform.class);
when(platform.supportsMatterWorldIo()).thenReturn(true);
withPlatform(platform, () -> {
assertNotNull(new EntityMatter().readFrom(World.class));
assertNotNull(new TileMatter().readFrom(World.class));
});
}
private void withPlatform(IrisPlatform platform, Runnable test) {
IrisPlatform previous = IrisPlatforms.isBound() ? IrisPlatforms.get() : null;
IrisPlatforms.unbind();
IrisPlatforms.bind(platform);
try {
test.run();
} finally {
IrisPlatforms.unbind();
if (previous != null) {
IrisPlatforms.bind(previous);
}
}
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ org.gradle.configureondemand=false
nmsTools.repo-url=https://repo.codemc.org/repository/nms/ nmsTools.repo-url=https://repo.codemc.org/repository/nms/
nmsTools.specialSourceVersion=1.11.4 nmsTools.specialSourceVersion=1.11.4
irisVersion=4.0.0-26.2 irisVersion=4.0.1-26.2
minecraftVersion=26.2 minecraftVersion=26.2
# Bukkit plugin api-version: lowest supported Minecraft release line so one artifact loads on 26.1.2 and 26.2 # Bukkit plugin api-version: lowest supported Minecraft release line so one artifact loads on 26.1.2 and 26.2
apiVersion=26.1 apiVersion=26.1
-6
View File
@@ -6,8 +6,6 @@
# Plugins # Plugins
shadow = "9.5.1" # https://plugins.gradle.org/plugin/com.gradleup.shadow shadow = "9.5.1" # https://plugins.gradle.org/plugin/com.gradleup.shadow
slimjar = "2.1.9" # https://plugins.gradle.org/plugin/de.crazydev22.slimjar slimjar = "2.1.9" # https://plugins.gradle.org/plugin/de.crazydev22.slimjar
download = "5.7.0" # https://plugins.gradle.org/plugin/de.undercouch.download
sentryPlugin = "6.14.0" # https://github.com/getsentry/sentry-android-gradle-plugin
# Core Libraries # Core Libraries
lombok = "1.18.46" lombok = "1.18.46"
@@ -20,7 +18,6 @@ annotations = "26.1.0" # https://central.sonatype.com/artifact/org.jetbrains/ann
paralithic = "0.8.1" # https://github.com/PolyhedralDev/Paralithic/ paralithic = "0.8.1" # https://github.com/PolyhedralDev/Paralithic/
paperlib = "1.0.8" # https://github.com/PaperMC/PaperLib/ paperlib = "1.0.8" # https://github.com/PaperMC/PaperLib/
bstats = "3.2.1" # https://github.com/Bastian/bstats-metrics/tree/master bstats = "3.2.1" # https://github.com/Bastian/bstats-metrics/tree/master
sentry = "8.48.0" # https://github.com/getsentry/sentry-java
commons-io = "2.22.0" # https://central.sonatype.com/artifact/commons-io/commons-io commons-io = "2.22.0" # https://central.sonatype.com/artifact/commons-io/commons-io
commons-lang3 = "3.20.0" # https://central.sonatype.com/artifact/org.apache.commons/commons-lang3 commons-lang3 = "3.20.0" # https://central.sonatype.com/artifact/org.apache.commons/commons-lang3
oshi = "6.9.0" # Minecraft 26.2 runtime ceiling oshi = "6.9.0" # Minecraft 26.2 runtime ceiling
@@ -80,7 +77,6 @@ adventure-serializer-plain = { module = "net.kyori:adventure-text-serializer-pla
paralithic = { module = "com.dfsek:paralithic", version.ref = "paralithic" } paralithic = { module = "com.dfsek:paralithic", version.ref = "paralithic" }
paperlib = { module = "io.papermc:paperlib", version.ref = "paperlib" } paperlib = { module = "io.papermc:paperlib", version.ref = "paperlib" }
bstats = { module = "org.bstats:bstats-bukkit", version.ref = "bstats" } bstats = { module = "org.bstats:bstats-bukkit", version.ref = "bstats" }
sentry = { module = "io.sentry:sentry", version.ref = "sentry" }
commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" } commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" }
commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commons-lang3" } commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commons-lang3" }
oshi = { module = "com.github.oshi:oshi-core", version.ref = "oshi" } oshi = { module = "com.github.oshi:oshi-core", version.ref = "oshi" }
@@ -127,5 +123,3 @@ fabricApi-permission = { module = "net.fabricmc.fabric-api:fabric-permission-api
[plugins] [plugins]
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
slimjar = { id = "de.crazydev22.slimjar", version.ref = "slimjar" } slimjar = { id = "de.crazydev22.slimjar", version.ref = "slimjar" }
download = { id = "de.undercouch.download", version.ref = "download" }
sentry = { id = "io.sentry.jvm.gradle", version.ref = "sentryPlugin" }
-1
View File
@@ -33,7 +33,6 @@ dependencies {
runtimeOnly(libs.lz4) runtimeOnly(libs.lz4)
runtimeOnly(libs.zip) runtimeOnly(libs.zip)
runtimeOnly(libs.guava) runtimeOnly(libs.guava)
runtimeOnly(libs.sentry)
runtimeOnly(libs.oshi) runtimeOnly(libs.oshi)
runtimeOnly(libs.byteBuddy.core) runtimeOnly(libs.byteBuddy.core)
runtimeOnly(libs.byteBuddy.agent) runtimeOnly(libs.byteBuddy.agent)
@@ -86,4 +86,3 @@ art.arcane.iris.util.common.plugin.VolmitPlugin BUKKIT_API org.bukkit.event.List
art.arcane.iris.util.common.plugin.VolmitSender BUKKIT_API org.bukkit.command.CommandSender art.arcane.iris.util.common.plugin.VolmitSender BUKKIT_API org.bukkit.command.CommandSender
art.arcane.iris.util.common.plugin.chunk.ChunkTickets BUKKIT_API org.bukkit.event.Listener art.arcane.iris.util.common.plugin.chunk.ChunkTickets BUKKIT_API org.bukkit.event.Listener
art.arcane.iris.util.nbt.common.mca.NBTWorld$Holder BUKKIT_API org.bukkit.Material art.arcane.iris.util.nbt.common.mca.NBTWorld$Holder BUKKIT_API org.bukkit.Material
art.arcane.iris.util.project.sentry.ServerID$Holder BUKKIT_API org.bukkit.Bukkit
1 art.arcane.iris.core.IrisWorlds BUKKIT_API org.bukkit.command.CommandSender
86 art.arcane.iris.util.common.plugin.VolmitSender BUKKIT_API org.bukkit.command.CommandSender
87 art.arcane.iris.util.common.plugin.chunk.ChunkTickets BUKKIT_API org.bukkit.event.Listener
88 art.arcane.iris.util.nbt.common.mca.NBTWorld$Holder BUKKIT_API org.bukkit.Material
art.arcane.iris.util.project.sentry.ServerID$Holder BUKKIT_API org.bukkit.Bukkit
@@ -66,6 +66,14 @@ public interface IrisPlatform {
*/ */
PlatformBiomeWriter biomeWriter(); PlatformBiomeWriter biomeWriter();
default Class<?> classifyMantleValue(Object value) {
return value.getClass();
}
default boolean supportsMatterWorldIo() {
return false;
}
/** /**
* Root folder Iris owns for packs, settings and generated data. Created if missing. Never null. * Root folder Iris owns for packs, settings and generated data. Created if missing. Never null.
*/ */