9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-19 15:09:18 +00:00

Compare commits

...

16 Commits
master ... dev

Author SHA1 Message Date
Julian Krings
3abe671851 suppress unchecked cast warning for the ChunkedDataCache 2025-12-18 18:53:59 +01:00
Julian Krings
e164a3bb5c Merge branch 'feat/safeguard' into dev
# Conflicts:
#	build.gradle.kts
#	core/src/main/java/com/volmit/iris/Iris.java
2025-12-18 18:44:36 +01:00
Julian Krings
4dfb4441e4 fix buildscript 2025-12-18 14:23:51 +01:00
Julian Krings
e686f67453 add command to fix offsets of all objects 2025-12-18 14:23:35 +01:00
Julian Krings
e2eed4812a ignore empty objects for shrinkwrap 2025-12-18 14:22:40 +01:00
Julian Krings
1737833bfe fix legacy object parsing 2025-12-18 14:22:21 +01:00
piexel
a4c5f46c37 Fix /iris object convert for .schem files with 128+ block types 2025-12-18 11:25:38 +01:00
piexel
025fa833c4 Fix Grass won't place on moss blocks 2025-12-18 11:21:16 +01:00
Julian Krings
98cc82cc3d Fix jigsaw editor bricking when opening a piece a missing object 2025-12-18 11:13:43 +01:00
Julian Krings
298365f588 fix studio open not working when not in spectator 2025-12-18 11:06:09 +01:00
Julian Krings
90e5720e2e improve buildscript 2025-12-18 11:05:28 +01:00
Julian Krings
7cd43791f4 fix offset with shrinkwrap 2025-12-18 11:05:14 +01:00
Julian Krings
a251d192ad fix loot for objects underground 2025-12-18 11:00:04 +01:00
Julian Krings
abfff28f43 fix redstone not rotating 2025-12-18 10:59:57 +01:00
Julian Krings
fbdae4c928 improve overwriting of the regenerated chunks 2025-12-18 10:59:32 +01:00
Julian Krings
526efd3ae1 restructure safeguard 2025-09-29 15:45:56 +02:00
29 changed files with 798 additions and 675 deletions

View File

