From f50e964d4f53e36bb7f65852e8a695da02fc3ece Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Mon, 21 Jul 2025 17:14:45 +0200 Subject: [PATCH 1/9] hopefully fix unsafe mantle chunk operations --- .../com/volmit/iris/util/mantle/Mantle.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java index 6e1e56e54..6851c4cea 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -421,19 +421,19 @@ public class Mantle { throw new RuntimeException("The Mantle is closed"); } - adjustedIdleDuration.set(baseIdleDuration); + double idleDuration = baseIdleDuration; if (loadedRegions.size() > tectonicLimit) { // todo update this correctly and maybe do something when its above a 100% - adjustedIdleDuration.set(Math.max(adjustedIdleDuration.get() - (1000 * (((loadedRegions.size() - tectonicLimit) / (double) tectonicLimit) * 100) * 0.4), 4000)); + idleDuration = Math.max(idleDuration - (1000 * (((loadedRegions.size() - tectonicLimit) / (double) tectonicLimit) * 100) * 0.4), 4000); } + adjustedIdleDuration.set(idleDuration); ioTrim.set(true); try { - double adjustedIdleDuration = this.adjustedIdleDuration.get(); - Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration, 0)); + Iris.debug("Trimming Tectonic Plates older than " + Form.duration(idleDuration, 0)); if (lastUse.isEmpty()) return; - double unloadTime = M.ms() - adjustedIdleDuration; + double unloadTime = M.ms() - idleDuration; for (long id : lastUse.keySet()) { hyperLock.withLong(id, () -> { Long lastUseTime = lastUse.get(id); @@ -462,6 +462,7 @@ public class Mantle { ioTectonicUnload.set(true); try { for (long id : toUnload) { + double unloadTime = M.ms() - adjustedIdleDuration.get(); burst.queue(() -> hyperLock.withLong(id, () -> { TectonicPlate m = loadedRegions.get(id); if (m == null) { @@ -470,6 +471,11 @@ public class Mantle { return; } + var used = lastUse.getOrDefault(id, 0L); + if (!toUnload.contains(id) || used >= unloadTime) { + return; + } + if (m.inUse()) { Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ()); lastUse.put(id, M.ms()); @@ -522,9 +528,11 @@ public class Mantle { } } - TectonicPlate p = loadedRegions.get(key(x, z)); + Long key = key(x, z); + TectonicPlate p = loadedRegions.get(key); if (p != null) { + use(key); return p; } @@ -556,12 +564,12 @@ public class Mantle { TectonicPlate p = loadedRegions.get(k); if (p != null) { - lastUse.put(k, M.ms()); + use(k); return CompletableFuture.completedFuture(p); } return ioBurst.completeValue(() -> hyperLock.withResult(x, z, () -> { - lastUse.put(k, M.ms()); + use(k); TectonicPlate region = loadedRegions.get(k); if (region != null) { @@ -602,6 +610,11 @@ public class Mantle { })); } + private void use(Long key) { + lastUse.put(key, M.ms()); + toUnload.remove(key); + } + public void saveAll() { } From 9d6e4e87d8477aae5ef12e8f4d430b589f8c6acc Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Tue, 22 Jul 2025 12:11:41 +0200 Subject: [PATCH 2/9] fix custom blocks not placing --- core/src/main/java/com/volmit/iris/engine/framework/Engine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 010628b7d..1e39c8667 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -262,7 +262,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat getMantle().updateBlock(x, y, z); } if (data instanceof IrisCustomData) { - getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM, true); + getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM_ACTIVE, true); } } From fc54fcb7eb70c1206cb509806d029a6aa81a0398 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Tue, 22 Jul 2025 12:12:13 +0200 Subject: [PATCH 3/9] make itemsadder data provider standalone --- .../core/link/data/ItemAdderDataProvider.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/volmit/iris/core/link/data/ItemAdderDataProvider.java b/core/src/main/java/com/volmit/iris/core/link/data/ItemAdderDataProvider.java index c0bf27ef4..f030fc6a8 100644 --- a/core/src/main/java/com/volmit/iris/core/link/data/ItemAdderDataProvider.java +++ b/core/src/main/java/com/volmit/iris/core/link/data/ItemAdderDataProvider.java @@ -3,10 +3,14 @@ package com.volmit.iris.core.link.data; import com.volmit.iris.Iris; import com.volmit.iris.core.link.ExternalDataProvider; import com.volmit.iris.core.link.Identifier; +import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.data.B; +import com.volmit.iris.util.data.IrisCustomData; import dev.lone.itemsadder.api.CustomBlock; import dev.lone.itemsadder.api.CustomStack; +import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -40,7 +44,11 @@ public class ItemAdderDataProvider extends ExternalDataProvider { @NotNull @Override public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap state) throws MissingResourceException { - return CustomBlock.getBaseBlockData(blockId.toString()); + CustomBlock block = CustomBlock.getInstance(blockId.toString()); + if (block == null) { + throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()); + } + return new IrisCustomData(B.getAir(), blockId); } @NotNull @@ -53,6 +61,11 @@ public class ItemAdderDataProvider extends ExternalDataProvider { return stack.getItemStack(); } + @Override + public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) { + CustomBlock.place(blockId.toString(), block.getLocation()); + } + @Override public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) { return switch (dataType) { From 3949468a6080bbb4ba300ad936ff155b71f8932d Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Wed, 23 Jul 2025 14:45:54 +0200 Subject: [PATCH 4/9] inject into the library loader to make sure libraries can always be loaded --- .../com/volmit/iris/util/misc/SlimJar.java | 122 +++++++++++++++--- 1 file changed, 104 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/util/misc/SlimJar.java b/core/src/main/java/com/volmit/iris/util/misc/SlimJar.java index fa79b849d..e4c882b74 100644 --- a/core/src/main/java/com/volmit/iris/util/misc/SlimJar.java +++ b/core/src/main/java/com/volmit/iris/util/misc/SlimJar.java @@ -1,20 +1,35 @@ package com.volmit.iris.util.misc; +import com.volmit.iris.Iris; +import com.volmit.iris.core.nms.container.Pair; import io.github.slimjar.app.builder.ApplicationBuilder; +import io.github.slimjar.exceptions.InjectorException; +import io.github.slimjar.injector.loader.Injectable; +import io.github.slimjar.injector.loader.InjectableFactory; +import io.github.slimjar.injector.loader.IsolatedInjectableClassLoader; import io.github.slimjar.logging.ProcessLogger; +import io.github.slimjar.resolver.data.Repository; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BiFunction; +import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; public class SlimJar { - private static final Logger LOGGER = Logger.getLogger("Iris"); + private static final String NAME = "Iris"; + private static final Logger LOGGER = Logger.getLogger(NAME); private static final ReentrantLock lock = new ReentrantLock(); private static final AtomicBoolean loaded = new AtomicBoolean(); + private static final boolean DISABLE_REMAPPER = Boolean.getBoolean("iris.disable-remapper"); public static void debug(boolean debug) { LOGGER.setLevel(debug ? Level.FINE : Level.INFO); @@ -31,28 +46,99 @@ public class SlimJar { } LOGGER.info("Loading libraries..."); - ApplicationBuilder.appending("Iris") - .downloadDirectoryPath(localRepository.toPath()) - .logger(new ProcessLogger() { - @Override - public void info(@NotNull String message, @Nullable Object... args) { - LOGGER.fine(message.formatted(args)); - } + load(localRepository.toPath(), new ProcessLogger() { + @Override + public void info(@NotNull String message, @Nullable Object... args) { + LOGGER.fine(message.formatted(args)); + } - @Override - public void error(@NotNull String message, @Nullable Object... args) { - LOGGER.severe(message.formatted(args)); - } + @Override + public void error(@NotNull String message, @Nullable Object... args) { + LOGGER.severe(message.formatted(args)); + } - @Override - public void debug(@NotNull String message, @Nullable Object... args) { - LOGGER.fine(message.formatted(args)); - } - }) - .build(); + @Override + public void debug(@NotNull String message, @Nullable Object... args) { + LOGGER.fine(message.formatted(args)); + } + }); LOGGER.info("Libraries loaded successfully!"); } finally { lock.unlock(); } } + + private static void load(Path downloadPath, ProcessLogger logger) { + try { + loadSpigot(downloadPath, logger); + } catch (Throwable e) { + Iris.warn("Failed to inject the library loader, falling back to application builder"); + ApplicationBuilder.appending(NAME) + .downloadDirectoryPath(downloadPath) + .logger(logger) + .build(); + } + } + + private static void loadSpigot(Path downloadPath, ProcessLogger logger) throws Throwable { + var current = SlimJar.class.getClassLoader(); + var libraryLoader = current.getClass().getDeclaredField("libraryLoader"); + libraryLoader.setAccessible(true); + if (!ClassLoader.class.isAssignableFrom(libraryLoader.getType())) throw new IllegalStateException("Failed to find library loader"); + + final var pair = findRemapper(); + final var remapper = pair.getA(); + final var factory = pair.getB(); + + final var libraries = factory.apply(new URL[0], current.getParent()); + final var injecting = InjectableFactory.create(downloadPath, List.of(Repository.central()), libraries); + + ApplicationBuilder.injecting(NAME, new Injectable() { + @Override + public void inject(@NotNull URL url) throws InjectorException { + try { + final List mapped; + synchronized (remapper) { + mapped = remapper.apply(List.of(Path.of(url.toURI()))); + } + + for (final Path path : mapped) { + injecting.inject(path.toUri().toURL()); + } + } catch (Throwable e) { + throw new InjectorException("Failed to inject " + url, e); + } + } + + @Override + public boolean isThreadSafe() { + return injecting.isThreadSafe(); + } + }) + .downloadDirectoryPath(downloadPath) + .logger(logger) + .build(); + + libraryLoader.set(current, libraries); + } + + private static Pair, List>, BiFunction> findRemapper() { + Function, List> mapper = null; + BiFunction factory = null; + if (!DISABLE_REMAPPER) { + try { + var libraryLoader = Class.forName("org.bukkit.plugin.java.LibraryLoader"); + var mapperField = libraryLoader.getDeclaredField("REMAPPER"); + var factoryField = libraryLoader.getDeclaredField("LIBRARY_LOADER_FACTORY"); + mapperField.setAccessible(true); + factoryField.setAccessible(true); + mapper = (Function, List>) mapperField.get(null); + factory = (BiFunction) factoryField.get(null); + } catch (Throwable ignored) {} + } + + if (mapper == null) mapper = Function.identity(); + if (factory == null) factory = (urls, parent) -> new IsolatedInjectableClassLoader(urls, List.of(), parent); + return new Pair<>(mapper, factory); + } } From e5f2fee926045c983053f6de520c7c499518db62 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Wed, 23 Jul 2025 15:07:06 +0200 Subject: [PATCH 5/9] add info about used commit to sentry reports --- core/build.gradle.kts | 8 ++++++++ .../src/main/java/com/volmit/iris/util/misc/Bindings.java | 7 +++++++ core/src/main/resources/plugin.yml | 2 ++ 3 files changed, 17 insertions(+) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ef7cc7168..a559f2b7f 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -137,6 +137,14 @@ tasks { "version" to rootProject.version, "apiVersion" to apiVersion, "main" to main, + "environment" to if (project.hasProperty("release")) "production" else "development", + "commit" to provider { + ProcessBuilder("git", "rev-parse", "HEAD") + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .start() + .inputStream.bufferedReader().readText().trim() + .takeIf { it.length == 40 } ?: "unknown" + } ) filesMatching("**/plugin.yml") { expand(inputs.properties) diff --git a/core/src/main/java/com/volmit/iris/util/misc/Bindings.java b/core/src/main/java/com/volmit/iris/util/misc/Bindings.java index 308d3d235..6dea9f4a8 100644 --- a/core/src/main/java/com/volmit/iris/util/misc/Bindings.java +++ b/core/src/main/java/com/volmit/iris/util/misc/Bindings.java @@ -23,9 +23,11 @@ import org.bstats.charts.SimplePie; import org.bstats.charts.SingleLineChart; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import oshi.SystemInfo; +import java.io.InputStreamReader; import java.math.RoundingMode; import java.text.NumberFormat; import java.util.HashMap; @@ -45,6 +47,9 @@ public class Bindings { if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) return; Iris.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings."); Iris.info("Your server ID is: " + ServerID.ID); + var resource = Iris.instance.getResource("plugin.yml"); + YamlConfiguration desc = resource != null ? YamlConfiguration.loadConfiguration(new InputStreamReader(resource)) : new YamlConfiguration(); + Sentry.init(options -> { options.setDsn("https://b16ecc222e9c1e0c48faecacb906fd89@o4509451052646400.ingest.de.sentry.io/4509452722765904"); if (settings.debug) { @@ -55,6 +60,7 @@ public class Bindings { options.setAttachServerName(false); options.setEnableUncaughtExceptionHandler(false); options.setRelease(Iris.instance.getDescription().getVersion()); + options.setEnvironment(desc.getString("environment", "production")); options.setBeforeSend((event, hint) -> { if (suppress(event.getThrowable())) return null; event.setTag("iris.safeguard", IrisSafeguard.mode()); @@ -71,6 +77,7 @@ public class Bindings { scope.setTag("server", Bukkit.getVersion()); scope.setTag("server.type", Bukkit.getName()); scope.setTag("server.api", Bukkit.getBukkitVersion()); + scope.setTag("iris.commit", desc.getString("commit", "unknown")); }); Runtime.getRuntime().addShutdownHook(new Thread(Sentry::close)); } diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index 99fa326be..f871ec1e3 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -5,6 +5,8 @@ load: STARTUP authors: [ cyberpwn, NextdoorPsycho, Vatuu ] website: volmit.com description: More than a Dimension! +environment: '${environment}' +commit: '${commit}' commands: iris: aliases: [ ir, irs ] From 16a4d20c90352ff579497c5368e058084b5d1bc1 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Wed, 23 Jul 2025 18:06:52 +0200 Subject: [PATCH 6/9] use grgit to resolve current commit --- core/build.gradle.kts | 9 ++++----- gradle/libs.versions.toml | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index a559f2b7f..ef3c51465 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -26,6 +26,7 @@ plugins { alias(libs.plugins.shadow) alias(libs.plugins.sentry) alias(libs.plugins.slimjar) + alias(libs.plugins.grgit) } val apiVersion = "1.19" @@ -139,11 +140,9 @@ tasks { "main" to main, "environment" to if (project.hasProperty("release")) "production" else "development", "commit" to provider { - ProcessBuilder("git", "rev-parse", "HEAD") - .redirectOutput(ProcessBuilder.Redirect.PIPE) - .start() - .inputStream.bufferedReader().readText().trim() - .takeIf { it.length == 40 } ?: "unknown" + runCatching { grgit.head().id } + .getOrDefault("") + .takeIf { it.length == 40 } ?: "unknown" } ) filesMatching("**/plugin.yml") { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f697c836e..cc74057db 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,6 +9,7 @@ slimjar = "2.0.8" # https://plugins.gradle.org/plugin/de.crazydev22.slimjar download = "5.6.0" # https://plugins.gradle.org/plugin/de.undercouch.download runPaper = "2.3.1" # https://plugins.gradle.org/plugin/xyz.jpenilla.run-paper sentryPlugin = "5.8.0" # https://github.com/getsentry/sentry-android-gradle-plugin +grgit = "5.3.2" # https://github.com/ajoberstar/grgit # Core Libraries lombok = "1.18.38" @@ -100,3 +101,4 @@ slimjar = { id = "de.crazydev22.slimjar", version.ref = "slimjar" } download = { id = "de.undercouch.download", version.ref = "download" } runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" } sentry = { id = "io.sentry.jvm.gradle", version.ref = "sentryPlugin" } +grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" } From 556bef6e4309440da14ca18a47537009920794f8 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Fri, 25 Jul 2025 12:44:01 +0200 Subject: [PATCH 7/9] fix more unsafe mantle chunk accesses --- .../com/volmit/iris/util/mantle/Mantle.java | 90 ++++++++++--------- .../iris/util/mantle/TectonicPlate.java | 8 ++ 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java index 6851c4cea..c48c43bd8 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -47,7 +47,6 @@ import org.bukkit.Chunk; import java.io.EOFException; import java.io.File; import java.io.IOException; -import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -58,16 +57,18 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class Mantle { + private static final int LOCK_SIZE = Short.MAX_VALUE; + private final File dataFolder; @Getter private final int worldHeight; - private final Map lastUse; - private final Map loadedRegions; + private final KMap lastUse; + private final KMap loadedRegions; private final HyperLock hyperLock; private final AtomicBoolean closed; private final MultiBurst ioBurst; - private final AtomicBoolean ioTrim; - private final AtomicBoolean ioTectonicUnload; + private final Semaphore ioTrim; + private final Semaphore ioTectonicUnload; private final AtomicDouble adjustedIdleDuration; private final KSet toUnload; @@ -83,8 +84,8 @@ public class Mantle { this.closed = new AtomicBoolean(false); this.dataFolder = dataFolder; this.worldHeight = worldHeight; - this.ioTrim = new AtomicBoolean(false); - this.ioTectonicUnload = new AtomicBoolean(false); + this.ioTrim = new Semaphore(LOCK_SIZE, true); + this.ioTectonicUnload = new Semaphore(LOCK_SIZE, true); loadedRegions = new KMap<>(); lastUse = new KMap<>(); ioBurst = MultiBurst.burst; @@ -428,7 +429,7 @@ public class Mantle { } adjustedIdleDuration.set(idleDuration); - ioTrim.set(true); + ioTrim.acquireUninterruptibly(LOCK_SIZE); try { Iris.debug("Trimming Tectonic Plates older than " + Form.duration(idleDuration, 0)); @@ -446,7 +447,7 @@ public class Mantle { } catch (Throwable e) { Iris.reportError(e); } finally { - ioTrim.set(false); + ioTrim.release(LOCK_SIZE); } } @@ -459,7 +460,7 @@ public class Mantle { BurstExecutor burst = ioBurst.burst(toUnload.size()); burst.setMulticore(toUnload.size() > tectonicLimit); - ioTectonicUnload.set(true); + ioTectonicUnload.acquireUninterruptibly(LOCK_SIZE); try { for (long id : toUnload) { double unloadTime = M.ms() - adjustedIdleDuration.get(); @@ -478,15 +479,14 @@ public class Mantle { if (m.inUse()) { Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ()); - lastUse.put(id, M.ms()); - toUnload.remove(id); + use(id); return; } try { m.write(fileForRegion(dataFolder, id, false)); oldFileForRegion(dataFolder, id).delete(); - loadedRegions.remove(id); + loadedRegions.remove(id, m); lastUse.remove(id); toUnload.remove(id); i.incrementAndGet(); @@ -502,7 +502,7 @@ public class Mantle { e.printStackTrace(); burst.complete(); } finally { - ioTectonicUnload.set(false); + ioTectonicUnload.release(LOCK_SIZE); } return i.get(); } @@ -518,32 +518,39 @@ public class Mantle { */ @RegionCoordinates private TectonicPlate get(int x, int z) { - if (ioTrim.get() || ioTectonicUnload.get()) { + boolean trim = ioTrim.tryAcquire(); + boolean unload = ioTectonicUnload.tryAcquire(); + try { + if (!trim || !unload) { + try { + return getSafe(x, z).get(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + Long key = key(x, z); + TectonicPlate p = loadedRegions.get(key); + + if (p != null && !p.isClosed()) { + use(key); + return p; + } + try { return getSafe(x, z).get(); } catch (InterruptedException e) { - e.printStackTrace(); + Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread intterruption (hotload?)"); + Iris.reportError(e); } catch (ExecutionException e) { - e.printStackTrace(); + Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread execution exception (engine close?)"); + Iris.reportError(e); } - } - - Long key = key(x, z); - TectonicPlate p = loadedRegions.get(key); - - if (p != null) { - use(key); - return p; - } - - try { - return getSafe(x, z).get(); - } catch (InterruptedException e) { - Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread intterruption (hotload?)"); - Iris.reportError(e); - } catch (ExecutionException e) { - Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread execution exception (engine close?)"); - Iris.reportError(e); + } finally { + if (trim) ioTrim.release(); + if (unload) ioTectonicUnload.release(); } Iris.warn("Retrying to get " + x + " " + z + " Mantle Region"); @@ -560,19 +567,12 @@ public class Mantle { */ @RegionCoordinates private Future getSafe(int x, int z) { - Long k = key(x, z); - TectonicPlate p = loadedRegions.get(k); - - if (p != null) { - use(k); - return CompletableFuture.completedFuture(p); - } - return ioBurst.completeValue(() -> hyperLock.withResult(x, z, () -> { + Long k = key(x, z); use(k); TectonicPlate region = loadedRegions.get(k); - if (region != null) { + if (region != null && !region.isClosed()) { return region; } @@ -600,12 +600,14 @@ public class Mantle { Iris.debug("Created new Tectonic Plate (Due to Load Failure) " + C.DARK_GREEN + x + " " + z); } + use(k); return region; } region = new TectonicPlate(worldHeight, x, z); loadedRegions.put(k, region); Iris.debug("Created new Tectonic Plate " + C.DARK_GREEN + x + " " + z); + use(k); return region; })); } diff --git a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java index 101019023..181ce9cd2 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java @@ -39,6 +39,7 @@ import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReferenceArray; /** @@ -52,6 +53,7 @@ public class TectonicPlate { private final int sectionHeight; private final AtomicReferenceArray chunks; + private final AtomicBoolean closed; @Getter private final int x; @@ -67,6 +69,7 @@ public class TectonicPlate { public TectonicPlate(int worldHeight, int x, int z) { this.sectionHeight = worldHeight >> 4; this.chunks = new AtomicReferenceArray<>(1024); + this.closed = new AtomicBoolean(false); this.x = x; this.z = z; } @@ -143,6 +146,7 @@ public class TectonicPlate { } public void close() throws InterruptedException { + closed.set(true); for (int i = 0; i < chunks.length(); i++) { MantleChunk chunk = chunks.get(i); if (chunk != null) { @@ -151,6 +155,10 @@ public class TectonicPlate { } } + public boolean isClosed() { + return closed.get(); + } + /** * Check if a chunk exists in this plate or not (same as get(x, z) != null) * From 08b9058c8f0ba3ee967da80b46caaf295627b4df Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Fri, 25 Jul 2025 13:07:13 +0200 Subject: [PATCH 8/9] make git commit retrieval fail safe --- core/build.gradle.kts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ef3c51465..7365bde48 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,6 @@ import io.github.slimjar.func.slimjar import io.github.slimjar.resolver.data.Mirror +import org.ajoberstar.grgit.Grgit import java.net.URI /* @@ -140,10 +141,13 @@ tasks { "main" to main, "environment" to if (project.hasProperty("release")) "production" else "development", "commit" to provider { - runCatching { grgit.head().id } + runCatching { extensions.getByType().head().id } .getOrDefault("") - .takeIf { it.length == 40 } ?: "unknown" - } + .takeIf { it.length == 40 } ?: { + project.logger.error("Git commit hash not found") + "unknown" + }() + }, ) filesMatching("**/plugin.yml") { expand(inputs.properties) From b0ca0e36170c668fe15a5aeeef8a0b497b3cc077 Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Fri, 25 Jul 2025 13:21:16 +0200 Subject: [PATCH 9/9] whoops messed up the extension retrieval --- core/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 7365bde48..7f8361822 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -141,10 +141,10 @@ tasks { "main" to main, "environment" to if (project.hasProperty("release")) "production" else "development", "commit" to provider { - runCatching { extensions.getByType().head().id } - .getOrDefault("") + val res = runCatching { project.extensions.getByType().head().id } + res.getOrDefault("") .takeIf { it.length == 40 } ?: { - project.logger.error("Git commit hash not found") + logger.error("Git commit hash not found", res.exceptionOrNull()) "unknown" }() },