mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-12 03:24:14 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15bc52e9b5 | ||
|
|
9103796845 | ||
|
|
27799039d1 | ||
|
|
fd8c55076e | ||
|
|
95d8523d1d | ||
|
|
ecec18509c | ||
|
|
1ca943ab51 | ||
|
|
1a561da2cd |
@@ -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
|
||||
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
|
||||
each download to finish before starting another. The shipping Overworld declares Towns & Towers
|
||||
26.1 and Dungeons & Taverns 5.3.0. With the default automatic ingest enabled, the first restart
|
||||
after download installs those external datapacks and leaves admission restart-required; complete
|
||||
the ensuing clean restart so Minecraft loads them together with the Iris dimension types and
|
||||
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
|
||||
each download to finish before starting another. The current built-in packs declare no external
|
||||
datapack imports. Restart after download so Minecraft loads their dimension types and biomes.
|
||||
Custom packs that declare `datapackImports` must complete their external-datapack installation and
|
||||
registry restart first. Plain Spigot supports ordinary managed `/iris create`, but not
|
||||
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
|
||||
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
|
||||
without stopping the server. Before loading the shipping Overworld, manually place the exact
|
||||
compatible Towns & Towers 26.1 and Dungeons & Taverns 5.3.0 archives in that save's `datapacks/`
|
||||
directory; modded `/iris datapack ingest` is an explanatory stub and does not install them. Restart
|
||||
once only after the Iris pack and both external datapacks are present. Packs register their custom
|
||||
dimension types, height ranges, biomes, and external structure keys during that boot; worlds created
|
||||
without stopping the server. The current built-in packs declare no external datapack imports.
|
||||
Custom packs that declare them require compatible archives in that save's `datapacks/` directory;
|
||||
modded `/iris datapack ingest` is an explanatory stub and does not install them. Restart only after
|
||||
the Iris pack and all of its inputs are present. Packs register their custom dimension types,
|
||||
height ranges, biomes, and external structure keys during that boot; worlds created
|
||||
before it run with fallback registry data.
|
||||
|
||||
**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
|
||||
```
|
||||
|
||||
builds every platform artifact into `dist/`:
|
||||
builds every platform artifact into the workspace-level `../PluginOuts/` directory:
|
||||
|
||||
```
|
||||
Iris v<version> [CraftBukkit] <mc>.jar
|
||||
|
||||
@@ -21,7 +21,6 @@ dependencies {
|
||||
testImplementation('org.mockito:mockito-core:5.23.0')
|
||||
testImplementation(libs.paper.api)
|
||||
testImplementation(libs.bstats)
|
||||
testImplementation(libs.sentry)
|
||||
testImplementation(project(':core'))
|
||||
testImplementation(volmLibCoordinate) {
|
||||
transitive = false
|
||||
|
||||
@@ -423,7 +423,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
return;
|
||||
}
|
||||
|
||||
Bindings.capture(e);
|
||||
boolean debug = false;
|
||||
if (instance != null) {
|
||||
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());
|
||||
}
|
||||
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
public static void reportError(String context, Throwable e) {
|
||||
@@ -473,7 +474,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
}
|
||||
|
||||
reportError(error);
|
||||
error.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
public static void dump() {
|
||||
@@ -606,7 +606,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
SimdSupport.install();
|
||||
services = new KMap<>();
|
||||
BukkitPlatform.hostHud(new HudActionBar(this), new HudBossBarLane());
|
||||
Bindings.setupSentry();
|
||||
// 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,
|
||||
// engine/world services next, commands last.
|
||||
|
||||
-14
@@ -34,7 +34,6 @@ import art.arcane.iris.engine.IrisEngineMantle;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
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.common.director.DirectorExecutor;
|
||||
import art.arcane.volmlib.util.director.DirectorOrigin;
|
||||
@@ -79,19 +78,6 @@ public class CommandDeveloper implements DirectorExecutor {
|
||||
.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)
|
||||
public void genhash(
|
||||
@Param(description = "The world to hash", descriptionKey = "iris.director.commanddeveloper.param.world_hash", contextual = true, contextualOverride = true)
|
||||
|
||||
@@ -114,6 +114,7 @@ dependencies {
|
||||
minecraft("com.mojang:minecraft:${minecraftVersion}")
|
||||
implementation("net.fabricmc:fabric-loader:${fabricLoaderVersion}")
|
||||
testImplementation('junit:junit:4.13.2')
|
||||
testImplementation('org.mockito:mockito-core:5.23.0')
|
||||
// registrySync and resourceLoader are LOAD-BEARING despite zero imports anywhere in Iris:
|
||||
// fabric-registry-sync-v0 delays registry freeze past mod init, which is what lets
|
||||
// IrisFabricBootstrap register the CHUNK_GENERATOR codec in
|
||||
@@ -162,8 +163,7 @@ dependencies {
|
||||
libs.lru,
|
||||
libs.caffeine,
|
||||
libs.dom4j,
|
||||
libs.jaxen,
|
||||
libs.sentry
|
||||
libs.jaxen
|
||||
]
|
||||
shared.each { Object notation ->
|
||||
add('bundle', notation)
|
||||
@@ -271,7 +271,6 @@ tasks.named('shadowJar', ShadowJar).configure {
|
||||
exclude('art/arcane/iris/platform/bukkit/**')
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
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
|
||||
// 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
|
||||
|
||||
@@ -131,6 +131,7 @@ configurations.testRuntimeClasspath.extendsFrom(configurations.runtimeClasspath,
|
||||
dependencies {
|
||||
implementation minecraft.dependency("net.minecraftforge:forge:${forgeVersion}")
|
||||
testImplementation('junit:junit:4.13.2')
|
||||
testImplementation('org.mockito:mockito-core:5.23.0')
|
||||
compileOnly('org.slf4j:slf4j-api:2.0.17')
|
||||
compileOnly(libs.spigot) {
|
||||
transitive = false
|
||||
@@ -161,8 +162,7 @@ dependencies {
|
||||
libs.lru,
|
||||
libs.caffeine,
|
||||
libs.dom4j,
|
||||
libs.jaxen,
|
||||
libs.sentry
|
||||
libs.jaxen
|
||||
]
|
||||
shared.each { Object notation ->
|
||||
add('bundle', notation)
|
||||
@@ -263,7 +263,6 @@ tasks.named('shadowJar', ShadowJar).configure {
|
||||
exclude('art/arcane/iris/platform/bukkit/**')
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
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
|
||||
// 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
|
||||
|
||||
+90
-12
@@ -331,34 +331,113 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
|
||||
if (server == null) {
|
||||
return null;
|
||||
}
|
||||
// Snapshot, never server.getAllLevels(): this runs off the server thread from data queries.
|
||||
for (ServerLevel level : ModdedServerLevels.levels(server)) {
|
||||
ServerLevel resolved = resolveBoundLevel(server, 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) {
|
||||
boundLevel = level;
|
||||
return level;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
ServerLevel overworld = server.getLevel(Level.OVERWORLD);
|
||||
return overworld != null && overworld.getChunkSource().getGenerator() == this ? overworld : null;
|
||||
}
|
||||
|
||||
Engine engine() {
|
||||
requireBindingAllowed();
|
||||
Engine cached = engine;
|
||||
requireCompletedShutdown(cached);
|
||||
if (cached != null && !cached.isClosed()) {
|
||||
Engine cached = readyEngine();
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
ServerLevel level = boundLevel();
|
||||
if (level == null) {
|
||||
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) {
|
||||
if (level.getChunkSource().getGenerator() != this) {
|
||||
throw new IllegalArgumentException("ServerLevel does not use Iris generator '" + dimensionKey + "'");
|
||||
}
|
||||
Engine current = engineIfBound();
|
||||
if (boundLevel == level && current != null && current.getComplex() != null) {
|
||||
return;
|
||||
}
|
||||
requireCompletedShutdown(engine);
|
||||
unloading = false;
|
||||
Engine bound = bindEngine(level);
|
||||
@@ -853,7 +932,6 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
|
||||
@Override
|
||||
public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) {
|
||||
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);
|
||||
try (GenerationSessionLease lease = requireGenerationLease(current, "modded_biome_decoration");
|
||||
IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) {
|
||||
@@ -867,7 +945,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
|
||||
|
||||
@Override
|
||||
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");
|
||||
IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) {
|
||||
Map<Structure, StructureStart> previousStarts = new HashMap<>(chunk.getAllStarts());
|
||||
@@ -891,7 +969,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
|
||||
|
||||
@Override
|
||||
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");
|
||||
IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) {
|
||||
NativeStructureReferenceRepair.createReferences(
|
||||
|
||||
+1
@@ -590,6 +590,7 @@ public final class ModdedDimensionManager {
|
||||
|
||||
boolean loadEventStarted = false;
|
||||
try {
|
||||
serverAccess.initializeLevelData(server, level);
|
||||
generator.bindLevel(level);
|
||||
Handle handle = new Handle(dimensionId, pack, packDimensionKey, seed, level, generator);
|
||||
ServerLevel previous = serverAccess.putLevelIfAbsent(server, key, level);
|
||||
|
||||
@@ -113,7 +113,6 @@ public final class ModdedEngineBootstrap {
|
||||
bindWorldGenerators(server);
|
||||
services().enableAll();
|
||||
ModdedProtocolHandler.start(server);
|
||||
ModdedSentry.start(loader());
|
||||
}
|
||||
|
||||
private static void bindWorldGenerators(MinecraftServer server) {
|
||||
@@ -194,7 +193,6 @@ public final class ModdedEngineBootstrap {
|
||||
MultiBurst.burst.close();
|
||||
MultiBurst.ioBurst.close();
|
||||
});
|
||||
failure = runStopStage(failure, "sentry", ModdedSentry::flush);
|
||||
failure = runStopStage(failure, "startup state", ModdedStartup::reset);
|
||||
failure = runStopStage(failure, "server state", () -> {
|
||||
currentServer = null;
|
||||
|
||||
@@ -47,7 +47,6 @@ public final class ModdedPlatform implements IrisPlatform {
|
||||
private static final ConcurrentHashMap<String, ErrorThrottle> ERROR_THROTTLES = new ConcurrentHashMap<>();
|
||||
|
||||
private static volatile Consumer<Throwable> ERROR_SINK = null;
|
||||
private static volatile Consumer<Throwable> CAPTURE_SINK = null;
|
||||
|
||||
private final ModdedLoader loader;
|
||||
private final ModdedRegistries registries;
|
||||
@@ -67,10 +66,6 @@ public final class ModdedPlatform implements IrisPlatform {
|
||||
ERROR_SINK = sink;
|
||||
}
|
||||
|
||||
public static void captureSink(Consumer<Throwable> sink) {
|
||||
CAPTURE_SINK = sink;
|
||||
}
|
||||
|
||||
public MinecraftServer server() {
|
||||
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
|
||||
* feeds Sentry, so each distinct signature reports its first few occurrences and then only a periodic
|
||||
* suppressed-count summary.
|
||||
* Throttled per exception signature. A single broken pack rule can fail on every generated chunk, so each
|
||||
* distinct signature reports its first few occurrences and then only a periodic suppressed-count summary.
|
||||
*/
|
||||
@Override
|
||||
public void reportError(Throwable error) {
|
||||
@@ -261,14 +255,6 @@ public final class ModdedPlatform implements IrisPlatform {
|
||||
return;
|
||||
}
|
||||
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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
void initializeLevelData(MinecraftServer server, ServerLevel level);
|
||||
|
||||
ServerLevel putLevel(MinecraftServer server, ResourceKey<Level> key, ServerLevel level);
|
||||
|
||||
ServerLevel putLevelIfAbsent(MinecraftServer server, ResourceKey<Level> key, ServerLevel level);
|
||||
|
||||
+150
-2
@@ -23,7 +23,11 @@ import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import 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.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -34,6 +38,18 @@ import java.util.function.Consumer;
|
||||
|
||||
public final class ModdedServerLevels implements ModdedServerAccess {
|
||||
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 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
|
||||
* thread, so every off-server-thread reader must iterate this snapshot instead of
|
||||
* Immutable view of the loaded levels. {@code server.levels} is loader-owned and published on the
|
||||
* server thread, so every off-server-thread reader must iterate this snapshot instead of
|
||||
* {@code server.getAllLevels()} to avoid ConcurrentModificationException.
|
||||
*/
|
||||
public static List<ServerLevel> levels(MinecraftServer server) {
|
||||
@@ -137,8 +153,32 @@ public final class ModdedServerLevels implements ModdedServerAccess {
|
||||
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
|
||||
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);
|
||||
if (previous != level) {
|
||||
capture(server);
|
||||
@@ -149,6 +189,15 @@ public final class ModdedServerLevels implements ModdedServerAccess {
|
||||
|
||||
@Override
|
||||
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);
|
||||
if (previous == null) {
|
||||
capture(server);
|
||||
@@ -159,6 +208,15 @@ public final class ModdedServerLevels implements ModdedServerAccess {
|
||||
|
||||
@Override
|
||||
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);
|
||||
if (removed != null) {
|
||||
capture(server);
|
||||
@@ -175,4 +233,94 @@ public final class ModdedServerLevels implements ModdedServerAccess {
|
||||
private record Snapshot(MinecraftServer server, List<ServerLevel> levels,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -87,7 +87,7 @@ final class ModdedCommandHelp {
|
||||
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.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(
|
||||
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("str", SECTIONS.get("structure"));
|
||||
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")
|
||||
));
|
||||
SECTIONS.put("dev", SECTIONS.get("developer"));
|
||||
|
||||
-9
@@ -19,7 +19,6 @@
|
||||
package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.modded.ModdedIrisLog;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
@@ -44,20 +43,12 @@ final class ModdedDeveloperCommands {
|
||||
static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
|
||||
return Commands.literal(name).requires(GATE)
|
||||
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "developer"))
|
||||
.then(Commands.literal("sentry")
|
||||
.executes((CommandContext<CommandSourceStack> context) -> sentry(context.getSource())))
|
||||
.then(Commands.literal("network")
|
||||
.executes((CommandContext<CommandSourceStack> context) -> network(context.getSource())))
|
||||
.then(Commands.literal("ip")
|
||||
.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) {
|
||||
try {
|
||||
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
|
||||
+150
@@ -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);
|
||||
}
|
||||
}
|
||||
+94
@@ -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 {
|
||||
}
|
||||
}
|
||||
+73
@@ -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 {
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,7 @@ configurations.testRuntimeClasspath.extendsFrom(configurations.runtimeClasspath,
|
||||
|
||||
dependencies {
|
||||
testImplementation('junit:junit:4.13.2')
|
||||
testImplementation('org.mockito:mockito-core:5.23.0')
|
||||
testRuntimeOnly('org.junit.platform:junit-platform-launcher:6.1.2')
|
||||
testRuntimeOnly('org.junit.vintage:junit-vintage-engine:6.1.2')
|
||||
compileOnly('org.slf4j:slf4j-api:2.0.17')
|
||||
@@ -131,8 +132,7 @@ dependencies {
|
||||
libs.lru,
|
||||
libs.caffeine,
|
||||
libs.dom4j,
|
||||
libs.jaxen,
|
||||
libs.sentry
|
||||
libs.jaxen
|
||||
]
|
||||
shared.each { Object notation ->
|
||||
add('bundle', notation)
|
||||
@@ -239,7 +239,6 @@ tasks.named('shadowJar', ShadowJar).configure {
|
||||
exclude('art/arcane/iris/platform/bukkit/**')
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
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
|
||||
// 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
|
||||
|
||||
+15
-50
@@ -1,4 +1,3 @@
|
||||
import de.undercouch.gradle.tasks.download.Download
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
@@ -39,7 +38,6 @@ buildscript {
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
alias(libs.plugins.download)
|
||||
}
|
||||
|
||||
group = 'art.arcane'
|
||||
@@ -75,6 +73,7 @@ String bukkitArtifactName = irisArtifactName('CraftBukkit', bukkitMinecraftRange
|
||||
String fabricArtifactName = irisArtifactName('Fabric', "${minecraftVersion}+${loaderDisplayVersion(fabricLoaderVersion)}")
|
||||
String forgeArtifactName = irisArtifactName('Forge', "${minecraftVersion}+${loaderDisplayVersion(forgeVersion)}")
|
||||
String neoForgeArtifactName = irisArtifactName('NeoForge', "${minecraftVersion}+${loaderDisplayVersion(neoForgeVersion)}")
|
||||
File pluginOutDirectory = layout.projectDirectory.dir('../PluginOuts').asFile
|
||||
long maximumBukkitArtifactBytes = 7_000_000L
|
||||
apply plugin: ApiGenerator
|
||||
|
||||
@@ -281,12 +280,12 @@ tasks.register('buildBukkit', Copy) {
|
||||
group = 'iris'
|
||||
dependsOn('jar')
|
||||
from(layout.buildDirectory.file("libs/${bukkitArtifactName}"))
|
||||
into(layout.projectDirectory.dir('dist'))
|
||||
into(pluginOutDirectory)
|
||||
doFirst {
|
||||
delete(fileTree(layout.projectDirectory.dir('dist')) {
|
||||
delete(fileTree(pluginOutDirectory) {
|
||||
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'
|
||||
dependsOn('fabricJar')
|
||||
from(layout.projectDirectory.file("adapters/fabric/build/libs/${fabricArtifactName}"))
|
||||
into(layout.projectDirectory.dir('dist'))
|
||||
into(pluginOutDirectory)
|
||||
doFirst {
|
||||
delete(fileTree(layout.projectDirectory.dir('dist')) {
|
||||
delete(fileTree(pluginOutDirectory) {
|
||||
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'
|
||||
dependsOn('forgeJar')
|
||||
from(layout.projectDirectory.file("adapters/forge/build/libs/${forgeArtifactName}"))
|
||||
into(layout.projectDirectory.dir('dist'))
|
||||
into(pluginOutDirectory)
|
||||
doFirst {
|
||||
delete(fileTree(layout.projectDirectory.dir('dist')) {
|
||||
delete(fileTree(pluginOutDirectory) {
|
||||
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'
|
||||
dependsOn('neoforgeJar')
|
||||
from(layout.projectDirectory.file("adapters/neoforge/build/libs/${neoForgeArtifactName}"))
|
||||
into(layout.projectDirectory.dir('dist'))
|
||||
into(pluginOutDirectory)
|
||||
doFirst {
|
||||
delete(fileTree(layout.projectDirectory.dir('dist')) {
|
||||
delete(fileTree(pluginOutDirectory) {
|
||||
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'
|
||||
dependsOn('buildBukkit', 'buildFabric', 'buildForge', 'buildNeoforge', ':spi:jar')
|
||||
doLast {
|
||||
File dist = layout.projectDirectory.dir('dist').asFile
|
||||
File[] jars = dist.listFiles((java.io.FileFilter) { File f -> f.name.endsWith('.jar') })
|
||||
File[] jars = pluginOutDirectory.listFiles((java.io.FileFilter) { File f -> f.name.startsWith('Iris v') && f.name.endsWith('.jar') })
|
||||
println('')
|
||||
println('=== Iris buildAllToOut -> dist/ ===')
|
||||
println('=== Iris buildAllToOut -> ' + pluginOutDirectory + ' ===')
|
||||
if (jars != null) {
|
||||
jars.sort { it.name }.each { File f ->
|
||||
println(String.format(' %-60s %8d KB', f.name, (long) (f.length() / 1024)))
|
||||
@@ -725,39 +723,6 @@ tasks.register('irisDev', Copy) {
|
||||
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 {
|
||||
resolutionStrategy.cacheChangingModulesFor(0, 'seconds')
|
||||
resolutionStrategy.cacheDynamicVersionsFor(0, 'seconds')
|
||||
|
||||
@@ -29,7 +29,6 @@ public final class BukkitArtifactVerifier {
|
||||
"art/arcane/iris/util/paper/",
|
||||
"art/arcane/iris/util/kyori/",
|
||||
"art/arcane/iris/util/metrics/",
|
||||
"art/arcane/iris/util/sentry/",
|
||||
"art/arcane/iris/util/maven/",
|
||||
"art/arcane/iris/util/plexus/",
|
||||
"art/arcane/iris/util/sisu/",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import io.github.slimjar.resolver.data.Mirror
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
@@ -31,7 +30,6 @@ plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
alias(libs.plugins.shadow)
|
||||
alias(libs.plugins.sentry)
|
||||
alias(libs.plugins.slimjar)
|
||||
}
|
||||
|
||||
@@ -39,8 +37,6 @@ def lib = 'art.arcane.iris.util'
|
||||
String volmLibCoordinate = providers.gradleProperty('volmLibCoordinate')
|
||||
.orElse('com.github.VolmitSoftware:VolmLib:e6574cf814b3dd670385a4d632a63fde2038e186')
|
||||
.get()
|
||||
String sentryAuthToken = findProperty('sentry.auth.token') as String ?: System.getenv('SENTRY_AUTH_TOKEN')
|
||||
boolean hasSentryAuthToken = sentryAuthToken != null && !sentryAuthToken.isBlank()
|
||||
|
||||
/**
|
||||
* Dependencies.
|
||||
@@ -97,8 +93,6 @@ dependencies {
|
||||
slim(libs.adventure.serializer.legacy)
|
||||
slim(libs.adventure.serializer.plain)
|
||||
slim(libs.bstats)
|
||||
slim(libs.sentry)
|
||||
|
||||
slim(libs.commons.io)
|
||||
slim(libs.commons.lang3)
|
||||
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 {
|
||||
mirrors = [
|
||||
new Mirror(
|
||||
@@ -158,7 +142,6 @@ slimJar {
|
||||
relocate('io.papermc.lib', "${lib}.paper")
|
||||
relocate('net.kyori', "${lib}.kyori")
|
||||
relocate('org.bstats', "${lib}.metrics")
|
||||
relocate('io.sentry', "${lib}.sentry")
|
||||
relocate('org.apache.maven', "${lib}.maven")
|
||||
relocate('org.codehaus.plexus', "${lib}.plexus")
|
||||
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 {
|
||||
it.name == 'prepareKotlinBuildScriptModel'
|
||||
}.configureEach {
|
||||
|
||||
@@ -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/slices/EntityMatter.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 IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||
private IrisSettingsPregen pregen = new IrisSettingsPregen();
|
||||
private IrisSettingsSentry sentry = new IrisSettingsSentry();
|
||||
private IrisSettingsTreeFeller treeFeller = new IrisSettingsTreeFeller();
|
||||
|
||||
public static int getThreadCount(int c) {
|
||||
@@ -182,7 +181,6 @@ public class IrisSettings {
|
||||
studio = studio == null ? new IrisSettingsStudio() : studio;
|
||||
performance = performance == null ? new IrisSettingsPerformance() : performance;
|
||||
pregen = pregen == null ? new IrisSettingsPregen() : pregen;
|
||||
sentry = sentry == null ? new IrisSettingsSentry() : sentry;
|
||||
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
|
||||
public static class IrisSettingsGUI {
|
||||
public boolean useServerLaunchedGuis = true;
|
||||
|
||||
@@ -123,6 +123,7 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
private VisionRenderController.Frame renderFrame;
|
||||
private JComboBox<RenderType> modeSelector;
|
||||
private JToggleButton gridToggle;
|
||||
private JToggleButton entitiesToggle;
|
||||
private JToggleButton followToggle;
|
||||
private RenderType currentType;
|
||||
private List<GuiMarker> players;
|
||||
@@ -140,6 +141,7 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
private double blocksPerPixel;
|
||||
private int paintCadenceFps;
|
||||
private boolean grid;
|
||||
private boolean entitiesVisible;
|
||||
private boolean follow;
|
||||
private boolean help;
|
||||
private boolean debug;
|
||||
@@ -158,6 +160,7 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
this.notifications = new LinkedHashMap<>();
|
||||
this.players = List.of();
|
||||
this.entities = List.of();
|
||||
this.entitiesVisible = false;
|
||||
this.currentType = RenderType.BIOME;
|
||||
this.blocksPerPixel = DEFAULT_BLOCKS_PER_PIXEL;
|
||||
this.contentRevision = 1L;
|
||||
@@ -263,6 +266,12 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
vision.gridToggle = createToggle(IrisLanguage.plain(DesktopUiMessages.VISION_GRID), vision.grid);
|
||||
vision.gridToggle.addActionListener(event -> vision.toggleGrid());
|
||||
trailing.add(vision.gridToggle);
|
||||
vision.entitiesToggle = createToggle(
|
||||
IrisLanguage.plain(DesktopUiMessages.VISION_ENTITIES),
|
||||
vision.entitiesVisible
|
||||
);
|
||||
vision.entitiesToggle.addActionListener(event -> vision.toggleEntities());
|
||||
trailing.add(vision.entitiesToggle);
|
||||
vision.followToggle = createToggle(IrisLanguage.plain(DesktopUiMessages.VISION_FOLLOW), vision.follow);
|
||||
vision.followToggle.addActionListener(event -> vision.toggleFollow());
|
||||
trailing.add(vision.followToggle);
|
||||
@@ -409,11 +418,13 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
}
|
||||
|
||||
private void renderMarkers(Graphics2D canvas) {
|
||||
for (GuiMarker marker : entities) {
|
||||
int screenX = (int) Math.round(worldToScreenX(marker.worldX()));
|
||||
int screenY = (int) Math.round(worldToScreenZ(marker.worldZ()));
|
||||
canvas.setColor(MOB_COLOR);
|
||||
canvas.fillRect(screenX - 2, screenY - 2, 5, 5);
|
||||
if (entitiesVisible) {
|
||||
for (GuiMarker marker : entities) {
|
||||
int screenX = (int) Math.round(worldToScreenX(marker.worldX()));
|
||||
int screenY = (int) Math.round(worldToScreenZ(marker.worldZ()));
|
||||
canvas.setColor(MOB_COLOR);
|
||||
canvas.fillRect(screenX - 2, screenY - 2, 5, 5);
|
||||
}
|
||||
}
|
||||
|
||||
for (GuiMarker marker : players) {
|
||||
@@ -428,7 +439,7 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
int labelWidth = canvas.getFontMetrics().stringWidth(marker.label());
|
||||
canvas.drawString(marker.label(), screenX - labelWidth / 2, screenY - 14);
|
||||
}
|
||||
if (detailedHover) {
|
||||
if (entitiesVisible && detailedHover) {
|
||||
renderNearestEntity(canvas);
|
||||
}
|
||||
}
|
||||
@@ -759,12 +770,16 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
try {
|
||||
List<GuiMarker> nextPlayers = overlay.players();
|
||||
players = nextPlayers == null ? List.of() : List.copyOf(nextPlayers);
|
||||
overlay.requestEntities(next -> EventQueue.invokeLater(() -> {
|
||||
if (!closed) {
|
||||
entities = next == null ? List.of() : List.copyOf(next);
|
||||
repaint();
|
||||
}
|
||||
}));
|
||||
if (entitiesVisible) {
|
||||
overlay.requestEntities(next -> EventQueue.invokeLater(() -> {
|
||||
if (!closed && entitiesVisible) {
|
||||
entities = next == null ? List.of() : List.copyOf(next);
|
||||
repaint();
|
||||
}
|
||||
}));
|
||||
} else if (!entities.isEmpty()) {
|
||||
entities = List.of();
|
||||
}
|
||||
if (follow && !players.isEmpty()) {
|
||||
GuiMarker player = players.get(0);
|
||||
if (Math.abs(centerX - player.worldX()) > 0.5D || Math.abs(centerZ - player.worldZ()) > 0.5D) {
|
||||
@@ -828,6 +843,22 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
notifyUser(IrisLanguage.plain(grid ? DesktopUiMessages.VISION_GRID_ENABLED : DesktopUiMessages.VISION_GRID_DISABLED));
|
||||
}
|
||||
|
||||
private void toggleEntities() {
|
||||
entitiesVisible = !entitiesVisible;
|
||||
if (entitiesVisible) {
|
||||
refreshMarkers();
|
||||
} else {
|
||||
entities = List.of();
|
||||
repaint();
|
||||
}
|
||||
syncControls();
|
||||
notifyUser(IrisLanguage.plain(
|
||||
entitiesVisible
|
||||
? DesktopUiMessages.VISION_ENTITIES_ENABLED
|
||||
: DesktopUiMessages.VISION_ENTITIES_DISABLED
|
||||
));
|
||||
}
|
||||
|
||||
private void toggleFollow() {
|
||||
follow = !follow;
|
||||
if (follow && players.isEmpty()) {
|
||||
@@ -857,6 +888,9 @@ public final class VisionGUI extends JPanel implements MouseWheelListener, KeyLi
|
||||
if (gridToggle != null) {
|
||||
gridToggle.setSelected(grid);
|
||||
}
|
||||
if (entitiesToggle != null) {
|
||||
entitiesToggle.setSelected(entitiesVisible);
|
||||
}
|
||||
if (followToggle != null) {
|
||||
followToggle.setSelected(follow);
|
||||
}
|
||||
|
||||
@@ -9,12 +9,15 @@ public final class DesktopUiMessages {
|
||||
public static final TextKey VISION_TITLE = TextKey.of("iris.desktop.vision.title", "Iris Vision");
|
||||
public static final TextKey VISION_VIEW = TextKey.of("iris.desktop.vision.view", "View:");
|
||||
public static final TextKey VISION_GRID = TextKey.of("iris.desktop.vision.grid", "Grid");
|
||||
public static final TextKey VISION_ENTITIES = TextKey.of("iris.desktop.vision.entities", "Entities");
|
||||
public static final TextKey VISION_FOLLOW = TextKey.of("iris.desktop.vision.follow", "Follow");
|
||||
public static final TextKey VISION_REFRESHING = TextKey.of("iris.desktop.vision.refreshing", "Refreshing");
|
||||
public static final TextKey VISION_FPS = TextKey.of("iris.desktop.vision.fps", "{fps} FPS");
|
||||
public static final TextKey VISION_ZOOM_RESET = TextKey.of("iris.desktop.vision.zoom_reset", "Zoom reset");
|
||||
public static final TextKey VISION_GRID_ENABLED = TextKey.of("iris.desktop.vision.grid_enabled", "Grid enabled");
|
||||
public static final TextKey VISION_GRID_DISABLED = TextKey.of("iris.desktop.vision.grid_disabled", "Grid disabled");
|
||||
public static final TextKey VISION_ENTITIES_ENABLED = TextKey.of("iris.desktop.vision.entities_enabled", "Entities enabled");
|
||||
public static final TextKey VISION_ENTITIES_DISABLED = TextKey.of("iris.desktop.vision.entities_disabled", "Entities disabled");
|
||||
public static final TextKey VISION_FOLLOWING = TextKey.of("iris.desktop.vision.following", "Following {player}");
|
||||
public static final TextKey VISION_NO_PLAYER = TextKey.of("iris.desktop.vision.no_player", "No player in world");
|
||||
public static final TextKey VISION_FOLLOW_DISABLED = TextKey.of("iris.desktop.vision.follow_disabled", "Follow disabled");
|
||||
@@ -157,8 +160,9 @@ public final class DesktopUiMessages {
|
||||
public static final TextKey IMAGEMAP_PREVIEW_STATUS = TextKey.of("iris.desktop.imagemap.preview_status", "X {x} Z {z} | {value} | {scale} blocks/pixel");
|
||||
|
||||
private static final List<MessageKey> KEYS = List.of(
|
||||
VISION_TITLE, VISION_VIEW, VISION_GRID, VISION_FOLLOW,
|
||||
VISION_TITLE, VISION_VIEW, VISION_GRID, VISION_ENTITIES, VISION_FOLLOW,
|
||||
VISION_REFRESHING, VISION_FPS, VISION_ZOOM_RESET, VISION_GRID_ENABLED, VISION_GRID_DISABLED,
|
||||
VISION_ENTITIES_ENABLED, VISION_ENTITIES_DISABLED,
|
||||
VISION_FOLLOWING, VISION_NO_PLAYER, VISION_FOLLOW_DISABLED,
|
||||
VISION_STATUS_LEFT, VISION_STATUS_RIGHT, VISION_ENTITY_POSITION, VISION_ENTITY_HEALTH,
|
||||
VISION_BLOCK_POSITION, VISION_CHUNK_POSITION, VISION_REGION_POSITION, VISION_BIOME_KEY,
|
||||
|
||||
@@ -38,10 +38,6 @@ public final class DirectorCommandMessages {
|
||||
"iris.director.commanddeveloper.director.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(
|
||||
"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"
|
||||
@@ -876,7 +872,6 @@ public final class DirectorCommandMessages {
|
||||
COMMAND_DATAPACK_PARAM_DATAPACK_ID_FOLDER_NAME_SHOWN_BY_IRIS_DATAPACK_LIST,
|
||||
COMMAND_DEVELOPER_DIRECTOR_IRIS_WORLD_MANAGER,
|
||||
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_PARAM_WORLD_HASH,
|
||||
COMMAND_DEVELOPER_PARAM_RADIUS_CHUNKS_AROUND_CENTER,
|
||||
|
||||
@@ -503,10 +503,6 @@ public final class ModdedCommandMessages {
|
||||
"iris.modded.moddeddatapackcommands.message_2",
|
||||
" - " + "{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(
|
||||
"iris.modded.moddeddevelopercommands.message",
|
||||
" " + "{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_INSTALLED_WORLD_DATAPACKS,
|
||||
MODDED_DATAPACK_COMMANDS_MESSAGE_2,
|
||||
MODDED_DEVELOPER_COMMANDS_DISPATCHED_TEST_EXCEPTION_IRIS_ERROR_REPORTER_SENTRY_IF_ENABLED,
|
||||
MODDED_DEVELOPER_COMMANDS_MESSAGE,
|
||||
MODDED_DEVELOPER_COMMANDS_NETWORK_SCAN_FAILED,
|
||||
MODDED_GOLDEN_HASH_GOLDENHASH_SCAN_IS_ALREADY_RUNNING,
|
||||
|
||||
@@ -98,9 +98,9 @@ public final class ModdedHelpMessages {
|
||||
"iris.modded.help.entry.command.goldenhash",
|
||||
"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",
|
||||
"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(
|
||||
"iris.modded.help.entry.command.biome",
|
||||
@@ -346,10 +346,6 @@ public final class ModdedHelpMessages {
|
||||
"iris.modded.help.entry.command.verify",
|
||||
"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(
|
||||
"iris.modded.help.entry.command.network",
|
||||
"List network interfaces and their addresses"
|
||||
@@ -443,7 +439,7 @@ public final class ModdedHelpMessages {
|
||||
GROUP_DATAPACK_WORLD_DATAPACK_INSTALL_AND_STATUS_HELPERS,
|
||||
GROUP_STRUCTURE_IRIS_STRUCTURE_INDEX_INFO_AND_PLACEMENT_TOOLS,
|
||||
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_REGION_FIND_AN_IRIS_REGION,
|
||||
COMMAND_OBJECT_FIND_AN_OBJECT_PLACEMENT,
|
||||
@@ -505,7 +501,6 @@ public final class ModdedHelpMessages {
|
||||
COMMAND_IMPORT_EXPLAIN_BUKKIT_STRUCTURE_IMPORT_WORKFLOW,
|
||||
COMMAND_CAPTURE_EXPLAIN_BUKKIT_STRUCTURE_CAPTURE_WORKFLOW,
|
||||
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_WHAT_HERE_INSPECT_CURRENT_IRIS_CONTEXT,
|
||||
COMMAND_WHAT_BIOME_INSPECT_CURRENT_BIOME,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package art.arcane.iris.engine;
|
||||
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.tools.WorldMaintenance;
|
||||
@@ -32,6 +31,7 @@ import art.arcane.iris.engine.mantle.components.MantleFloatingObjectComponent;
|
||||
import art.arcane.iris.engine.mantle.components.MantleObjectComponent;
|
||||
import art.arcane.iris.engine.mantle.components.IrisStructureComponent;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.iris.util.project.matter.IrisMatterContext;
|
||||
import art.arcane.iris.util.project.matter.IrisMatterSupport;
|
||||
@@ -51,7 +51,6 @@ import art.arcane.iris.util.common.format.C;
|
||||
import art.arcane.volmlib.util.matter.IrisMatter;
|
||||
import art.arcane.volmlib.util.matter.Matter;
|
||||
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.MultiBurst;
|
||||
import lombok.AccessLevel;
|
||||
@@ -73,7 +72,6 @@ import java.util.function.Supplier;
|
||||
@EqualsAndHashCode(exclude = "engine")
|
||||
@ToString(exclude = "engine")
|
||||
public class IrisEngineMantle implements EngineMantle {
|
||||
private static final boolean BUKKIT_PRESENT = IrisMatterSupport.isBukkitPresent();
|
||||
private final Engine engine;
|
||||
private final Mantle<Matter> mantle;
|
||||
@Getter(AccessLevel.NONE)
|
||||
@@ -248,10 +246,7 @@ public class IrisEngineMantle implements EngineMantle {
|
||||
if (value instanceof PlatformBlockState) {
|
||||
return PlatformBlockState.class;
|
||||
}
|
||||
if (BUKKIT_PRESENT) {
|
||||
return BukkitPlatform.classifyMantleValue(value);
|
||||
}
|
||||
return value.getClass();
|
||||
return IrisPlatforms.get().classifyMantleValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -43,21 +43,11 @@ final class DecoratorCore {
|
||||
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_PLANT = "minecraft:twisting_vines_plant";
|
||||
private static final boolean BUKKIT_PRESENT = detectBukkit();
|
||||
private static volatile PlatformBlockState weepingVines;
|
||||
private static volatile PlatformBlockState weepingVinesPlant;
|
||||
private static volatile PlatformBlockState twistingVines;
|
||||
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 class PlaceOpts {
|
||||
@@ -391,9 +381,9 @@ final class DecoratorCore {
|
||||
if (!B.isVineBlock(b)) {
|
||||
return b;
|
||||
}
|
||||
if (!BUKKIT_PRESENT) {
|
||||
DecoratorPlatformHooks.FaceFixer fixer = DecoratorPlatformHooks.faceFixer();
|
||||
return fixer == null ? b : fixer.fixFaces(b, hunk, rX, rZ, x, y, z, mantle);
|
||||
DecoratorPlatformHooks.FaceFixer fixer = DecoratorPlatformHooks.faceFixer();
|
||||
if (fixer != null) {
|
||||
return fixer.fixFaces(b, hunk, rX, rZ, x, y, z, mantle);
|
||||
}
|
||||
BlockData rawB = (BlockData) b.nativeHandle();
|
||||
BlockData cloned = rawB.clone();
|
||||
@@ -447,9 +437,9 @@ final class DecoratorCore {
|
||||
if (!B.canPlaceOnto(decorator, surface)) {
|
||||
return false;
|
||||
}
|
||||
if (!BUKKIT_PRESENT) {
|
||||
DecoratorPlatformHooks.SurfaceSturdiness sturdiness = DecoratorPlatformHooks.surfaceSturdiness();
|
||||
return sturdiness == null ? B.isSolid(surface) : sturdiness.canGoOn(surface);
|
||||
DecoratorPlatformHooks.SurfaceSturdiness sturdiness = DecoratorPlatformHooks.surfaceSturdiness();
|
||||
if (sturdiness != null) {
|
||||
return sturdiness.canGoOn(surface);
|
||||
}
|
||||
return ((BlockData) surface.nativeHandle()).isFaceSturdy(BlockFace.UP, BlockSupport.FULL);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class BlockDataMergeSupport {
|
||||
private static final boolean BUKKIT_PRESENT = detectBukkit();
|
||||
private static volatile StateMerger PLATFORM_MERGER = null;
|
||||
|
||||
private BlockDataMergeSupport() {
|
||||
@@ -29,31 +28,15 @@ public final class BlockDataMergeSupport {
|
||||
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) {
|
||||
if (!BUKKIT_PRESENT) {
|
||||
StateMerger merger = requirePlatformMerger(PLATFORM_MERGER);
|
||||
StateMerger merger = PLATFORM_MERGER;
|
||||
if (merger != null) {
|
||||
return merger.merge(base, update);
|
||||
}
|
||||
BlockData merged = merge((BlockData) base.nativeHandle(), (BlockData) update.nativeHandle(), BukkitBlockResolution::get);
|
||||
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) {
|
||||
try {
|
||||
return base.merge(update);
|
||||
|
||||
@@ -53,7 +53,6 @@ import java.util.Set;
|
||||
@Desc("Configures rotation for iris")
|
||||
@Data
|
||||
public class IrisObjectRotation {
|
||||
private static final boolean BUKKIT_PRESENT = detectBukkit();
|
||||
private static volatile StateRotator PLATFORM_ROTATOR = null;
|
||||
|
||||
public interface StateRotator {
|
||||
@@ -70,15 +69,6 @@ public class IrisObjectRotation {
|
||||
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 List<BlockFace> WALL_FACES = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
|
||||
}
|
||||
@@ -298,8 +288,8 @@ public class IrisObjectRotation {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!BUKKIT_PRESENT) {
|
||||
StateRotator rotator = requirePlatformRotator(PLATFORM_ROTATOR);
|
||||
StateRotator rotator = PLATFORM_ROTATOR;
|
||||
if (rotator != null) {
|
||||
return rotator.rotate(this, state, spinx, spiny, spinz);
|
||||
}
|
||||
|
||||
@@ -313,13 +303,6 @@ public class IrisObjectRotation {
|
||||
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) {
|
||||
return data instanceof Directional
|
||||
|| 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
|
||||
* either Bukkit-typed ({@link #fromBukkit(BlockState)}, reached only from
|
||||
* {@link TileData#getTileState(Block, boolean)} and the Bukkit structure importer) or sits behind
|
||||
* the {@code BUKKIT_PRESENT} short-circuit in {@link TileData#read(DataInputStream)}, which hands
|
||||
* off to the bound platform reader before this class is ever referenced. The nested handler types
|
||||
* {@link TileData#getTileState(Block, boolean)} and the Bukkit structure importer) or follows the
|
||||
* bound platform-reader path in {@link TileData#read(DataInputStream)}, which returns before this
|
||||
* class is ever referenced. The nested handler types
|
||||
* therefore keep their raw Bukkit fields.
|
||||
*/
|
||||
@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.
|
||||
*/
|
||||
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 TileFactory PLATFORM_FACTORY = null;
|
||||
|
||||
@@ -96,15 +95,6 @@ public class TileData implements Cloneable {
|
||||
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
|
||||
* 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) {
|
||||
if (!BUKKIT_PRESENT) {
|
||||
return requirePlatformFactory(PLATFORM_FACTORY).create(state, properties);
|
||||
TileFactory factory = PLATFORM_FACTORY;
|
||||
if (factory != null) {
|
||||
return factory.create(state, properties);
|
||||
}
|
||||
Object handle = state.nativeHandle();
|
||||
if (!(handle instanceof BlockData blockData)) {
|
||||
@@ -158,8 +149,9 @@ public class TileData implements Cloneable {
|
||||
}
|
||||
|
||||
public static TileData read(DataInputStream in) throws IOException {
|
||||
if (!BUKKIT_PRESENT) {
|
||||
return requirePlatformReader(PLATFORM_READER).read(in);
|
||||
TileReader reader = PLATFORM_READER;
|
||||
if (reader != null) {
|
||||
return reader.read(in);
|
||||
}
|
||||
if (!in.markSupported())
|
||||
throw new IOException("Mark not supported");
|
||||
@@ -215,20 +207,6 @@ public class TileData implements Cloneable {
|
||||
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) {
|
||||
Material resolved = resolveMaterial();
|
||||
return resolved != null && data.getMaterial() == resolved;
|
||||
|
||||
@@ -175,7 +175,8 @@ public final class BukkitPlatform implements IrisPlatform {
|
||||
return BukkitBiome.of((Biome) biome);
|
||||
}
|
||||
|
||||
public static Class<?> classifyMantleValue(Object value) {
|
||||
@Override
|
||||
public Class<?> classifyMantleValue(Object value) {
|
||||
if (value instanceof World) {
|
||||
return World.class;
|
||||
}
|
||||
@@ -191,6 +192,11 @@ public final class BukkitPlatform implements IrisPlatform {
|
||||
return value.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsMatterWorldIo() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void unregisterListener(Object candidate) {
|
||||
if (candidate instanceof Listener listener) {
|
||||
volmitPlugin().unregisterListener(listener);
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
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.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.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.scheduling.J;
|
||||
|
||||
import io.sentry.Sentry;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.DrilldownPie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
@@ -29,56 +16,6 @@ import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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
|
||||
private static final int BSTATS_PLUGIN_ID = 24220;
|
||||
|
||||
@@ -87,7 +24,7 @@ public class Bindings {
|
||||
return;
|
||||
}
|
||||
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()
|
||||
.stream()
|
||||
.filter(IrisToolbelt::isIrisWorld)
|
||||
@@ -100,7 +37,7 @@ public class Bindings {
|
||||
.map(PlatformChunkGenerator::getEngine)
|
||||
.filter(Objects::nonNull)
|
||||
.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();
|
||||
int version = engine.getDimension().getVersion();
|
||||
String checksum = Long.toHexString(hash32);
|
||||
|
||||
@@ -121,7 +121,7 @@ public class J {
|
||||
}
|
||||
|
||||
public static void aBukkit(Runnable a) {
|
||||
if (!BUKKIT_PRESENT) {
|
||||
if (!usesBukkitScheduler()) {
|
||||
if (IrisPlatforms.isBound()) {
|
||||
IrisPlatforms.get().scheduler().async(a);
|
||||
}
|
||||
@@ -186,7 +186,7 @@ public class J {
|
||||
}
|
||||
|
||||
public static boolean isFolia() {
|
||||
return BUKKIT_PRESENT && FoliaScheduler.isFolia(Bukkit.getServer());
|
||||
return usesBukkitScheduler() && FoliaScheduler.isFolia(Bukkit.getServer());
|
||||
}
|
||||
|
||||
public static boolean isPrimaryThread() {
|
||||
@@ -345,7 +345,7 @@ public class J {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BUKKIT_PRESENT) {
|
||||
if (!usesBukkitScheduler()) {
|
||||
if (!IrisPlatforms.isBound()) {
|
||||
return false;
|
||||
}
|
||||
@@ -416,7 +416,7 @@ public class J {
|
||||
|
||||
public static void cancelPluginTasks() {
|
||||
cancelTrackedRepeatingTasks();
|
||||
if (!BukkitPlatform.hasPlugin()) {
|
||||
if (!usesBukkitScheduler() || !BukkitPlatform.hasPlugin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ public class J {
|
||||
}
|
||||
|
||||
public static void s(Runnable r) {
|
||||
if (!BUKKIT_PRESENT) {
|
||||
if (!usesBukkitScheduler()) {
|
||||
if (IrisPlatforms.isBound()) {
|
||||
IrisPlatforms.get().scheduler().global(r);
|
||||
}
|
||||
@@ -566,7 +566,7 @@ public class J {
|
||||
}
|
||||
|
||||
public static void s(Runnable r, int delay) {
|
||||
if (!BUKKIT_PRESENT) {
|
||||
if (!usesBukkitScheduler()) {
|
||||
if (IrisPlatforms.isBound()) {
|
||||
IrisPlatforms.get().scheduler().laterGlobal(r, delay);
|
||||
}
|
||||
@@ -667,7 +667,7 @@ public class J {
|
||||
}
|
||||
|
||||
public static void a(Runnable r, int delay) {
|
||||
if (!BUKKIT_PRESENT) {
|
||||
if (!usesBukkitScheduler()) {
|
||||
if (IrisPlatforms.isBound()) {
|
||||
if (delay <= 0) {
|
||||
IrisPlatforms.get().scheduler().async(r);
|
||||
@@ -772,11 +772,17 @@ public class J {
|
||||
}
|
||||
|
||||
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() {
|
||||
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) {
|
||||
|
||||
@@ -36,25 +36,11 @@ import art.arcane.iris.util.common.math.IrisBlockVector;
|
||||
import java.io.File;
|
||||
|
||||
public final class IrisMatterSupport {
|
||||
private static final boolean BUKKIT_PRESENT = detectBukkit();
|
||||
private static boolean registered;
|
||||
|
||||
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() {
|
||||
if (registered) {
|
||||
return;
|
||||
|
||||
@@ -21,7 +21,7 @@ package art.arcane.iris.util.project.matter.slices;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
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.KMap;
|
||||
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) {
|
||||
super(width, height, depth, MatterEntityGroup.class);
|
||||
if (IrisMatterSupport.isBukkitPresent()) {
|
||||
if (IrisPlatforms.isBound() && IrisPlatforms.get().supportsMatterWorldIo()) {
|
||||
registerBukkitIO();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package art.arcane.iris.util.project.matter.slices;
|
||||
|
||||
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.volmlib.util.data.palette.Palette;
|
||||
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) {
|
||||
super(width, height, depth, TileWrapper.class);
|
||||
if (IrisMatterSupport.isBukkitPresent()) {
|
||||
if (IrisPlatforms.isBound() && IrisPlatforms.get().supportsMatterWorldIo()) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.installed_world_datapacks": "Installierte Weltdatenpakete: {value}",
|
||||
"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.network_scan_failed": "Netzwerk-Scan fehlgeschlagen: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris-Weltverwaltung",
|
||||
"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.param.world_hash": "Die zu hashende Welt",
|
||||
"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.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.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.region": "Eine Iris-Region finden",
|
||||
"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.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.sentry": "Eine Testausnahme an den Iris-Fehlerbericht senden",
|
||||
"iris.modded.help.entry.command.network": "Liste der Netzwerkschnittstellen und ihrer Adressen",
|
||||
"iris.runtime.progress.finding_regions": "Regionen werden gesucht",
|
||||
"iris.runtime.progress.converting": "Umwandlung",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Vision",
|
||||
"iris.desktop.vision.view": "Ansicht:",
|
||||
"iris.desktop.vision.grid": "Raster",
|
||||
"iris.desktop.vision.entities": "Entitäten",
|
||||
"iris.desktop.vision.follow": "Folgen",
|
||||
"iris.desktop.vision.refreshing": "Wird aktualisiert",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Zoom-Reset",
|
||||
"iris.desktop.vision.grid_enabled": "Raster aktiviert",
|
||||
"iris.desktop.vision.grid_disabled": "Raster deaktiviert",
|
||||
"iris.desktop.vision.entities_enabled": "Entitäten aktiviert",
|
||||
"iris.desktop.vision.entities_disabled": "Entitäten deaktiviert",
|
||||
"iris.desktop.vision.following": "Folge {player}",
|
||||
"iris.desktop.vision.no_player": "Kein Spieler in der Welt",
|
||||
"iris.desktop.vision.follow_disabled": "Folgen deaktiviert",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Datapacks del mundo instalados: {value}",
|
||||
"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.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.",
|
||||
@@ -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.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.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.param.world_hash": "El mundo cuyo hash se calculará",
|
||||
"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.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.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.region": "Buscar una región de Iris",
|
||||
"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.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.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.runtime.progress.finding_regions": "Buscando regiones",
|
||||
"iris.runtime.progress.converting": "Convirtiendo",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Vision",
|
||||
"iris.desktop.vision.view": "Vista:",
|
||||
"iris.desktop.vision.grid": "Cuadrícula",
|
||||
"iris.desktop.vision.entities": "Entidades",
|
||||
"iris.desktop.vision.follow": "Seguir",
|
||||
"iris.desktop.vision.refreshing": "Actualizando",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Zoom restablecido",
|
||||
"iris.desktop.vision.grid_enabled": "Cuadrícula activada",
|
||||
"iris.desktop.vision.grid_disabled": "Cuadrícula desactivada",
|
||||
"iris.desktop.vision.entities_enabled": "Entidades activadas",
|
||||
"iris.desktop.vision.entities_disabled": "Entidades desactivadas",
|
||||
"iris.desktop.vision.following": "Siguiendo a {player}",
|
||||
"iris.desktop.vision.no_player": "No hay jugadores en el mundo",
|
||||
"iris.desktop.vision.follow_disabled": "Seguimiento desactivado",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Asennetut maailman datapaketit: {value}",
|
||||
"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.network_scan_failed": "Verkkoskannaus epäonnistui: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris Maailmanjohtaja",
|
||||
"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.param.world_hash": "Maailma hasista",
|
||||
"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.structure": "Iris rakenneindeksi, tiedot ja työvälineet",
|
||||
"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.region": "Etsi Iris alue",
|
||||
"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.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.sentry": "Lähetä testi poikkeus Iris virheraportointi",
|
||||
"iris.modded.help.entry.command.network": "Listaa verkkoliittymät ja niiden osoitteet",
|
||||
"iris.runtime.progress.finding_regions": "Alueet",
|
||||
"iris.runtime.progress.converting": "Muunnetaan",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Näkö",
|
||||
"iris.desktop.vision.view": "Näytä:",
|
||||
"iris.desktop.vision.grid": "Ruudukko",
|
||||
"iris.desktop.vision.entities": "Entiteetit",
|
||||
"iris.desktop.vision.follow": "Seuraa",
|
||||
"iris.desktop.vision.refreshing": "Virkistävä",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Lähennä nollaus",
|
||||
"iris.desktop.vision.grid_enabled": "Verkko käytössä",
|
||||
"iris.desktop.vision.grid_disabled": "Verkko pois käytöstä",
|
||||
"iris.desktop.vision.entities_enabled": "Entiteetit käytössä",
|
||||
"iris.desktop.vision.entities_disabled": "Entiteetit pois käytöstä",
|
||||
"iris.desktop.vision.following": "Seurataan pelaajaa {player}",
|
||||
"iris.desktop.vision.no_player": "Ei pelaajaa maailmassa",
|
||||
"iris.desktop.vision.follow_disabled": "Seuraa pois käytöstä",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Datapacks du monde installés : {value}",
|
||||
"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.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.",
|
||||
@@ -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.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.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.param.world_hash": "Le monde dont le hash sera calculé",
|
||||
"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.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.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.region": "Rechercher une région Iris",
|
||||
"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.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.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.runtime.progress.finding_regions": "Recherche des régions",
|
||||
"iris.runtime.progress.converting": "Conversion",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Vision",
|
||||
"iris.desktop.vision.view": "Vue :",
|
||||
"iris.desktop.vision.grid": "Grille",
|
||||
"iris.desktop.vision.entities": "Entités",
|
||||
"iris.desktop.vision.follow": "Suivre",
|
||||
"iris.desktop.vision.refreshing": "Actualisation",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Zoom réinitialisé",
|
||||
"iris.desktop.vision.grid_enabled": "Grille activée",
|
||||
"iris.desktop.vision.grid_disabled": "Grille désactivée",
|
||||
"iris.desktop.vision.entities_enabled": "Entités activées",
|
||||
"iris.desktop.vision.entities_disabled": "Entités désactivées",
|
||||
"iris.desktop.vision.following": "Suivi de {player}",
|
||||
"iris.desktop.vision.no_player": "Aucun joueur dans le monde",
|
||||
"iris.desktop.vision.follow_disabled": "Suivi désactivé",
|
||||
|
||||
@@ -429,7 +429,6 @@
|
||||
"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.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.network_scan_failed": "סריקות רשת נכשלות: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris מנהל עולמי",
|
||||
"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.param.world_hash": "העולם שיש",
|
||||
"iris.director.commanddeveloper.param.radius_chunks_around_center": "רדינוס בחלקים סביב המרכז",
|
||||
@@ -850,7 +848,7 @@
|
||||
"iris.modded.help.entry.group.datapack": "חבילת נתונים עולמית להתקין ועוזרי סטטוס",
|
||||
"iris.modded.help.entry.group.structure": "Iris מדד מבנה, מידע וכלי מיקום",
|
||||
"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.region": "מצא Iris האזור האזורי",
|
||||
"iris.modded.help.entry.command.object": "מצא מיקום אובייקט",
|
||||
@@ -912,7 +910,6 @@
|
||||
"iris.modded.help.entry.command.import": "להסביר Bukkit ייבוא תהליך עבודה",
|
||||
"iris.modded.help.entry.command.capture": "להסביר Bukkit מבנה לכידת עבודה",
|
||||
"iris.modded.help.entry.command.verify": "דו\"ח Native ו- Iris מגיע לשיאות במימד הנוכחי",
|
||||
"iris.modded.help.entry.command.sentry": "שלח יוצא דופן במבחן Iris עיתונאי טעות",
|
||||
"iris.modded.help.entry.command.network": "ממשקי רשת וכתובות",
|
||||
"iris.runtime.progress.finding_regions": "מציאת אזורים",
|
||||
"iris.runtime.progress.converting": "המרת",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris חזון",
|
||||
"iris.desktop.vision.view": "תגית:",
|
||||
"iris.desktop.vision.grid": "גרי",
|
||||
"iris.desktop.vision.entities": "ישויות",
|
||||
"iris.desktop.vision.follow": "עקבו אחרי עקוב",
|
||||
"iris.desktop.vision.refreshing": "מרעננים",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "ZOOE",
|
||||
"iris.desktop.vision.grid_enabled": "רשת אפשר",
|
||||
"iris.desktop.vision.grid_disabled": "סגור",
|
||||
"iris.desktop.vision.entities_enabled": "ישויות מופעלות",
|
||||
"iris.desktop.vision.entities_disabled": "ישויות מושבתות",
|
||||
"iris.desktop.vision.following": "עוקב אחר {player}",
|
||||
"iris.desktop.vision.no_player": "אין שחקן בעולם",
|
||||
"iris.desktop.vision.follow_disabled": "עקבו אחרי מוגבלויות",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Datapack installati nel mondo: {value}",
|
||||
"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.network_scan_failed": "La scansione di rete non è riuscita: {value}",
|
||||
"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.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.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.param.world_hash": "Il mondo di cui calcolare l'hash",
|
||||
"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.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.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.region": "Trova una regione Iris",
|
||||
"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.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.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.runtime.progress.finding_regions": "Ricerca delle regioni",
|
||||
"iris.runtime.progress.converting": "Conversione",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Vision",
|
||||
"iris.desktop.vision.view": "Vedi:",
|
||||
"iris.desktop.vision.grid": "Griglia",
|
||||
"iris.desktop.vision.entities": "Entità",
|
||||
"iris.desktop.vision.follow": "Segui",
|
||||
"iris.desktop.vision.refreshing": "Aggiornamento",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Ripristino dello zoom",
|
||||
"iris.desktop.vision.grid_enabled": "Griglia abilitata",
|
||||
"iris.desktop.vision.grid_disabled": "Griglia disattivata",
|
||||
"iris.desktop.vision.entities_enabled": "Entità abilitate",
|
||||
"iris.desktop.vision.entities_disabled": "Entità disabilitate",
|
||||
"iris.desktop.vision.following": "Stai seguendo {player}",
|
||||
"iris.desktop.vision.no_player": "Nessun giocatore nel mondo",
|
||||
"iris.desktop.vision.follow_disabled": "Segui disattivato",
|
||||
|
||||
@@ -429,7 +429,6 @@
|
||||
"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.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.network_scan_failed": "ネットワークスキャン失敗: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris ワールドマネージャー",
|
||||
"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.param.world_hash": "ハッシュ化するワールド",
|
||||
"iris.director.commanddeveloper.param.radius_chunks_around_center": "中心からの半径(チャンク単位)",
|
||||
@@ -850,7 +848,7 @@
|
||||
"iris.modded.help.entry.group.datapack": "ワールドデータパックのインストールと状態確認を支援します",
|
||||
"iris.modded.help.entry.group.structure": "Iris 構造物のインデックス、情報、配置ツールです",
|
||||
"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.region": "Iris リージョンを検索します",
|
||||
"iris.modded.help.entry.command.object": "オブジェクト配置を検索します",
|
||||
@@ -912,7 +910,6 @@
|
||||
"iris.modded.help.entry.command.import": "Bukkit の構造物インポート手順を説明します",
|
||||
"iris.modded.help.entry.command.capture": "Bukkit の構造物キャプチャ手順を説明します",
|
||||
"iris.modded.help.entry.command.verify": "現在のディメンションでネイティブ構造物と Iris 構造物が到達可能か報告します",
|
||||
"iris.modded.help.entry.command.sentry": "Iris エラーレポーターへテスト例外を送信します",
|
||||
"iris.modded.help.entry.command.network": "ネットワークインターフェースとアドレスを一覧表示します",
|
||||
"iris.runtime.progress.finding_regions": "リージョンを検索中",
|
||||
"iris.runtime.progress.converting": "変換中",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris ビジョン",
|
||||
"iris.desktop.vision.view": "表示:",
|
||||
"iris.desktop.vision.grid": "グリッド",
|
||||
"iris.desktop.vision.entities": "エンティティ",
|
||||
"iris.desktop.vision.follow": "フォロー",
|
||||
"iris.desktop.vision.refreshing": "更新中",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "ズームリセット",
|
||||
"iris.desktop.vision.grid_enabled": "グリッド有効",
|
||||
"iris.desktop.vision.grid_disabled": "グリッド無効",
|
||||
"iris.desktop.vision.entities_enabled": "エンティティ有効",
|
||||
"iris.desktop.vision.entities_disabled": "エンティティ無効",
|
||||
"iris.desktop.vision.following": "{player} を追跡中",
|
||||
"iris.desktop.vision.no_player": "ワールドにプレイヤーがいません",
|
||||
"iris.desktop.vision.follow_disabled": "追跡無効",
|
||||
|
||||
@@ -429,7 +429,6 @@
|
||||
"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.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.network_scan_failed": "네트워크 검사 실패: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris 월드 관리자",
|
||||
"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.param.world_hash": "해시할 월드",
|
||||
"iris.director.commanddeveloper.param.radius_chunks_around_center": "중심 기준 반경(청크 단위)",
|
||||
@@ -850,7 +848,7 @@
|
||||
"iris.modded.help.entry.group.datapack": "월드 데이터 팩 설치와 상태 확인 도구입니다",
|
||||
"iris.modded.help.entry.group.structure": "Iris 구조물 인덱스, 정보, 배치 도구입니다",
|
||||
"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.region": "Iris 리전을 찾습니다",
|
||||
"iris.modded.help.entry.command.object": "오브젝트 배치를 찾습니다",
|
||||
@@ -912,7 +910,6 @@
|
||||
"iris.modded.help.entry.command.import": "Bukkit 구조물 가져오기 절차를 설명합니다",
|
||||
"iris.modded.help.entry.command.capture": "Bukkit 구조물 캡처 절차를 설명합니다",
|
||||
"iris.modded.help.entry.command.verify": "현재 차원의 네이티브 및 Iris 구조물 도달 가능성을 보고합니다",
|
||||
"iris.modded.help.entry.command.sentry": "Iris 오류 보고기로 테스트 예외를 보냅니다",
|
||||
"iris.modded.help.entry.command.network": "네트워크 인터페이스와 주소를 나열합니다",
|
||||
"iris.runtime.progress.finding_regions": "지역 찾기",
|
||||
"iris.runtime.progress.converting": "변환 중",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Vision",
|
||||
"iris.desktop.vision.view": "보기:",
|
||||
"iris.desktop.vision.grid": "격자",
|
||||
"iris.desktop.vision.entities": "엔티티",
|
||||
"iris.desktop.vision.follow": "추적",
|
||||
"iris.desktop.vision.refreshing": "새로 고치는 중",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Zoom 리셋",
|
||||
"iris.desktop.vision.grid_enabled": "격자 활성화",
|
||||
"iris.desktop.vision.grid_disabled": "격자 비활성화",
|
||||
"iris.desktop.vision.entities_enabled": "엔티티 활성화",
|
||||
"iris.desktop.vision.entities_disabled": "엔티티 비활성화",
|
||||
"iris.desktop.vision.following": "{player} 추적 중",
|
||||
"iris.desktop.vision.no_player": "월드에 플레이어가 없음",
|
||||
"iris.desktop.vision.follow_disabled": "추적 비활성화",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Įdiegti pasauliniai duomenys: {value}",
|
||||
"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.network_scan_failed": "Tinklo skenavimas nepavyko: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris Pasaulio vadybininkas",
|
||||
"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.param.world_hash": "Pasaulis, kuriam reikia maišyti",
|
||||
"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.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.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.region": "Rasti Iris regionas",
|
||||
"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.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.sentry": "Siųsti bandymo išimtį Iris klaidų reporteris",
|
||||
"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.converting": "Konvertuojama",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Regėjimas",
|
||||
"iris.desktop.vision.view": "Rodymas:",
|
||||
"iris.desktop.vision.grid": "Tinklelis",
|
||||
"iris.desktop.vision.entities": "Esybės",
|
||||
"iris.desktop.vision.follow": "Sekti",
|
||||
"iris.desktop.vision.refreshing": "Atnaujinimas",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Mastelis iš naujo",
|
||||
"iris.desktop.vision.grid_enabled": "Tinklelis įjungtas",
|
||||
"iris.desktop.vision.grid_disabled": "Tinklelis išjungtas",
|
||||
"iris.desktop.vision.entities_enabled": "Esybės įjungtos",
|
||||
"iris.desktop.vision.entities_disabled": "Esybės išjungtos",
|
||||
"iris.desktop.vision.following": "Sekamas {player}",
|
||||
"iris.desktop.vision.no_player": "Jokio žaidėjo pasaulyje",
|
||||
"iris.desktop.vision.follow_disabled": "Sekti išjungtą",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Geïnstalleerde werelddatapacks: {value}",
|
||||
"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.network_scan_failed": "Netwerkscan mislukt: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris Wereldmanager",
|
||||
"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.param.world_hash": "De wereld te hash",
|
||||
"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.structure": "Iris structuurindex, info- en plaatsingsinstrumenten",
|
||||
"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.region": "Zoek een Iris regio",
|
||||
"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.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.sentry": "Stuur een testuitzondering naar de Iris foutverslaggever",
|
||||
"iris.modded.help.entry.command.network": "Lijst van netwerkinterfaces en hun adressen",
|
||||
"iris.runtime.progress.finding_regions": "Regio's vinden",
|
||||
"iris.runtime.progress.converting": "Converteren",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Gezicht",
|
||||
"iris.desktop.vision.view": "Beeld:",
|
||||
"iris.desktop.vision.grid": "Raster",
|
||||
"iris.desktop.vision.entities": "Entiteiten",
|
||||
"iris.desktop.vision.follow": "Volgen",
|
||||
"iris.desktop.vision.refreshing": "Verversen",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Reset zoomen",
|
||||
"iris.desktop.vision.grid_enabled": "Raster ingeschakeld",
|
||||
"iris.desktop.vision.grid_disabled": "Raster uitgeschakeld",
|
||||
"iris.desktop.vision.entities_enabled": "Entiteiten ingeschakeld",
|
||||
"iris.desktop.vision.entities_disabled": "Entiteiten uitgeschakeld",
|
||||
"iris.desktop.vision.following": "Volgt {player}",
|
||||
"iris.desktop.vision.no_player": "Geen speler in de wereld",
|
||||
"iris.desktop.vision.follow_disabled": "Volgen uitgeschakeld",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Zainstalowane world datapacks: {value}",
|
||||
"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.network_scan_failed": "Skanowanie sieci nie powiodło się: {value}",
|
||||
"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.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.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.param.world_hash": "Świat, by się zahaczyć",
|
||||
"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.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.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.region": "Znajdź Iris regiony",
|
||||
"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.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.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.runtime.progress.finding_regions": "Znalezienie regionów",
|
||||
"iris.runtime.progress.converting": "Konwersja",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Wizja",
|
||||
"iris.desktop.vision.view": "Widok:",
|
||||
"iris.desktop.vision.grid": "Sieć",
|
||||
"iris.desktop.vision.entities": "Byty",
|
||||
"iris.desktop.vision.follow": "Śledź",
|
||||
"iris.desktop.vision.refreshing": "Odświeżające",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Zmień powiększenie",
|
||||
"iris.desktop.vision.grid_enabled": "Siatka włączona",
|
||||
"iris.desktop.vision.grid_disabled": "Sieć wyłączona",
|
||||
"iris.desktop.vision.entities_enabled": "Byty włączone",
|
||||
"iris.desktop.vision.entities_disabled": "Byty wyłączone",
|
||||
"iris.desktop.vision.following": "Śledzenie gracza {player}",
|
||||
"iris.desktop.vision.no_player": "Brak gracza na świecie",
|
||||
"iris.desktop.vision.follow_disabled": "Śledź wyłączone",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Pacotes de dados mundiais instalados: {value}",
|
||||
"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.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.",
|
||||
@@ -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.commanddeveloper.director.iris_world_manager": "Iris Gestor Mundial",
|
||||
"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.param.world_hash": "O mundo para hash",
|
||||
"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.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.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.region": "Procurar um Iris região",
|
||||
"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.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.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.runtime.progress.finding_regions": "Regiões de pesquisa",
|
||||
"iris.runtime.progress.converting": "Conversão",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Visão",
|
||||
"iris.desktop.vision.view": "Ver:",
|
||||
"iris.desktop.vision.grid": "Grade",
|
||||
"iris.desktop.vision.entities": "Entidades",
|
||||
"iris.desktop.vision.follow": "Seguir",
|
||||
"iris.desktop.vision.refreshing": "Atualizando",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Ampliação repor",
|
||||
"iris.desktop.vision.grid_enabled": "Grade habilitada",
|
||||
"iris.desktop.vision.grid_disabled": "Grade desabilitada",
|
||||
"iris.desktop.vision.entities_enabled": "Entidades ativadas",
|
||||
"iris.desktop.vision.entities_disabled": "Entidades desativadas",
|
||||
"iris.desktop.vision.following": "A seguir {player}",
|
||||
"iris.desktop.vision.no_player": "Nenhum jogador no mundo",
|
||||
"iris.desktop.vision.follow_disabled": "Seguir desabilitado",
|
||||
|
||||
@@ -429,7 +429,6 @@
|
||||
"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.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.network_scan_failed": "Сканирование сети не удалось: {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris Мировой менеджер",
|
||||
"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.param.world_hash": "Мир для хеширования",
|
||||
"iris.director.commanddeveloper.param.radius_chunks_around_center": "Радиус в чанках вокруг центра",
|
||||
@@ -850,7 +848,7 @@
|
||||
"iris.modded.help.entry.group.datapack": "Установка Мировой пакет данных и статус помощников",
|
||||
"iris.modded.help.entry.group.structure": "Iris Индекс структуры, информация и инструменты размещения",
|
||||
"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.region": "Найти Iris регион",
|
||||
"iris.modded.help.entry.command.object": "Найти объект размещения",
|
||||
@@ -912,7 +910,6 @@
|
||||
"iris.modded.help.entry.command.import": "Объяснять Bukkit Структура импортного рабочего процесса",
|
||||
"iris.modded.help.entry.command.capture": "Объяснять Bukkit Структура захвата рабочего процесса",
|
||||
"iris.modded.help.entry.command.verify": "Сообщение родного и Iris Достижимость структуры в текущем измерении",
|
||||
"iris.modded.help.entry.command.sentry": "Отправить тестовое исключение из Iris репортер ошибок",
|
||||
"iris.modded.help.entry.command.network": "Список сетевых интерфейсов и их адреса",
|
||||
"iris.runtime.progress.finding_regions": "Поиск регионов",
|
||||
"iris.runtime.progress.converting": "преобразовывать",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Видение",
|
||||
"iris.desktop.vision.view": "Посмотреть:",
|
||||
"iris.desktop.vision.grid": "сетка",
|
||||
"iris.desktop.vision.entities": "Сущности",
|
||||
"iris.desktop.vision.follow": "Следить",
|
||||
"iris.desktop.vision.refreshing": "освежающий",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Сброс Zoom",
|
||||
"iris.desktop.vision.grid_enabled": "Сетка включена",
|
||||
"iris.desktop.vision.grid_disabled": "Сетка отключена",
|
||||
"iris.desktop.vision.entities_enabled": "Сущности включены",
|
||||
"iris.desktop.vision.entities_disabled": "Сущности отключены",
|
||||
"iris.desktop.vision.following": "Отслеживается {player}",
|
||||
"iris.desktop.vision.no_player": "Нет игрока в мире",
|
||||
"iris.desktop.vision.follow_disabled": "Следить за инвалидами",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Bağlantılı dünya veri paketleri: {value}",
|
||||
"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.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.",
|
||||
@@ -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.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.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.param.world_hash": "Dünyanın sahip olması",
|
||||
"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.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.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.region": "Bir an bulun Iris Bölge bölgesi",
|
||||
"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.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.sentry": "Bir test istisnaı gönderin Iris hata muhabiri",
|
||||
"iris.modded.help.entry.command.network": "Liste ağ arabirimleri ve adresleri",
|
||||
"iris.runtime.progress.finding_regions": "Bölgeleri bulmak",
|
||||
"iris.runtime.progress.converting": "Dönüştürmek",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Vizyon",
|
||||
"iris.desktop.vision.view": "Görüntüleme:",
|
||||
"iris.desktop.vision.grid": "Izgara",
|
||||
"iris.desktop.vision.entities": "Varlıklar",
|
||||
"iris.desktop.vision.follow": "Takip",
|
||||
"iris.desktop.vision.refreshing": "Yenileme",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "yakınlaştırma reset sıfırlama",
|
||||
"iris.desktop.vision.grid_enabled": "Grid etkinleştirdi",
|
||||
"iris.desktop.vision.grid_disabled": "Izgara",
|
||||
"iris.desktop.vision.entities_enabled": "Varlıklar etkin",
|
||||
"iris.desktop.vision.entities_disabled": "Varlıklar devre dışı",
|
||||
"iris.desktop.vision.following": "{player} takip ediliyor",
|
||||
"iris.desktop.vision.no_player": "Hiçbir oyuncu dünyada",
|
||||
"iris.desktop.vision.follow_disabled": "Engellileri Takip Et",
|
||||
|
||||
@@ -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.installed_world_datapacks": "Bộ dữ liệu thế giới đã cài đặt: {value}",
|
||||
"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.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.",
|
||||
@@ -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.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.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.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",
|
||||
@@ -850,7 +848,7 @@
|
||||
"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.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.region": "Tìm một Iris vù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.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.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.runtime.progress.finding_regions": "Tìm vùng",
|
||||
"iris.runtime.progress.converting": "Chuyển đổi",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris Tầm nhìn",
|
||||
"iris.desktop.vision.view": "Xem:",
|
||||
"iris.desktop.vision.grid": "Lưới",
|
||||
"iris.desktop.vision.entities": "Thực thể",
|
||||
"iris.desktop.vision.follow": "Theo",
|
||||
"iris.desktop.vision.refreshing": "Cập nhật",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "Đặt lại phóng đại",
|
||||
"iris.desktop.vision.grid_enabled": "Lưới đã bật",
|
||||
"iris.desktop.vision.grid_disabled": "Tắt Lưới",
|
||||
"iris.desktop.vision.entities_enabled": "Đã bật thực thể",
|
||||
"iris.desktop.vision.entities_disabled": "Đã tắt thực thể",
|
||||
"iris.desktop.vision.following": "Đang theo dõi {player}",
|
||||
"iris.desktop.vision.no_player": "Không có người chơi trên thế giới",
|
||||
"iris.desktop.vision.follow_disabled": "Tắt theo",
|
||||
|
||||
@@ -429,7 +429,6 @@
|
||||
"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.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.network_scan_failed": "网络扫描失败 : {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris 世界经理",
|
||||
"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.param.world_hash": "散开的世界",
|
||||
"iris.director.commanddeveloper.param.radius_chunks_around_center": "半径为中心周围的块",
|
||||
@@ -850,7 +848,7 @@
|
||||
"iris.modded.help.entry.group.datapack": "世界数据包安装和状态工具",
|
||||
"iris.modded.help.entry.group.structure": "Iris 结构索引、信息和放置工具",
|
||||
"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.region": "查找 Iris 区域",
|
||||
"iris.modded.help.entry.command.object": "查找对象放置",
|
||||
@@ -912,7 +910,6 @@
|
||||
"iris.modded.help.entry.command.import": "说明 Bukkit 结构导入流程",
|
||||
"iris.modded.help.entry.command.capture": "说明 Bukkit 结构捕获流程",
|
||||
"iris.modded.help.entry.command.verify": "报告当前维度中原生结构和 Iris 结构的可达性",
|
||||
"iris.modded.help.entry.command.sentry": "向 Iris 错误报告器发送测试异常",
|
||||
"iris.modded.help.entry.command.network": "列出网络接口及其地址",
|
||||
"iris.runtime.progress.finding_regions": "寻找区域",
|
||||
"iris.runtime.progress.converting": "转换",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris 愿景",
|
||||
"iris.desktop.vision.view": "视图 :",
|
||||
"iris.desktop.vision.grid": "网格",
|
||||
"iris.desktop.vision.entities": "实体",
|
||||
"iris.desktop.vision.follow": "跟着",
|
||||
"iris.desktop.vision.refreshing": "刷新",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "缩放重置",
|
||||
"iris.desktop.vision.grid_enabled": "已启用网格",
|
||||
"iris.desktop.vision.grid_disabled": "已禁用网格",
|
||||
"iris.desktop.vision.entities_enabled": "实体已启用",
|
||||
"iris.desktop.vision.entities_disabled": "实体已禁用",
|
||||
"iris.desktop.vision.following": "跟踪 {player}",
|
||||
"iris.desktop.vision.no_player": "世界上没有玩家",
|
||||
"iris.desktop.vision.follow_disabled": "跟随已禁用",
|
||||
|
||||
@@ -429,7 +429,6 @@
|
||||
"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.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.network_scan_failed": "網路掃描失敗 : {value}",
|
||||
"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.commanddeveloper.director.iris_world_manager": "Iris 世界經理",
|
||||
"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.param.world_hash": "散開的世界",
|
||||
"iris.director.commanddeveloper.param.radius_chunks_around_center": "半徑為中心周圍的塊",
|
||||
@@ -850,7 +848,7 @@
|
||||
"iris.modded.help.entry.group.datapack": "世界資料包安裝和狀態工具",
|
||||
"iris.modded.help.entry.group.structure": "Iris 結構索引、資訊和放置工具",
|
||||
"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.region": "尋找 Iris 區域",
|
||||
"iris.modded.help.entry.command.object": "尋找物件放置",
|
||||
@@ -912,7 +910,6 @@
|
||||
"iris.modded.help.entry.command.import": "說明 Bukkit 結構匯入流程",
|
||||
"iris.modded.help.entry.command.capture": "說明 Bukkit 結構擷取流程",
|
||||
"iris.modded.help.entry.command.verify": "回報目前維度中原生結構和 Iris 結構的可達性",
|
||||
"iris.modded.help.entry.command.sentry": "向 Iris 錯誤回報器傳送測試例外",
|
||||
"iris.modded.help.entry.command.network": "列出網路介面及其位址",
|
||||
"iris.runtime.progress.finding_regions": "尋找區域",
|
||||
"iris.runtime.progress.converting": "轉換",
|
||||
@@ -1358,12 +1355,15 @@
|
||||
"iris.desktop.vision.title": "Iris 願景",
|
||||
"iris.desktop.vision.view": "檢視 :",
|
||||
"iris.desktop.vision.grid": "網格",
|
||||
"iris.desktop.vision.entities": "實體",
|
||||
"iris.desktop.vision.follow": "跟著",
|
||||
"iris.desktop.vision.refreshing": "重新整理",
|
||||
"iris.desktop.vision.fps": "{fps} FPS",
|
||||
"iris.desktop.vision.zoom_reset": "縮放重置",
|
||||
"iris.desktop.vision.grid_enabled": "已啟用網格",
|
||||
"iris.desktop.vision.grid_disabled": "已禁用網格",
|
||||
"iris.desktop.vision.entities_enabled": "實體已啟用",
|
||||
"iris.desktop.vision.entities_disabled": "實體已停用",
|
||||
"iris.desktop.vision.following": "跟蹤 {player}",
|
||||
"iris.desktop.vision.no_player": "世界上沒有玩家",
|
||||
"iris.desktop.vision.follow_disabled": "跟隨已禁用",
|
||||
|
||||
@@ -55,7 +55,7 @@ public class IrisLanguageTest {
|
||||
+ "|\\b[A-Za-z0-9_*{}.-]+\\.(?:json|toml|ya?ml|jar|nbt|iob|properties|log|zip)\\b"
|
||||
);
|
||||
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(
|
||||
"Iris Vision",
|
||||
@@ -66,7 +66,6 @@ public class IrisLanguageTest {
|
||||
"ResourceManager",
|
||||
"GoldenHash",
|
||||
"IGenData",
|
||||
"Sentry",
|
||||
"TectonicPlates"
|
||||
);
|
||||
private static final Pattern MARKER_DEBRIS = Pattern.compile("(?:⟬|⟭|\\b(?:XQ|QZ)[A-Z0-9_]*\\b|[\\uE000-\\uF8FF])");
|
||||
|
||||
@@ -47,7 +47,7 @@ public class IrisEnginePlatformHookIsolationTest {
|
||||
);
|
||||
|
||||
@Test
|
||||
public void sharedGeneratorHotPathsDoNotLinkBukkitImplementations() throws IOException {
|
||||
public void sharedGeneratorHotPathsDoNotLinkBukkitImplementations() throws IOException, ClassNotFoundException {
|
||||
assertNoClassLinks(IrisEngine.class, BUKKIT_ENGINE_CLASSES);
|
||||
assertNoClassLinks(EngineBackgroundTasks.class, BUKKIT_ENGINE_CLASSES);
|
||||
assertNoClassLinks(EngineDataStore.class, BUKKIT_ENGINE_CLASSES);
|
||||
@@ -56,6 +56,8 @@ public class IrisEnginePlatformHookIsolationTest {
|
||||
assertNoClassLinks(EngineRuntimeBuilder.class, BUKKIT_ENGINE_CLASSES);
|
||||
assertNoClassLinks(EngineShutdownSequence.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(EngineMode.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 {
|
||||
InputStream stream = type.getResourceAsStream(type.getSimpleName() + ".class");
|
||||
String resourceName = type.getName().substring(type.getName().lastIndexOf('.') + 1) + ".class";
|
||||
InputStream stream = type.getResourceAsStream(resourceName);
|
||||
assertNotNull(stream);
|
||||
String bytecode;
|
||||
try (InputStream input = stream) {
|
||||
|
||||
@@ -429,6 +429,28 @@ public class DecoratorCoreTest {
|
||||
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() {
|
||||
PlatformBlockState air = mock(PlatformBlockState.class);
|
||||
when(air.isAir()).thenReturn(true);
|
||||
|
||||
+54
-22
@@ -1,42 +1,74 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class PlatformStateHookContractTest {
|
||||
@Test
|
||||
public void missingPlatformRotatorFailsLoudly() {
|
||||
IllegalStateException error = assertThrows(IllegalStateException.class,
|
||||
() -> IrisObjectRotation.requirePlatformRotator(null));
|
||||
|
||||
assertEquals("No platform block-state rotator is bound", error.getMessage());
|
||||
public void boundRotatorWinsWhenBukkitClassesArePresent() {
|
||||
PlatformBlockState source = mock(PlatformBlockState.class);
|
||||
PlatformBlockState rotated = mock(PlatformBlockState.class);
|
||||
IrisObjectRotation.StateRotator hook = mock(IrisObjectRotation.StateRotator.class);
|
||||
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
|
||||
public void missingPlatformMergerFailsLoudly() {
|
||||
IllegalStateException error = assertThrows(IllegalStateException.class,
|
||||
() -> BlockDataMergeSupport.requirePlatformMerger(null));
|
||||
|
||||
assertEquals("No platform block-state merger is bound", error.getMessage());
|
||||
public void boundMergerWinsWhenBukkitClassesArePresent() {
|
||||
PlatformBlockState base = mock(PlatformBlockState.class);
|
||||
PlatformBlockState update = mock(PlatformBlockState.class);
|
||||
PlatformBlockState merged = mock(PlatformBlockState.class);
|
||||
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
|
||||
public void missingPlatformTileFactoryFailsLoudly() {
|
||||
IllegalStateException error = assertThrows(IllegalStateException.class,
|
||||
() -> TileData.requirePlatformFactory(null));
|
||||
|
||||
assertEquals("No platform tile-data factory is bound", error.getMessage());
|
||||
public void boundTileFactoryWinsWhenBukkitClassesArePresent() {
|
||||
PlatformBlockState state = mock(PlatformBlockState.class);
|
||||
KMap<String, Object> properties = new KMap<>();
|
||||
TileData expected = mock(TileData.class);
|
||||
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
|
||||
public void missingPlatformTileReaderFailsLoudly() {
|
||||
IOException error = assertThrows(IOException.class,
|
||||
() -> TileData.requirePlatformReader(null));
|
||||
|
||||
assertEquals("No platform tile-data reader is bound", error.getMessage());
|
||||
public void boundTileReaderWinsWhenBukkitClassesArePresent() throws IOException {
|
||||
TileData expected = mock(TileData.class);
|
||||
TileData.TileReader hook = mock(TileData.TileReader.class);
|
||||
DataInputStream input = new DataInputStream(new ByteArrayInputStream(new byte[0]));
|
||||
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.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.junit.Assume;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
@@ -102,6 +104,16 @@ public class BukkitSpiConformanceTest {
|
||||
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
|
||||
public void blockStateKeyMatchesCanonicalString() {
|
||||
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));
|
||||
}
|
||||
}
|
||||
+46
@@ -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
@@ -23,7 +23,7 @@ org.gradle.configureondemand=false
|
||||
|
||||
nmsTools.repo-url=https://repo.codemc.org/repository/nms/
|
||||
nmsTools.specialSourceVersion=1.11.4
|
||||
irisVersion=4.0.0-26.2
|
||||
irisVersion=4.0.1-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
|
||||
apiVersion=26.1
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
# Plugins
|
||||
shadow = "9.5.1" # https://plugins.gradle.org/plugin/com.gradleup.shadow
|
||||
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
|
||||
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/
|
||||
paperlib = "1.0.8" # https://github.com/PaperMC/PaperLib/
|
||||
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-lang3 = "3.20.0" # https://central.sonatype.com/artifact/org.apache.commons/commons-lang3
|
||||
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" }
|
||||
paperlib = { module = "io.papermc:paperlib", version.ref = "paperlib" }
|
||||
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-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commons-lang3" }
|
||||
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]
|
||||
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
||||
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" }
|
||||
|
||||
@@ -33,7 +33,6 @@ dependencies {
|
||||
runtimeOnly(libs.lz4)
|
||||
runtimeOnly(libs.zip)
|
||||
runtimeOnly(libs.guava)
|
||||
runtimeOnly(libs.sentry)
|
||||
runtimeOnly(libs.oshi)
|
||||
runtimeOnly(libs.byteBuddy.core)
|
||||
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.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.project.sentry.ServerID$Holder BUKKIT_API org.bukkit.Bukkit
|
||||
|
||||
|
@@ -66,6 +66,14 @@ public interface IrisPlatform {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user