@@ -60,7 +60,7 @@ val serverMaxHeap = "10G"
val additionalFlags = "-XX:+AlwaysPreTouch"
//Valid values are: none, truecolor, indexed256, indexed16, indexed8
val color = "truecolor"
val errorReporting = findProperty("errorReporting") as Boolean? ?: false
val errorReporting = "true" == findProperty("errorReporting")
val nmsBindings = mapOf(
"v1_21_R6" to "1.21.10-R0.1-SNAPSHOT",
@@ -109,19 +109,21 @@ nmsBindings.forEach { (key, value) ->
}
}
val included: Configuration by configurations.creating
val jarJar: Configuration by configurations.creating
dependencies {
for (key in nmsBindings.keys) {
implementation(project(":nms:$key", "reobf"))
included(project(":nms:$key", "reobf"))
}
implementation(project(":core", "shadow"))
included(project(":core", "shadow"))
jarJar(project(":core:agent"))
}
tasks {
jar {
inputs.files(included)
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from(jarJar, configurations.runtimeClasspath.map { it.resolve().map(::zipTree) })
from(jarJar, provider { included.resolve().map(::zipTree) })
archiveFileName.set("Iris-${project.version}.jar")
}

View File

@@ -115,7 +115,7 @@ java {
}
sentry {
url = "http://sentry.volmit.com:8080/"
url = "http://sentry.volmit.com:8080"
autoInstallation.enabled = false
includeSourceContext = true
@@ -175,6 +175,10 @@ tasks {
relocate("io.github.slimjar", "$lib.slimjar")
exclude("modules/loader-agent.isolated-jar")
}
sentryCollectSourcesJava {
dependsOn(generateTemplates)
}
}
val templateSource = file("src/main/templates")
@@ -185,10 +189,10 @@ val generateTemplates = tasks.register<Copy>("generateTemplates") {
"commit" to provider {
val res = runCatching { project.extensions.getByType<Grgit>().head().id }
res.getOrDefault("")
.takeIf { it.length == 40 } ?: {
logger.error("Git commit hash not found", res.exceptionOrNull())
.takeIf { it.length == 40 } ?: run {
this.logger.error("Git commit hash not found", res.exceptionOrNull())
"unknown"
}()
}
},
)

View File

@@ -28,7 +28,6 @@ import com.volmit.iris.core.link.IrisPapiExpansion;
import com.volmit.iris.core.link.MultiverseCoreLink;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import com.volmit.iris.core.pregenerator.LazyPregenerator;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisToolbelt;
@@ -43,7 +42,6 @@ import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.NastyRunnable;
import com.volmit.iris.util.io.FileWatcher;
import com.volmit.iris.util.io.IO;
@@ -53,7 +51,6 @@ import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.Bindings;
import com.volmit.iris.util.misc.SlimJar;
import com.volmit.iris.util.misc.getHardware;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitPlugin;
@@ -84,9 +81,6 @@ import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
@SuppressWarnings("CanBeFinal")
public class Iris extends VolmitPlugin implements Listener {
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
@@ -308,9 +302,6 @@ public class Iris extends VolmitPlugin implements Listener {
public static void info(String format, Object... args) {
msg(C.WHITE + String.format(format, args));
}
public static void safeguard(String format, Object... args) {
msg(C.RESET + String.format(format, args));
}
@SuppressWarnings("deprecation")
public static void later(NastyRunnable object) {
@@ -449,9 +440,9 @@ public class Iris extends VolmitPlugin implements Listener {
IO.delete(new File("iris"));
compat = IrisCompat.configured(getDataFile("compat.json"));
ServerConfigurator.configure();
IrisSafeguard.IrisSafeguardSystem();
IrisSafeguard.execute();
getSender().setTag(getTag());
IrisSafeguard.splash(true);
IrisSafeguard.splash();
tickets = new ChunkTickets();
linkMultiverseCore = new MultiverseCoreLink();
configWatcher = new FileWatcher(getDataFile("settings.json"));
@@ -459,7 +450,6 @@ public class Iris extends VolmitPlugin implements Listener {
services.values().forEach(this::registerListener);
addShutdownHook();
J.s(() -> {
J.a(IrisSafeguard::suggestPaper);
J.a(() -> IO.delete(getTemp()));
J.a(LazyPregenerator::loadLazyGenerators, 100);
J.a(this::bstats);
@@ -467,7 +457,6 @@ public class Iris extends VolmitPlugin implements Listener {
J.sr(this::tickQueue, 0);
J.s(this::setupPapi);
J.a(ServerConfigurator::configure, 20);
IrisSafeguard.splash(false);
autoStartStudio();
checkForBukkitWorlds(s -> true);
@@ -529,9 +518,10 @@ public class Iris extends VolmitPlugin implements Listener {
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
J.s(() -> {
var spawn = w.getSpawnLocation();
for (Player i : getServer().getOnlinePlayers()) {
i.setGameMode(GameMode.SPECTATOR);
i.teleport(new Location(w, 0, 200, 0));
i.teleport(spawn);
}
});
});
@@ -560,10 +550,10 @@ public class Iris extends VolmitPlugin implements Listener {
enable();
super.onEnable();
Bukkit.getPluginManager().registerEvents(this, this);
setupChecks();
}
public void onDisable() {
if (IrisSafeguard.isForceShutdown()) return;
services.values().forEach(IrisService::onDisable);
Bukkit.getScheduler().cancelTasks(this);
HandlerList.unregisterAll((Plugin) this);
@@ -591,49 +581,7 @@ public class Iris extends VolmitPlugin implements Listener {
@Override
public String getTag(String subTag) {
if (unstablemode) {
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
}
if (warningmode) {
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.GOLD + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
}
return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.IRIS + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": ";
}
private boolean setupChecks() {
boolean passed = true;
Iris.info("Version Information: " + instance.getServer().getVersion() + " | " + instance.getServer().getBukkitVersion());
if (INMS.get() instanceof NMSBinding1X) {
passed = false;
Iris.warn("============================================");
Iris.warn("=");
Iris.warn("=");
Iris.warn("=");
Iris.warn("Iris is not compatible with this version of Minecraft.");
Iris.warn("=");
Iris.warn("=");
Iris.warn("=");
Iris.warn("============================================");
}
try {
Class.forName("io.papermc.paper.configuration.PaperConfigurations");
} catch (ClassNotFoundException e) {
Iris.info(C.RED + "Iris requires paper or above to function properly..");
return false;
}
try {
Class.forName("org.purpurmc.purpur.PurpurConfig");
} catch (ClassNotFoundException e) {
Iris.info("We recommend using Purpur for the best experience with Iris.");
Iris.info("Purpur is a fork of Paper that is optimized for performance and stability.");
Iris.info("Plugins that work on Spigot / Paper work on Purpur.");
Iris.info("You can download it here: https://purpurmc.org");
return false;
}
return passed;
return IrisSafeguard.mode().tag(subTag);
}
private void checkConfigHotload() {
@@ -741,88 +689,11 @@ public class Iris extends VolmitPlugin implements Listener {
}
public void splash() {
if (!IrisSettings.get().getGeneral().isSplashLogoStartup()) {
return;
}
String padd = Form.repeat(" ", 8);
String padd2 = Form.repeat(" ", 4);
String[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "<rainbow>Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion()};
if (unstablemode) {
info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + getDescription().getVersion()};
}
if (warningmode) {
info = new String[]{"", "", "", "", "", padd2 + C.GOLD + " Iris", padd2 + C.GRAY + " by " + C.GOLD + "Volmit Software", padd2 + C.GRAY + " v" + C.GOLD + getDescription().getVersion()};
}
String[] splashstable = {
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.IRIS + " .(((()))). ",
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.IRIS + " .((((((())))))). ",
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.IRIS + " ((((((((())))))))) " + C.GRAY + " @",
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.IRIS + " ((((((((-))))))))) " + C.GRAY + " @@",
padd + C.GRAY + "@@@&&" + C.IRIS + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
padd + C.GRAY + "@@" + C.IRIS + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
padd + C.GRAY + "@" + C.IRIS + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
padd + C.GRAY + "" + C.IRIS + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
padd + C.GRAY + "" + C.IRIS + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
};
String[] splashunstable = {
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.RED + " .(((()))). ",
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.RED + " .((((((())))))). ",
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.RED + " ((((((((())))))))) " + C.GRAY + " @",
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.RED + " ((((((((-))))))))) " + C.GRAY + " @@",
padd + C.GRAY + "@@@&&" + C.RED + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
padd + C.GRAY + "@@" + C.RED + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
padd + C.GRAY + "@" + C.RED + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
padd + C.GRAY + "" + C.RED + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
padd + C.GRAY + "" + C.RED + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
};
String[] splashwarning = {
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.GOLD + " .(((()))). ",
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.GOLD + " .((((((())))))). ",
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.GOLD + " ((((((((())))))))) " + C.GRAY + " @",
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.GOLD + " ((((((((-))))))))) " + C.GRAY + " @@",
padd + C.GRAY + "@@@&&" + C.GOLD + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
padd + C.GRAY + "@@" + C.GOLD + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
padd + C.GRAY + "@" + C.GOLD + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
padd + C.GRAY + "" + C.GOLD + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
padd + C.GRAY + "" + C.GOLD + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@"
};
String[] splash;
File freeSpace = new File(Bukkit.getWorldContainer() + ".");
if (unstablemode) {
splash = splashunstable;
} else if (warningmode) {
splash = splashwarning;
} else {
splash = splashstable;
}
if (!passedserversoftware) {
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
Iris.info("Java: " + getJava());
if (getHardware.getProcessMemory() < 5999) {
Iris.warn("6GB+ Ram is recommended");
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
}
Iris.info("Bukkit distro: " + Bukkit.getName());
Iris.info("Server type & version: " + Bukkit.getName() + " v" + Bukkit.getVersion());
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
setupChecks();
printPacks();
for (int i = 0; i < info.length; i++) {
splash[i] += info[i];
}
Iris.info("\n\n " + new KList<>(splash).toString("\n") + "\n");
IrisSafeguard.mode().trySplash();
}
private void printPacks() {

View File

@@ -31,7 +31,9 @@ import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisPosition;
import com.volmit.iris.engine.object.annotations.Snippet;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
@@ -52,6 +54,7 @@ import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.jobs.Job;
import lombok.SneakyThrows;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
@@ -92,6 +95,124 @@ public class CommandDeveloper implements DecreeExecutor {
Iris.reportError(new Exception("This is a test"));
}
@Decree(description = "Dev cmd to fix all the broken objects caused by faulty shrinkwarp")
public void fixObjects(
@Param(aliases = "dimension", description = "The dimension type to create the world with")
IrisDimension type
) {
if (type == null) {
sender().sendMessage("Type cant be null?");
return;
}
IrisData dm = IrisData.get(Iris.instance.getDataFolder("packs", type.getLoadKey()));
var loader = dm.getObjectLoader();
var processed = new KMap<String, IrisPosition>();
var objects = loader.getPossibleKeys();
var pieces = dm.getJigsawPieceLoader().getPossibleKeys();
var sender = sender();
sender.sendMessage(C.IRIS + "Found " + objects.length + " objects in " + type.getLoadKey());
sender.sendMessage(C.IRIS + "Found " + pieces.length + " jigsaw pieces in " + type.getLoadKey());
final int total = objects.length;
final AtomicInteger completed = new AtomicInteger();
final AtomicInteger changed = new AtomicInteger();
new Job() {
@Override
public String getName() {
return "Fixing Objects";
}
@Override
public void execute() {
Arrays.stream(pieces).parallel()
.map(dm.getJigsawPieceLoader()::load)
.filter(Objects::nonNull)
.forEach(piece -> {
var offset = processed.compute(piece.getObject(), (key, o) -> {
if (o != null) return o;
var obj = loader.load(key);
if (obj == null) return new IrisPosition();
obj.shrinkwrap();
try {
if (!obj.getShrinkOffset().isZero()) {
changed.incrementAndGet();
obj.write(obj.getLoadFile());
}
completeWork();
} catch (IOException e) {
Iris.error("Failed to write object " + obj.getLoadKey());
e.printStackTrace();
return new IrisPosition();
}
return new IrisPosition(obj.getShrinkOffset());
});
if (offset.getX() == 0 && offset.getY() == 0 && offset.getZ() == 0)
return;
piece.getConnectors().forEach(connector -> connector.setPosition(connector.getPosition().add(offset)));
try {
IO.writeAll(piece.getLoadFile(), dm.getGson().toJson(piece));
} catch (IOException e) {
Iris.error("Failed to write jigsaw piece " + piece.getLoadKey());
e.printStackTrace();
}
});
Arrays.stream(loader.getPossibleKeys()).parallel()
.filter(key -> !processed.containsKey(key))
.map(loader::load)
.forEach(obj -> {
if (obj == null) {
completeWork();
return;
}
obj.shrinkwrap();
if (obj.getShrinkOffset().isZero()) {
completeWork();
return;
}
try {
obj.write(obj.getLoadFile());
completeWork();
changed.incrementAndGet();
} catch (IOException e) {
Iris.error("Failed to write object " + obj.getLoadKey());
e.printStackTrace();
}
});
}
@Override
public void completeWork() {
completed.incrementAndGet();
}
@Override
public int getTotalWork() {
return total;
}
@Override
public int getWorkCompleted() {
return completed.get();
}
}.execute(sender, () -> {
var failed = total - completed.get();
if (failed != 0) sender.sendMessage(C.IRIS + "" + failed + " objects failed!");
if (changed.get() != 0) sender.sendMessage(C.IRIS + "" + changed.get() + " objects had their offsets changed!");
else sender.sendMessage(C.IRIS + "No objects had their offsets changed!");
});
}
@Decree(description = "Test")
public void mantle(@Param(defaultValue = "false") boolean plate, @Param(defaultValue = "21474836474") String name) throws Throwable {
var base = Iris.instance.getDataFile("dump", "pv." + name + ".ttp.lz4b.bin");

View File

@@ -222,22 +222,8 @@ public class CommandStudio implements DecreeExecutor {
job.execute(sender(), latch::countDown);
latch.await();
int sections = mantle.getWorldHeight() >> 4;
chunkMap.forEach((pos, chunk) -> {
var c = mantle.getChunk(pos.getX(), pos.getZ()).use();
try {
c.copyFlags(chunk);
c.clear();
for (int y = 0; y < sections; y++) {
var slice = chunk.get(y);
if (slice == null) continue;
var s = c.getOrCreate(y);
slice.getSliceMap().forEach(s::putSlice);
}
} finally {
c.release();
}
});
chunkMap.forEach((pos, chunk) ->
mantle.getChunk(pos.getX(), pos.getZ()).copyFrom(chunk));
} catch (Throwable e) {
sender().sendMessage("Error while regenerating chunks");
e.printStackTrace();
@@ -702,8 +688,14 @@ public class CommandStudio implements DecreeExecutor {
}
sender().sendMessage(C.GREEN + "Sending you to the studio world!");
player().teleport(Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getTarget().getWorld().spawnLocation());
player().setGameMode(GameMode.SPECTATOR);
var player = player();
PaperLib.teleportAsync(player(), Iris.service(StudioSVC.class)
.getActiveProject()
.getActiveProvider()
.getTarget()
.getWorld()
.spawnLocation()
).thenRun(() -> player.setGameMode(GameMode.SPECTATOR));
}
@Decree(description = "Update your dimension projects VSCode workspace")

View File

@@ -61,14 +61,14 @@ public class JigsawEditor implements Listener {
private Location target;
public JigsawEditor(Player player, IrisJigsawPiece piece, IrisObject object, File saveLocation) {
if (editors.containsKey(player)) {
editors.get(player).close();
}
if (object == null) throw new RuntimeException("Object is null! " + piece.getObject());
editors.compute(player, ($, current) -> {
if (current != null) {
current.exit();
}
return this;
});
editors.put(player, this);
if (object == null) {
throw new RuntimeException("Object is null! " + piece.getObject());
}
this.object = object;
this.player = player;
origin = player.getLocation().clone().add(0, 7, 0);

View File

@@ -225,7 +225,7 @@ public class IrisProject {
sender.sendMessage("Can't find dimension: " + getName());
return;
} else if (sender.isPlayer()) {
sender.player().setGameMode(GameMode.SPECTATOR);
J.s(() -> sender.player().setGameMode(GameMode.SPECTATOR));
}
try {

View File

@@ -1,64 +0,0 @@
package com.volmit.iris.core.safeguard;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import io.papermc.lib.PaperLib;
import java.util.concurrent.atomic.AtomicBoolean;
public class IrisSafeguard {
private static final AtomicBoolean sfg = new AtomicBoolean(false);
public static boolean unstablemode = false;
public static boolean warningmode = false;
public static boolean stablemode = false;
public static void IrisSafeguardSystem() {
Iris.info("Enabled Iris SafeGuard");
ServerBootSFG.BootCheck();
}
public static void splash(boolean early) {
if (early && (ServerBootSFG.safeguardPassed || IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode))
return;
if (!sfg.getAndSet(true)) {
Iris.instance.splash();
UtilsSFG.splash();
}
}
public static String mode() {
if (unstablemode) {
return "unstable";
} else if (warningmode) {
return "warning";
} else {
return "stable";
}
}
public static void suggestPaper() {
PaperLib.suggestPaper(Iris.instance);
}
public static KMap<String, Object> asContext() {
KMap<String, Object> m = new KMap<>();
m.put("diskSpace", !ServerBootSFG.hasEnoughDiskSpace);
m.put("javaVersion", !ServerBootSFG.isCorrectJDK);
m.put("jre", ServerBootSFG.isJRE);
m.put("missingAgent", ServerBootSFG.missingAgent);
m.put("missingDimensionTypes", ServerBootSFG.missingDimensionTypes);
m.put("failedInjection", ServerBootSFG.failedInjection);
m.put("unsupportedVersion", ServerBootSFG.unsuportedversion);
m.put("serverSoftware", !ServerBootSFG.passedserversoftware);
KList<String> incompatiblePlugins = new KList<>();
ServerBootSFG.incompatibilities.forEach((plugin, present) -> {
if (present) incompatiblePlugins.add(plugin);
});
m.put("plugins", incompatiblePlugins);
return m;
}
}

View File

@@ -1,80 +0,0 @@
package com.volmit.iris.core.safeguard;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.util.format.C;
public class ModesSFG {
public static void selectMode() {
if (IrisSafeguard.unstablemode) {
Iris.safeguard(C.DARK_RED + "Iris is running in Unstable Mode");
unstable();
}
if (IrisSafeguard.warningmode) {
Iris.safeguard(C.GOLD + "Iris is running in Warning Mode");
warning();
}
if (IrisSafeguard.stablemode) {
stable();
}
}
public static void stable() {
Iris.safeguard(C.BLUE + "Iris is running Stable");
}
public static void unstable() {
UtilsSFG.printIncompatibleWarnings();
if (IrisSafeguard.unstablemode) {
Iris.info("");
Iris.info(C.DARK_GRAY + "--==<" + C.RED + " IMPORTANT " + C.DARK_GRAY + ">==--");
Iris.info(C.RED + "Iris is running in unstable mode which may cause the following issues:");
Iris.info(C.DARK_RED + "Server Issues");
Iris.info(C.RED + "- Server won't boot");
Iris.info(C.RED + "- Data Loss");
Iris.info(C.RED + "- Unexpected behavior.");
Iris.info(C.RED + "- And More...");
Iris.info(C.DARK_RED + "World Issues");
Iris.info(C.RED + "- Worlds can't load due to corruption.");
Iris.info(C.RED + "- Worlds may slowly corrupt until they can't load.");
Iris.info(C.RED + "- World data loss.");
Iris.info(C.RED + "- And More...");
Iris.info(C.DARK_RED + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support.");
Iris.info(C.DARK_RED + "CAUSE: " + C.RED + UtilsSFG.MSGIncompatibleWarnings());
if (IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode) {
Iris.info(C.DARK_RED + "Boot Unstable is set to true, continuing with the startup process.");
} else {
Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed.");
while (true) {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
// no
}
}
}
Iris.info("");
}
}
public static void warning() {
UtilsSFG.printIncompatibleWarnings();
if (IrisSafeguard.warningmode) {
Iris.info("");
Iris.info(C.DARK_GRAY + "--==<" + C.GOLD + " IMPORTANT " + C.DARK_GRAY + ">==--");
Iris.info(C.GOLD + "Iris is running in warning mode which may cause the following issues:");
Iris.info(C.YELLOW + "- Data Loss");
Iris.info(C.YELLOW + "- Errors");
Iris.info(C.YELLOW + "- Broken worlds");
Iris.info(C.YELLOW + "- Unexpected behavior.");
Iris.info(C.YELLOW + "- And perhaps further complications.");
Iris.info(C.GOLD + "CAUSE: " + C.YELLOW + UtilsSFG.MSGIncompatibleWarnings());
Iris.info("");
}
}
}

View File

@@ -1,8 +0,0 @@
package com.volmit.iris.core.safeguard;
public class PerformanceSFG {
public static void calculatePerformance() {
}
}

View File

@@ -1,194 +0,0 @@
package com.volmit.iris.core.safeguard;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisWorlds;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.agent.Agent;
import com.volmit.iris.util.collection.KSet;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.stream.Collectors;
import static com.volmit.iris.Iris.getJavaVersion;
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
public class ServerBootSFG {
public static final Map<String, Boolean> incompatibilities = new HashMap<>();
public static boolean isCorrectJDK = true;
public static boolean hasEnoughDiskSpace = true;
public static boolean isJRE = false;
public static boolean hasPrivileges = true;
public static boolean unsuportedversion = false;
public static boolean missingDimensionTypes = false;
public static boolean missingAgent = false;
public static boolean failedInjection = false;
protected static boolean safeguardPassed;
public static boolean passedserversoftware = true;
protected static int count;
protected static byte severityLow;
protected static byte severityMedium;
protected static byte severityHigh;
public static String allIncompatibilities;
public static void BootCheck() {
Iris.info("Checking for possible conflicts..");
PluginManager pluginManager = Bukkit.getPluginManager();
Plugin[] plugins = pluginManager.getPlugins();
incompatibilities.clear();
incompatibilities.put("dynmap", false);
incompatibilities.put("Stratos", false);
String pluginName;
for (Plugin plugin : plugins) {
pluginName = plugin.getName();
Boolean flag = incompatibilities.get(pluginName);
if (flag != null && !flag) {
severityHigh++;
incompatibilities.put(pluginName, true);
}
}
StringJoiner joiner = new StringJoiner(", ");
for (Map.Entry<String, Boolean> entry : incompatibilities.entrySet()) {
if (entry.getValue()) {
joiner.add(entry.getKey());
}
}
// Legacy ServerInfo
String distro = Bukkit.getName().toLowerCase();
if (
!distro.contains("purpur") &&
!distro.contains("paper") &&
!distro.contains("spigot") &&
!distro.contains("pufferfish") &&
!distro.contains("bukkit")) {
passedserversoftware = false;
joiner.add("Server Software");
severityMedium++;
}
if (INMS.get() instanceof NMSBinding1X) {
unsuportedversion = true;
joiner.add("Unsupported Minecraft Version");
severityHigh++;
}
if (!List.of(21).contains(getJavaVersion())) {
isCorrectJDK = false;
joiner.add("Unsupported Java version");
severityMedium++;
}
if (!isJDK()) {
isJRE = true;
joiner.add("Unsupported JDK");
severityMedium++;
}
// if (!hasPrivileges()){
// hasPrivileges = false;
// joiner.add("Insufficient Privileges");
// severityMedium++;
// } Some servers dont like this
if (!enoughDiskSpace()){
hasEnoughDiskSpace = false;
joiner.add("Insufficient Disk Space");
severityMedium++;
}
if (!Agent.install()) {
missingAgent = true;
joiner.add("Missing Java Agent");
severityHigh++;
} else {
if (missingDimensionTypes()) {
missingDimensionTypes = true;
joiner.add("Missing Dimension Types");
severityHigh++;
}
if (!INMS.get().injectBukkit()) {
failedInjection = true;
joiner.add("Failed Bukkit Injection");
severityHigh++;
}
}
allIncompatibilities = joiner.toString();
safeguardPassed = (severityHigh == 0 && severityMedium == 0 && severityLow == 0);
count = severityHigh + severityMedium + severityLow;
if (safeguardPassed) {
stablemode = true;
Iris.safeguard("Stable mode has been activated.");
}
if (!safeguardPassed) {
if (severityMedium >= 1 && severityHigh == 0) {
warningmode = true;
Iris.safeguard("Warning mode has been activated.");
}
if (severityHigh >= 1) {
unstablemode = true;
Iris.safeguard("Unstable mode has been activated.");
}
}
}
public static boolean isJDK() {
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// If the compiler is null, it means this is a JRE environment, not a JDK.
return compiler != null;
} catch (Exception ignored) {}
return false;
}
public static boolean hasPrivileges() {
Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
if (Files.isReadable(pv) && Files.isWritable(pv)) {
return true;
}
} catch (Exception e) {
return false;
}
return false;
}
public static boolean enoughDiskSpace() {
File freeSpace = Bukkit.getWorldContainer();
double gigabytes = freeSpace.getFreeSpace() / (1024.0 * 1024.0 * 1024.0);
return gigabytes > 3;
}
private static boolean checkJavac(String path) {
return !path.isEmpty() && (new File(path, "javac").exists() || new File(path, "javac.exe").exists());
}
private static boolean missingDimensionTypes() {
return INMS.get().missingDimensionTypes(getDimensionTypes().toArray(String[]::new));
}
private static KSet<String> getDimensionTypes() {
return IrisWorlds.get()
.getDimensions()
.map(IrisDimension::getDimensionTypeKey)
.collect(Collectors.toCollection(KSet::new));
}
}

View File

@@ -1,76 +0,0 @@
package com.volmit.iris.core.safeguard;
import com.volmit.iris.Iris;
import com.volmit.iris.util.agent.Agent;
import com.volmit.iris.util.format.C;
public class UtilsSFG {
public static void splash() {
ModesSFG.selectMode();
}
public static void printIncompatibleWarnings() {
String[] parts = Iris.instance.getDescription().getVersion().split("-");
String minVersion = parts[1];
String maxVersion = parts[2];
if (ServerBootSFG.safeguardPassed) {
Iris.safeguard(C.BLUE + "0 Conflicts found");
} else {
if (IrisSafeguard.unstablemode) {
Iris.safeguard(C.DARK_RED + "" + ServerBootSFG.count + " Conflicts found");
}
if (IrisSafeguard.warningmode) {
Iris.safeguard(C.YELLOW + "" + ServerBootSFG.count + " Conflicts found");
}
if (ServerBootSFG.incompatibilities.get("dynmap")) {
Iris.safeguard(C.RED + "Dynmap");
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap.");
}
if (ServerBootSFG.incompatibilities.get("Stratos")) {
Iris.safeguard(C.YELLOW + "Stratos");
Iris.safeguard(C.YELLOW + "- Iris is not compatible with other worldgen plugins.");
}
if (ServerBootSFG.unsuportedversion) {
Iris.safeguard(C.RED + "Server Version");
Iris.safeguard(C.RED + "- Iris only supports " + minVersion + " > " + maxVersion);
}
if (ServerBootSFG.missingDimensionTypes) {
Iris.safeguard(C.RED + "Dimension Types");
Iris.safeguard(C.RED + "- Required Iris dimension types were not loaded.");
Iris.safeguard(C.RED + "- If this still happens after a restart please contact support.");
}
if (ServerBootSFG.missingAgent) {
Iris.safeguard(C.RED + "Java Agent");
Iris.safeguard(C.RED + "- Please enable dynamic agent loading by adding -XX:+EnableDynamicAgentLoading to your jvm arguments.");
Iris.safeguard(C.RED + "- or add the jvm argument -javaagent:" + Agent.AGENT_JAR.getPath());
}
if (!ServerBootSFG.passedserversoftware) {
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
}
if (!ServerBootSFG.hasPrivileges) {
Iris.safeguard(C.YELLOW + "Insufficient Privileges");
Iris.safeguard(C.YELLOW + "- The server has insufficient Privileges to run iris. Please contact support.");
}
if (!ServerBootSFG.hasEnoughDiskSpace) {
Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
}
if (!ServerBootSFG.isCorrectJDK) {
Iris.safeguard(C.YELLOW + "Unsupported java version");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JDK " + Iris.getJavaVersion());
}
if (ServerBootSFG.isJRE) {
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JRE " + Iris.getJavaVersion());
}
}
}
public static String MSGIncompatibleWarnings() {
return ServerBootSFG.allIncompatibilities;
}
}

View File

@@ -2,29 +2,21 @@ package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.data.Varint;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.io.NamedTag;
import com.volmit.iris.util.nbt.tag.*;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.reflect.V;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.FileUtil;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.io.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@@ -39,13 +31,17 @@ public class IrisConverter {
sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath());
return;
}
AtomicInteger counter = new AtomicInteger(0);
var stopwatch = PrecisionStopwatch.start();
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(() -> {
for (File schem : fileList) {
try {
for (File schem : fileList) {
try {
PrecisionStopwatch p = PrecisionStopwatch.start();
IrisObject object;
boolean largeObject = false;
NamedTag tag = null;
NamedTag tag;
try {
tag = NBTUtil.read(schem);
} catch (IOException e) {
@@ -53,17 +49,20 @@ public class IrisConverter {
throw new RuntimeException(e);
}
CompoundTag compound = (CompoundTag) tag.getTag();
int version = resolveVersion(compound);
if (!(version == 2 || version == 3))
throw new RuntimeException(C.RED + "Unsupported schematic version: " + version);
if (compound.containsKey("Palette") && compound.containsKey("Width") && compound.containsKey("Height") && compound.containsKey("Length")) {
compound = version == 3 ? (CompoundTag) compound.get("Schematic") : compound;
int objW = ((ShortTag) compound.get("Width")).getValue();
int objH = ((ShortTag) compound.get("Height")).getValue();
int objD = ((ShortTag) compound.get("Length")).getValue();
int i = -1;
int mv = objW * objH * objD;
AtomicInteger v = new AtomicInteger(0);
if (mv > 500_000) {
if (mv > 2_000_000) {
largeObject = true;
Iris.info(C.GRAY + "Converting.. "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
Iris.info(C.GRAY + "Converting.. " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
Iris.info(C.GRAY + "- It may take a while");
if (sender.isPlayer()) {
i = J.ar(() -> {
@@ -72,6 +71,7 @@ public class IrisConverter {
}
}
compound = version == 3 ? (CompoundTag) compound.get("Blocks") : compound;
CompoundTag paletteTag = (CompoundTag) compound.get("Palette");
Map<Integer, BlockData> blockmap = new HashMap<>(paletteTag.size(), 0.9f);
for (Map.Entry<String, Tag<?>> entry : paletteTag.getValue().entrySet()) {
@@ -82,14 +82,16 @@ public class IrisConverter {
blockmap.put(blockId, bd);
}
ByteArrayTag byteArray = (ByteArrayTag) compound.get("BlockData");
boolean isBytes = version == 3 ? compound.getByteArrayTag("Data").length() < 128 : ((IntTag) compound.get("PaletteMax")).getValue() < 128;
ByteArrayTag byteArray = version == 3 ? (ByteArrayTag) compound.get("Data") : (ByteArrayTag) compound.get("BlockData");
byte[] originalBlockArray = byteArray.getValue();
IrisObject object = new IrisObject(objW, objH, objD);
var din = new DataInputStream(new ByteArrayInputStream(originalBlockArray));
object = new IrisObject(objW, objH, objD);
for (int h = 0; h < objH; h++) {
for (int d = 0; d < objD; d++) {
for (int w = 0; w < objW; w++) {
BlockData bd = blockmap.get(Byte.toUnsignedInt(originalBlockArray[v.get()]));
int blockIndex = isBytes ? din.read() & 0xFF : Varint.readUnsignedVarInt(din);
BlockData bd = blockmap.get(blockIndex);
if (!bd.getMaterial().isAir()) {
object.setUnsigned(w, h, d, bd);
}
@@ -97,42 +99,59 @@ public class IrisConverter {
}
}
}
if (i != -1) J.car(i);
try {
object.shrinkwrap();
object.write(new File(folder, schem.getName().replace(".schem", ".iob")));
} catch (IOException e) {
Iris.info(C.RED + "Failed to save: " + schem.getName());
throw new RuntimeException(e);
}
if (sender.isPlayer()) {
if (largeObject) {
sender.sendMessage(C.IRIS + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
} else {
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
counter.incrementAndGet();
if (sender.isPlayer()) {
if (largeObject) {
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
} else {
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
}
}
if (largeObject) {
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
} else {
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
}
FileUtils.delete(schem);
} catch (IOException e) {
sender.sendMessage(C.RED + "Failed to save: " + schem.getName());
throw new IOException(e);
}
if (largeObject) {
Iris.info(C.GRAY + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
} else {
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
}
FileUtils.delete(schem);
}
} catch (Exception e) {
Iris.info(C.RED + "Failed to convert: " + schem.getName());
if (sender.isPlayer()) {
} catch (Exception e) {
sender.sendMessage(C.RED + "Failed to convert: " + schem.getName());
e.printStackTrace();
}
e.printStackTrace();
Iris.reportError(e);
}
}
sender.sendMessage(C.GRAY + "converted: " + fileList.length);
stopwatch.end();
if (counter.get() != 0) {
sender.sendMessage(C.GRAY + "Converted: " + counter.get() + " in " + Form.duration(stopwatch.getMillis()));
}
if (counter.get() < fileList.length) {
sender.sendMessage(C.RED + "Some schematics failed to convert. Check the console for details.");
}
});
}
private static int resolveVersion(CompoundTag compound) throws Exception {
try {
IntTag root = compound.getIntTag("Version");
if (root != null) {
return root.getValue();
}
CompoundTag schematic = (CompoundTag) compound.get("Schematic");
return schematic.getIntTag("Version").getValue();
} catch (NullPointerException e) {
throw new Exception("Cannot resolve schematic version", e);
}
}
}

View File

@@ -851,7 +851,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
}
}
IrisBiome biome = getBiome(x, y, z);
IrisBiome biome = getSurfaceBiome(x, z);
for (IrisObjectPlacement i : biome.getObjects()) {
if (i.getPlace().contains(object)) {

View File

@@ -69,7 +69,7 @@ public class PlannedPiece {
this.setRotation(rot);
this.ogObject = data.getObjectLoader().load(piece.getObject());
this.object = structure.rotated(piece, rotation);
this.piece = rotation.rotateCopy(piece);
this.piece = rotation.rotateCopy(piece, new IrisPosition(object.getShrinkOffset()));
this.piece.setLoadKey(piece.getLoadKey());
this.object.setLoadKey(piece.getObject());
this.ogObject.setLoadKey(piece.getObject());

View File

@@ -98,6 +98,8 @@ public class IrisObject extends IrisRegistrant {
@Getter
@Setter
private transient Vector3i center;
@Getter
private transient Vector3i shrinkOffset;
public IrisObject(int w, int h, int d) {
blocks = new VectorMap<>();
@@ -106,6 +108,7 @@ public class IrisObject extends IrisRegistrant {
this.h = h;
this.d = d;
center = new Vector3i(w / 2, h / 2, d / 2);
shrinkOffset = new Vector3i(0, 0, 0);
var lock = new ReentrantReadWriteLock();
readLock = lock.readLock();
writeLock = lock.writeLock();
@@ -305,6 +308,9 @@ public class IrisObject extends IrisRegistrant {
blocks.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), B.get(din.readUTF()));
}
if (din.available() == 0)
return;
try {
int size = din.readInt();
@@ -313,7 +319,6 @@ public class IrisObject extends IrisRegistrant {
}
} catch (Throwable e) {
Iris.reportError(e);
}
}
@@ -323,7 +328,7 @@ public class IrisObject extends IrisRegistrant {
this.h = din.readInt();
this.d = din.readInt();
if (!din.readUTF().equals("Iris V2 IOB;")) {
return;
throw new HeaderException();
}
center = new Vector3i(w / 2, h / 2, d / 2);
int s = din.readShort();
@@ -470,16 +475,14 @@ public class IrisObject extends IrisRegistrant {
}
public void read(File file) throws IOException {
var fin = new BufferedInputStream(new FileInputStream(file));
try {
try (var fin = new BufferedInputStream(new FileInputStream(file))) {
read(fin);
fin.close();
} catch (Throwable e) {
Iris.reportError(e);
fin.close();
fin = new BufferedInputStream(new FileInputStream(file));
readLegacy(fin);
fin.close();
if (!(e instanceof HeaderException))
Iris.reportError(e);
try (var fin = new BufferedInputStream(new FileInputStream(file))) {
readLegacy(fin);
}
}
}
@@ -504,8 +507,9 @@ public class IrisObject extends IrisRegistrant {
}
public void shrinkwrap() {
BlockVector min = new BlockVector();
BlockVector max = new BlockVector();
if (blocks.isEmpty()) return;
BlockVector min = new BlockVector(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
BlockVector max = new BlockVector(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
for (BlockVector i : blocks.keys()) {
min.setX(Math.min(min.getX(), i.getX()));
@@ -520,6 +524,31 @@ public class IrisObject extends IrisRegistrant {
h = max.getBlockY() - min.getBlockY() + 1;
d = max.getBlockZ() - min.getBlockZ() + 1;
center = new Vector3i(w / 2, h / 2, d / 2);
Vector3i offset = new Vector3i(
-center.getBlockX() - min.getBlockX(),
-center.getBlockY() - min.getBlockY(),
-center.getBlockZ() - min.getBlockZ()
);
if (offset.getBlockX() == 0 && offset.getBlockY() == 0 && offset.getBlockZ() == 0)
return;
VectorMap<BlockData> b = new VectorMap<>();
VectorMap<TileData> s = new VectorMap<>();
blocks.forEach((vector, data) -> {
vector.add(offset);
b.put(vector, data);
});
states.forEach((vector, data) -> {
vector.add(offset);
s.put(vector, data);
});
shrinkOffset = offset;
blocks = b;
states = s;
}
public void clean() {
@@ -1150,8 +1179,8 @@ public class IrisObject extends IrisRegistrant {
blocks = d;
states = dx;
writeLock.unlock();
shrinkwrap();
writeLock.unlock();
}
public void place(Location at) {
@@ -1389,4 +1418,10 @@ public class IrisObject extends IrisRegistrant {
@Override
public void scanForErrors(JSONObject p, VolmitSender sender) {
}
private static class HeaderException extends IOException {
public HeaderException() {
super("Invalid Header");
}
}
}

View File

@@ -28,13 +28,13 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.Axis;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.*;
import org.bukkit.block.data.type.RedstoneWire;
import org.bukkit.block.data.type.Wall;
import org.bukkit.block.structure.StructureRotation;
import org.bukkit.util.BlockVector;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -101,15 +101,15 @@ public class IrisObjectRotation {
return e.rotateCopy(this);
}
public IrisJigsawPiece rotateCopy(IrisJigsawPiece v) {
public IrisJigsawPiece rotateCopy(IrisJigsawPiece v, IrisPosition offset) {
IrisJigsawPiece piece = v.copy();
for (IrisJigsawPieceConnector i : piece.getConnectors()) {
i.setPosition(rotate(i.getPosition()));
i.setPosition(rotate(i.getPosition()).add(offset));
i.setDirection(rotate(i.getDirection()));
}
try {
var translate = piece.getPlacementOptions().getTranslate();
var pos = rotate(new IrisPosition(translate.getX(), translate.getY(), translate.getZ()));
var pos = rotate(new IrisPosition(translate.getX(), translate.getY(), translate.getZ())).add(offset);
translate.setX(pos.getX()).setY(pos.getY()).setZ(pos.getZ());
} catch (NullPointerException ignored) {}
@@ -259,14 +259,14 @@ public class IrisObjectRotation {
g.setRotation(face);
} else if (d instanceof Orientable) {
BlockFace f = getFace(((Orientable) d).getAxis());
} else if (d instanceof Orientable g) {
BlockFace f = getFace(g.getAxis());
BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ());
bv = rotate(bv.clone(), spinx, spiny, spinz);
Axis a = getAxis(bv);
if (!a.equals(((Orientable) d).getAxis()) && ((Orientable) d).getAxes().contains(a)) {
((Orientable) d).setAxis(a);
if (!a.equals(g.getAxis()) && g.getAxes().contains(a)) {
g.setAxis(a);
}
} else if (d instanceof MultipleFacing g) {
List<BlockFace> faces = new KList<>();
@@ -304,14 +304,22 @@ public class IrisObjectRotation {
for (BlockFace i : WALL_FACES) {
wall.setHeight(i, faces.getOrDefault(i, Wall.Height.NONE));
}
} else if (d.getMaterial().equals(Material.NETHER_PORTAL) && d instanceof Orientable g) {
//TODO: Fucks up logs
BlockFace f = faceForAxis(g.getAxis());
BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ());
bv = rotate(bv.clone(), spinx, spiny, spinz);
BlockFace t = getFace(bv);
Axis a = !g.getAxes().contains(Axis.Y) ? axisFor(t) : axisFor2D(t);
((Orientable) d).setAxis(a);
} else if (d instanceof RedstoneWire wire) {
Map<BlockFace, RedstoneWire.Connection> faces = new HashMap<>();
var allowed = wire.getAllowedFaces();
for (BlockFace i : allowed) {
RedstoneWire.Connection connection = wire.getFace(i);
BlockVector bv = new BlockVector(i.getModX(), i.getModY(), i.getModZ());
bv = rotate(bv.clone(), spinx, spiny, spinz);
BlockFace r = getFace(bv);
if (allowed.contains(r))
faces.put(r, connection);
}
for (BlockFace i : allowed) {
wire.setFace(i, faces.getOrDefault(i, RedstoneWire.Connection.NONE));
}
}
} catch (Throwable e) {
Iris.reportError(e);

View File

@@ -360,6 +360,7 @@ public class B {
public static boolean isFoliagePlantable(BlockData d) {
return d.getMaterial().equals(Material.GRASS_BLOCK)
|| d.getMaterial().equals(Material.MOSS_BLOCK)
|| d.getMaterial().equals(Material.ROOTED_DIRT)
|| d.getMaterial().equals(Material.DIRT)
|| d.getMaterial().equals(Material.COARSE_DIRT)
@@ -368,6 +369,7 @@ public class B {
public static boolean isFoliagePlantable(Material d) {
return d.equals(Material.GRASS_BLOCK)
|| d.equals(Material.MOSS_BLOCK)
|| d.equals(Material.DIRT)
|| d.equals(TALL_GRASS)
|| d.equals(TALL_SEAGRASS)

View File

@@ -20,6 +20,7 @@ package com.volmit.iris.util.format;
import com.volmit.iris.Iris;
import com.volmit.iris.util.plugin.VolmitSender;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import org.apache.commons.lang.Validate;
@@ -495,6 +496,14 @@ public enum C {
return STRIP_COLOR_PATTERN.matcher(input).replaceAll("");
}
public static String strip(final String input) {
if (input == null) {
return null;
}
return MiniMessage.miniMessage().stripTags(stripColor(input));
}
/**
* DyeColor to ChatColor
*

View File

@@ -131,9 +131,13 @@ public class MantleChunk extends FlaggedChunk {
ref.release();
}
public void copyFlags(MantleChunk chunk) {
public void copyFrom(MantleChunk chunk) {
use();
super.copyFlags(chunk);
super.copyFrom(chunk, () -> {
for (int i = 0; i < sections.length(); i++) {
sections.set(i, chunk.get(i));
}
});
release();
}

View File

@@ -56,7 +56,7 @@ public class Bindings {
options.setEnvironment(BuildConstants.ENVIRONMENT);
options.setBeforeSend((event, hint) -> {
if (suppress(event.getThrowable())) return null;
event.setTag("iris.safeguard", IrisSafeguard.mode());
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());
@@ -67,6 +67,7 @@ public class Bindings {
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());

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.util.sentry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.volmit.iris.core.safeguard.IrisSafeguard;
import com.volmit.iris.util.collection.KMap;
import io.sentry.Attachment;
import org.bukkit.Bukkit;
@@ -12,6 +13,7 @@ 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);

View File

@@ -0,0 +1,143 @@
package com.volmit.iris.core.safeguard
import com.volmit.iris.Iris
import com.volmit.iris.core.IrisSettings
import com.volmit.iris.core.safeguard.task.Diagnostic
import com.volmit.iris.core.safeguard.task.Task
import com.volmit.iris.core.safeguard.task.ValueWithDiagnostics
import com.volmit.iris.core.safeguard.task.tasks
import com.volmit.iris.util.format.C
import com.volmit.iris.util.scheduling.J
import org.bukkit.Bukkit
import java.util.*
object IrisSafeguard {
@Volatile
private var forceShutdown = false
private var results: Map<Task, ValueWithDiagnostics<Mode>> = emptyMap()
private var context: Map<String, String> = emptyMap()
private var attachment: Map<String, List<String>> = emptyMap()
private var mode = Mode.STABLE
private var count = 0
@JvmStatic
fun execute() {
val results = LinkedHashMap<Task, ValueWithDiagnostics<Mode>>(tasks.size)
val context = LinkedHashMap<String, String>(tasks.size)
val attachment = LinkedHashMap<String, List<String>>(tasks.size)
var mode = Mode.STABLE
var count = 0
for (task in tasks) {
var result: ValueWithDiagnostics<Mode>
try {
result = task.run()
} catch (e: Throwable) {
Iris.reportError(e)
result = ValueWithDiagnostics(
Mode.WARNING,
Diagnostic(Diagnostic.Logger.ERROR, "Error while running task ${task.id}", e)
)
}
mode = mode.highest(result.value)
results[task] = result
context[task.id] = result.value.id
attachment[task.id] = result.diagnostics.flatMap { it.toString().split('\n') }
if (result.value != Mode.STABLE) count++
}
this.results = Collections.unmodifiableMap(results)
this.context = Collections.unmodifiableMap(context)
this.attachment = Collections.unmodifiableMap(attachment)
this.mode = mode
this.count = count
}
@JvmStatic
fun mode() = mode
@JvmStatic
fun asContext() = context
@JvmStatic
fun asAttachment() = attachment
@JvmStatic
fun splash() {
Iris.instance.splash()
printReports()
printFooter()
}
@JvmStatic
fun printReports() {
when (mode) {
Mode.STABLE -> Iris.info(C.BLUE.toString() + "0 Conflicts found")
Mode.WARNING -> Iris.warn(C.GOLD.toString() + "%s Issues found", count)
Mode.UNSTABLE -> Iris.error(C.DARK_RED.toString() + "%s Issues found", count)
}
results.values.forEach { it.log(withStackTrace = true) }
}
@JvmStatic
fun printFooter() {
when (mode) {
Mode.STABLE -> Iris.info(C.BLUE.toString() + "Iris is running Stable")
Mode.WARNING -> warning()
Mode.UNSTABLE -> unstable()
}
}
@JvmStatic
fun isForceShutdown() = forceShutdown
private fun warning() {
Iris.warn(C.GOLD.toString() + "Iris is running in Warning Mode")
Iris.warn("")
Iris.warn(C.DARK_GRAY.toString() + "--==<" + C.GOLD + " IMPORTANT " + C.DARK_GRAY + ">==--")
Iris.warn(C.GOLD.toString() + "Iris is running in warning mode which may cause the following issues:")
Iris.warn("- Data Loss")
Iris.warn("- Errors")
Iris.warn("- Broken worlds")
Iris.warn("- Unexpected behavior.")
Iris.warn("- And perhaps further complications.")
Iris.warn("")
}
private fun unstable() {
Iris.error(C.DARK_RED.toString() + "Iris is running in Unstable Mode")
Iris.error("")
Iris.error(C.DARK_GRAY.toString() + "--==<" + C.RED + " IMPORTANT " + C.DARK_GRAY + ">==--")
Iris.error("Iris is running in unstable mode which may cause the following issues:")
Iris.error(C.DARK_RED.toString() + "Server Issues")
Iris.error("- Server won't boot")
Iris.error("- Data Loss")
Iris.error("- Unexpected behavior.")
Iris.error("- And More...")
Iris.error(C.DARK_RED.toString() + "World Issues")
Iris.error("- Worlds can't load due to corruption.")
Iris.error("- Worlds may slowly corrupt until they can't load.")
Iris.error("- World data loss.")
Iris.error("- And More...")
Iris.error(C.DARK_RED.toString() + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support.")
if (IrisSettings.get().general.isDoomsdayAnnihilationSelfDestructMode) {
Iris.error(C.DARK_RED.toString() + "Boot Unstable is set to true, continuing with the startup process in 10 seconds.")
J.sleep(10000L)
} else {
Iris.error(C.DARK_RED.toString() + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed.")
Iris.error(C.DARK_RED.toString() + "The server will shutdown in 10 seconds.")
J.sleep(10000L)
Iris.error(C.DARK_RED.toString() + "Shutting down server.")
forceShutdown = true
try {
Bukkit.getPluginManager().disablePlugins()
} finally {
Runtime.getRuntime().halt(42)
}
}
Iris.info("")
}
}

View File

@@ -0,0 +1,76 @@
package com.volmit.iris.core.safeguard
import com.volmit.iris.BuildConstants
import com.volmit.iris.Iris
import com.volmit.iris.core.IrisSettings
import com.volmit.iris.util.format.C
import com.volmit.iris.util.format.Form
enum class Mode(private val color: C) {
STABLE(C.IRIS),
WARNING(C.GOLD),
UNSTABLE(C.RED);
val id = name.lowercase()
fun highest(m: Mode): Mode {
return if (m.ordinal > ordinal) m else this
}
fun tag(subTag: String?): String {
if (subTag == null || subTag.isBlank()) return wrap("Iris") + C.GRAY + ": "
return wrap("Iris") + " " + wrap(subTag) + C.GRAY + ": "
}
private fun wrap(tag: String?): String {
return C.BOLD.toString() + "" + C.DARK_GRAY + "[" + C.BOLD + color + tag + C.BOLD + C.DARK_GRAY + "]" + C.RESET
}
fun trySplash() {
if (!IrisSettings.get().general.isSplashLogoStartup) return
splash()
}
fun splash() {
val padd = Form.repeat(" ", 8)
val padd2 = Form.repeat(" ", 4)
val splash = arrayOf(
padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@",
padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + color + " .(((()))). ",
padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + color + " .((((((())))))). ",
padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + color + " ((((((((())))))))) " + C.GRAY + " @",
padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + color + " ((((((((-))))))))) " + C.GRAY + " @@",
padd + C.GRAY + "@@@&&" + color + " ((((((({ })))))))) " + C.GRAY + " &&@@@",
padd + C.GRAY + "@@" + color + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@",
padd + C.GRAY + "@" + color + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@",
padd + C.GRAY + "" + color + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@",
padd + C.GRAY + "" + color + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@",
padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@",
)
val info = arrayOf(
"",
"",
"",
"",
"",
padd2 + color + " Iris",
padd2 + C.GRAY + " by " + color + "Volmit Software",
padd2 + C.GRAY + " v" + color + Iris.instance.description.version,
padd2 + C.GRAY + " c" + color + BuildConstants.COMMIT + C.GRAY + "/" + color + BuildConstants.ENVIRONMENT,
)
val builder = StringBuilder("\n\n")
for (i in splash.indices) {
builder.append(splash[i])
if (i < info.size) {
builder.append(info[i])
}
builder.append("\n")
}
Iris.info(builder.toString())
}
}

View File

@@ -0,0 +1,28 @@
package com.volmit.iris.core.safeguard.task
import com.volmit.iris.core.safeguard.Mode
import com.volmit.iris.util.format.Form
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
abstract class Task(
val id: String,
val name: String = Form.capitalizeWords(id.replace(" ", "_").lowercase()),
) {
abstract fun run(): ValueWithDiagnostics<Mode>
companion object {
fun of(id: String, name: String = id, action: () -> ValueWithDiagnostics<Mode>) = object : Task(id, name) {
override fun run() = action()
}
fun of(id: String, action: () -> ValueWithDiagnostics<Mode>) = object : Task(id) {
override fun run() = action()
}
fun task(action: () -> ValueWithDiagnostics<Mode>) = PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, Task>> { _, _ ->
ReadOnlyProperty { _, property -> of(property.name, action) }
}
}
}

View File

@@ -0,0 +1,138 @@
package com.volmit.iris.core.safeguard.task
import com.volmit.iris.Iris
import com.volmit.iris.core.IrisWorlds
import com.volmit.iris.core.nms.INMS
import com.volmit.iris.core.nms.v1X.NMSBinding1X
import com.volmit.iris.core.safeguard.Mode
import com.volmit.iris.core.safeguard.Mode.*
import com.volmit.iris.core.safeguard.task.Diagnostic.Logger.*
import com.volmit.iris.core.safeguard.task.Task.Companion.of
import com.volmit.iris.util.agent.Agent
import com.volmit.iris.util.misc.getHardware
import org.bukkit.Bukkit
import java.util.stream.Collectors
import javax.tools.ToolProvider
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
private val memory by task {
val mem = getHardware.getProcessMemory()
if (mem >= 5999) STABLE.withDiagnostics()
else STABLE.withDiagnostics(
WARN.create("Low Memory"),
WARN.create("- 6GB+ Ram is recommended"),
WARN.create("- Process Memory: $mem MB")
)
}
private val incompatibilities by task {
val plugins = mutableSetOf("dynmap", "Stratos")
plugins.removeIf { server.pluginManager.getPlugin(it) == null }
if (plugins.isEmpty()) STABLE.withDiagnostics()
else {
val diagnostics = mutableListOf<Diagnostic>()
if ("dynmap" in plugins) diagnostics.addAll(
ERROR.create("Dynmap"),
ERROR.create("- The plugin Dynmap is not compatible with the server."),
ERROR.create("- If you want to have a map plugin like Dynmap, consider Bluemap.")
)
if ("Stratos" in plugins) diagnostics.addAll(
ERROR.create("Stratos"),
ERROR.create("- Iris is not compatible with other worldgen plugins.")
)
WARNING.withDiagnostics(diagnostics)
}
}
private val software by task {
val supported = setOf(
"purpur",
"pufferfish",
"paper",
"spigot",
"bukkit"
)
if (supported.any { server.name.contains(it, true) }) STABLE.withDiagnostics()
else WARNING.withDiagnostics(
WARN.create("Unsupported Server Software"),
WARN.create("- Please consider using Paper or Purpur instead.")
)
}
private val version by task {
val parts = Iris.instance.description.version.split('-')
val minVersion = parts[1]
val maxVersion = parts[2]
if (INMS.get() !is NMSBinding1X) STABLE.withDiagnostics()
else UNSTABLE.withDiagnostics(
ERROR.create("Server Version"),
ERROR.create("- Iris only supports $minVersion > $maxVersion")
)
}
private val injection by task {
if (!Agent.install()) UNSTABLE.withDiagnostics(
ERROR.create("Java Agent"),
ERROR.create("- Please enable dynamic agent loading by adding -XX:+EnableDynamicAgentLoading to your jvm arguments."),
ERROR.create("- or add the jvm argument -javaagent:" + Agent.AGENT_JAR.path)
)
else if (!INMS.get().injectBukkit()) UNSTABLE.withDiagnostics(
ERROR.create("Code Injection"),
ERROR.create("- Failed to inject code. Please contact support")
)
else STABLE.withDiagnostics()
}
private val dimensionTypes by task {
val keys = IrisWorlds.get()
.dimensions
.map { it.dimensionTypeKey }
.collect(Collectors.toSet())
if (!INMS.get().missingDimensionTypes(*keys.toTypedArray())) STABLE.withDiagnostics()
else UNSTABLE.withDiagnostics(
ERROR.create("Dimension Types"),
ERROR.create("- Required Iris dimension types were not loaded."),
ERROR.create("- If this still happens after a restart please contact support.")
)
}
private val diskSpace by task {
if (server.worldContainer.freeSpace.toDouble().div(0x4000_0000) > 3) STABLE.withDiagnostics()
else WARNING.withDiagnostics(
WARN.create("Insufficient Disk Space"),
WARN.create("- 3GB of free space is required for Iris to function.")
)
}
private val java by task {
val version = Iris.getJavaVersion()
val jdk = runCatching { ToolProvider.getSystemJavaCompiler() }.getOrNull() != null
if (version in setOf(21) && jdk) STABLE.withDiagnostics()
else WARNING.withDiagnostics(
WARN.create("Unsupported Java version"),
WARN.create("- Please consider using JDK 21 Instead of ${if(jdk) "JDK" else "JRE"} $version")
)
}
val tasks = listOf(
memory,
incompatibilities,
software,
version,
injection,
dimensionTypes,
diskSpace,
java,
)
private val server get() = Bukkit.getServer()
private fun <T> MutableList<T>.addAll(vararg values: T) = values.forEach(this::add)
fun task(action: () -> ValueWithDiagnostics<Mode>) = PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, Task>> { _, _ ->
ReadOnlyProperty { _, property -> of(property.name, action) }
}

View File

@@ -0,0 +1,74 @@
package com.volmit.iris.core.safeguard.task
import com.volmit.iris.Iris
import com.volmit.iris.util.format.C
import java.io.ByteArrayOutputStream
import java.io.PrintStream
data class ValueWithDiagnostics<out T>(
val value: T,
val diagnostics: List<Diagnostic>
) {
constructor(value: T, vararg diagnostics: Diagnostic) : this(value, diagnostics.toList())
@JvmOverloads
fun log(
withException: Boolean = true,
withStackTrace: Boolean = false
) {
diagnostics.forEach { it.log(withException, withStackTrace) }
}
}
data class Diagnostic @JvmOverloads constructor(
val logger: Logger = Logger.ERROR,
val message: String,
val exception: Throwable? = null
) {
enum class Logger(
private val logger: (String) -> Unit
) {
DEBUG(Iris::debug),
RAW(Iris::msg),
INFO(Iris::info),
WARN(Iris::warn),
ERROR(Iris::error);
fun print(message: String) = message.split('\n').forEach(logger)
fun create(message: String, exception: Throwable? = null) = Diagnostic(this, message, exception)
}
@JvmOverloads
fun log(
withException: Boolean = true,
withStackTrace: Boolean = false
) {
logger.print(render(withException, withStackTrace))
}
fun render(
withException: Boolean = true,
withStackTrace: Boolean = false
): String = buildString {
append(message)
if (withException && exception != null) {
append(": ")
append(exception)
if (withStackTrace) {
ByteArrayOutputStream().use { os ->
val ps = PrintStream(os)
exception.printStackTrace(ps)
ps.flush()
append("\n")
append(os.toString())
}
}
}
}
override fun toString(): String = C.strip(render())
}
fun <T> T.withDiagnostics(vararg diagnostics: Diagnostic) = ValueWithDiagnostics(this, diagnostics.toList())
fun <T> T.withDiagnostics(diagnostics: List<Diagnostic>) = ValueWithDiagnostics(this, diagnostics)

View File

@@ -35,6 +35,7 @@ class ChunkedDataCache<T> private constructor(
}
@BlockCoordinates
@Suppress("UNCHECKED_CAST")
fun get(x: Int, z: Int): T? {
if (!cache) {
return stream.get((this.x + x).toDouble(), (this.z + z).toDouble())

View File

@@ -3,6 +3,9 @@ package com.volmit.iris.util.mantle
import com.volmit.iris.util.data.Varint
import com.volmit.iris.util.mantle.flag.MantleFlag
import com.volmit.iris.util.parallel.AtomicBooleanArray
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.io.DataInput
@@ -22,9 +25,21 @@ abstract class FlaggedChunk() {
abstract fun isClosed(): Boolean
protected fun copyFlags(other: FlaggedChunk) {
protected fun copyFrom(other: FlaggedChunk, action: Runnable) = runBlocking {
coroutineScope {
for (i in 0 until flags.length()) {
launch { locks[i].lock() }.start()
}
}
action.run()
for (i in 0 until flags.length()) {
flags.set(i, other.flags.get(i))
flags[i] = other.flags[i]
}
for (i in 0 until flags.length()) {
locks[i].unlock()
}
}