9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-19 23:19:21 +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" val additionalFlags = "-XX:+AlwaysPreTouch"
//Valid values are: none, truecolor, indexed256, indexed16, indexed8 //Valid values are: none, truecolor, indexed256, indexed16, indexed8
val color = "truecolor" val color = "truecolor"
val errorReporting = findProperty("errorReporting") as Boolean? ?: false val errorReporting = "true" == findProperty("errorReporting")
val nmsBindings = mapOf( val nmsBindings = mapOf(
"v1_21_R6" to "1.21.10-R0.1-SNAPSHOT", "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 val jarJar: Configuration by configurations.creating
dependencies { dependencies {
for (key in nmsBindings.keys) { 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")) jarJar(project(":core:agent"))
} }
tasks { tasks {
jar { jar {
inputs.files(included)
duplicatesStrategy = DuplicatesStrategy.EXCLUDE 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") archiveFileName.set("Iris-${project.version}.jar")
} }

View File

@@ -115,7 +115,7 @@ java {
} }
sentry { sentry {
url = "http://sentry.volmit.com:8080/" url = "http://sentry.volmit.com:8080"
autoInstallation.enabled = false autoInstallation.enabled = false
includeSourceContext = true includeSourceContext = true
@@ -175,6 +175,10 @@ tasks {
relocate("io.github.slimjar", "$lib.slimjar") relocate("io.github.slimjar", "$lib.slimjar")
exclude("modules/loader-agent.isolated-jar") exclude("modules/loader-agent.isolated-jar")
} }
sentryCollectSourcesJava {
dependsOn(generateTemplates)
}
} }
val templateSource = file("src/main/templates") val templateSource = file("src/main/templates")
@@ -185,10 +189,10 @@ val generateTemplates = tasks.register<Copy>("generateTemplates") {
"commit" to provider { "commit" to provider {
val res = runCatching { project.extensions.getByType<Grgit>().head().id } val res = runCatching { project.extensions.getByType<Grgit>().head().id }
res.getOrDefault("") res.getOrDefault("")
.takeIf { it.length == 40 } ?: { .takeIf { it.length == 40 } ?: run {
logger.error("Git commit hash not found", res.exceptionOrNull()) this.logger.error("Git commit hash not found", res.exceptionOrNull())
"unknown" "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.link.MultiverseCoreLink;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS; 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.pregenerator.LazyPregenerator;
import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisToolbelt; 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.collection.KMap;
import com.volmit.iris.util.exceptions.IrisException; import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.C; 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.function.NastyRunnable;
import com.volmit.iris.util.io.FileWatcher; import com.volmit.iris.util.io.FileWatcher;
import com.volmit.iris.util.io.IO; 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.math.RNG;
import com.volmit.iris.util.misc.Bindings; import com.volmit.iris.util.misc.Bindings;
import com.volmit.iris.util.misc.SlimJar; 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.parallel.MultiBurst;
import com.volmit.iris.util.plugin.IrisService; import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitPlugin; 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.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
@SuppressWarnings("CanBeFinal") @SuppressWarnings("CanBeFinal")
public class Iris extends VolmitPlugin implements Listener { public class Iris extends VolmitPlugin implements Listener {
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>(); 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) { public static void info(String format, Object... args) {
msg(C.WHITE + String.format(format, 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") @SuppressWarnings("deprecation")
public static void later(NastyRunnable object) { public static void later(NastyRunnable object) {
@@ -449,9 +440,9 @@ public class Iris extends VolmitPlugin implements Listener {
IO.delete(new File("iris")); IO.delete(new File("iris"));
compat = IrisCompat.configured(getDataFile("compat.json")); compat = IrisCompat.configured(getDataFile("compat.json"));
ServerConfigurator.configure(); ServerConfigurator.configure();
IrisSafeguard.IrisSafeguardSystem(); IrisSafeguard.execute();
getSender().setTag(getTag()); getSender().setTag(getTag());
IrisSafeguard.splash(true); IrisSafeguard.splash();
tickets = new ChunkTickets(); tickets = new ChunkTickets();
linkMultiverseCore = new MultiverseCoreLink(); linkMultiverseCore = new MultiverseCoreLink();
configWatcher = new FileWatcher(getDataFile("settings.json")); configWatcher = new FileWatcher(getDataFile("settings.json"));
@@ -459,7 +450,6 @@ public class Iris extends VolmitPlugin implements Listener {
services.values().forEach(this::registerListener); services.values().forEach(this::registerListener);
addShutdownHook(); addShutdownHook();
J.s(() -> { J.s(() -> {
J.a(IrisSafeguard::suggestPaper);
J.a(() -> IO.delete(getTemp())); J.a(() -> IO.delete(getTemp()));
J.a(LazyPregenerator::loadLazyGenerators, 100); J.a(LazyPregenerator::loadLazyGenerators, 100);
J.a(this::bstats); J.a(this::bstats);
@@ -467,7 +457,6 @@ public class Iris extends VolmitPlugin implements Listener {
J.sr(this::tickQueue, 0); J.sr(this::tickQueue, 0);
J.s(this::setupPapi); J.s(this::setupPapi);
J.a(ServerConfigurator::configure, 20); J.a(ServerConfigurator::configure, 20);
IrisSafeguard.splash(false);
autoStartStudio(); autoStartStudio();
checkForBukkitWorlds(s -> true); checkForBukkitWorlds(s -> true);
@@ -529,9 +518,10 @@ public class Iris extends VolmitPlugin implements Listener {
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom(); Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> { Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
J.s(() -> { J.s(() -> {
var spawn = w.getSpawnLocation();
for (Player i : getServer().getOnlinePlayers()) { for (Player i : getServer().getOnlinePlayers()) {
i.setGameMode(GameMode.SPECTATOR); 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(); enable();
super.onEnable(); super.onEnable();
Bukkit.getPluginManager().registerEvents(this, this); Bukkit.getPluginManager().registerEvents(this, this);
setupChecks();
} }
public void onDisable() { public void onDisable() {
if (IrisSafeguard.isForceShutdown()) return;
services.values().forEach(IrisService::onDisable); services.values().forEach(IrisService::onDisable);
Bukkit.getScheduler().cancelTasks(this); Bukkit.getScheduler().cancelTasks(this);
HandlerList.unregisterAll((Plugin) this); HandlerList.unregisterAll((Plugin) this);
@@ -591,49 +581,7 @@ public class Iris extends VolmitPlugin implements Listener {
@Override @Override
public String getTag(String subTag) { public String getTag(String subTag) {
if (unstablemode) { return IrisSafeguard.mode().tag(subTag);
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;
} }
private void checkConfigHotload() { private void checkConfigHotload() {
@@ -741,88 +689,11 @@ public class Iris extends VolmitPlugin implements Listener {
} }
public void splash() { public void splash() {
if (!IrisSettings.get().getGeneral().isSplashLogoStartup()) { Iris.info("Server type & version: " + Bukkit.getName() + " v" + Bukkit.getVersion());
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("Custom Biomes: " + INMS.get().countCustomBiomes()); Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
setupChecks();
printPacks(); printPacks();
for (int i = 0; i < info.length; i++) { IrisSafeguard.mode().trySplash();
splash[i] += info[i];
}
Iris.info("\n\n " + new KList<>(splash).toString("\n") + "\n");
} }
private void printPacks() { 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.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension; 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.engine.object.annotations.Snippet;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.IrisContext; import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement; 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.nbt.mca.MCAUtil;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.jobs.Job;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.jpountz.lz4.LZ4BlockInputStream; import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream; import net.jpountz.lz4.LZ4BlockOutputStream;
@@ -92,6 +95,124 @@ public class CommandDeveloper implements DecreeExecutor {
Iris.reportError(new Exception("This is a test")); 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") @Decree(description = "Test")
public void mantle(@Param(defaultValue = "false") boolean plate, @Param(defaultValue = "21474836474") String name) throws Throwable { 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"); 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); job.execute(sender(), latch::countDown);
latch.await(); latch.await();
int sections = mantle.getWorldHeight() >> 4; chunkMap.forEach((pos, chunk) ->
chunkMap.forEach((pos, chunk) -> { mantle.getChunk(pos.getX(), pos.getZ()).copyFrom(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();
}
});
} catch (Throwable e) { } catch (Throwable e) {
sender().sendMessage("Error while regenerating chunks"); sender().sendMessage("Error while regenerating chunks");
e.printStackTrace(); e.printStackTrace();
@@ -702,8 +688,14 @@ public class CommandStudio implements DecreeExecutor {
} }
sender().sendMessage(C.GREEN + "Sending you to the studio world!"); sender().sendMessage(C.GREEN + "Sending you to the studio world!");
player().teleport(Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getTarget().getWorld().spawnLocation()); var player = player();
player().setGameMode(GameMode.SPECTATOR); 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") @Decree(description = "Update your dimension projects VSCode workspace")

View File

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

View File

@@ -225,7 +225,7 @@ public class IrisProject {
sender.sendMessage("Can't find dimension: " + getName()); sender.sendMessage("Can't find dimension: " + getName());
return; return;
} else if (sender.isPlayer()) { } else if (sender.isPlayer()) {
sender.player().setGameMode(GameMode.SPECTATOR); J.s(() -> sender.player().setGameMode(GameMode.SPECTATOR));
} }
try { 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.Iris;
import com.volmit.iris.engine.object.*; 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.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.nbt.io.NBTUtil; import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.io.NamedTag; import com.volmit.iris.util.nbt.io.NamedTag;
import com.volmit.iris.util.nbt.tag.*; import com.volmit.iris.util.nbt.tag.*;
import com.volmit.iris.util.plugin.VolmitSender; 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.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.util.FileUtil;
import org.bukkit.util.Vector;
import java.io.File; import java.io.*;
import java.io.FilenameFilter; import java.util.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@@ -39,13 +31,17 @@ public class IrisConverter {
sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath()); sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath());
return; return;
} }
AtomicInteger counter = new AtomicInteger(0);
var stopwatch = PrecisionStopwatch.start();
ExecutorService executorService = Executors.newFixedThreadPool(1); ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(() -> { executorService.submit(() -> {
for (File schem : fileList) { for (File schem : fileList) {
try { try {
PrecisionStopwatch p = PrecisionStopwatch.start(); PrecisionStopwatch p = PrecisionStopwatch.start();
IrisObject object;
boolean largeObject = false; boolean largeObject = false;
NamedTag tag = null; NamedTag tag;
try { try {
tag = NBTUtil.read(schem); tag = NBTUtil.read(schem);
} catch (IOException e) { } catch (IOException e) {
@@ -53,15 +49,18 @@ public class IrisConverter {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
CompoundTag compound = (CompoundTag) tag.getTag(); 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 objW = ((ShortTag) compound.get("Width")).getValue();
int objH = ((ShortTag) compound.get("Height")).getValue(); int objH = ((ShortTag) compound.get("Height")).getValue();
int objD = ((ShortTag) compound.get("Length")).getValue(); int objD = ((ShortTag) compound.get("Length")).getValue();
int i = -1; int i = -1;
int mv = objW * objH * objD; int mv = objW * objH * objD;
AtomicInteger v = new AtomicInteger(0); AtomicInteger v = new AtomicInteger(0);
if (mv > 500_000) { if (mv > 2_000_000) {
largeObject = true; 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"); Iris.info(C.GRAY + "- It may take a while");
@@ -72,6 +71,7 @@ public class IrisConverter {
} }
} }
compound = version == 3 ? (CompoundTag) compound.get("Blocks") : compound;
CompoundTag paletteTag = (CompoundTag) compound.get("Palette"); CompoundTag paletteTag = (CompoundTag) compound.get("Palette");
Map<Integer, BlockData> blockmap = new HashMap<>(paletteTag.size(), 0.9f); Map<Integer, BlockData> blockmap = new HashMap<>(paletteTag.size(), 0.9f);
for (Map.Entry<String, Tag<?>> entry : paletteTag.getValue().entrySet()) { for (Map.Entry<String, Tag<?>> entry : paletteTag.getValue().entrySet()) {
@@ -82,14 +82,16 @@ public class IrisConverter {
blockmap.put(blockId, bd); 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(); byte[] originalBlockArray = byteArray.getValue();
var din = new DataInputStream(new ByteArrayInputStream(originalBlockArray));
IrisObject object = new IrisObject(objW, objH, objD); object = new IrisObject(objW, objH, objD);
for (int h = 0; h < objH; h++) { for (int h = 0; h < objH; h++) {
for (int d = 0; d < objD; d++) { for (int d = 0; d < objD; d++) {
for (int w = 0; w < objW; w++) { 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()) { if (!bd.getMaterial().isAir()) {
object.setUnsigned(w, h, d, bd); object.setUnsigned(w, h, d, bd);
} }
@@ -97,14 +99,12 @@ public class IrisConverter {
} }
} }
} }
if (i != -1) J.car(i); if (i != -1) J.car(i);
try { try {
object.shrinkwrap(); object.shrinkwrap();
object.write(new File(folder, schem.getName().replace(".schem", ".iob"))); object.write(new File(folder, schem.getName().replace(".schem", ".iob")));
} catch (IOException e) { counter.incrementAndGet();
Iris.info(C.RED + "Failed to save: " + schem.getName());
throw new RuntimeException(e);
}
if (sender.isPlayer()) { if (sender.isPlayer()) {
if (largeObject) { if (largeObject) {
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis())); sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
@@ -118,21 +118,40 @@ public class IrisConverter {
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob")); Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
} }
FileUtils.delete(schem); FileUtils.delete(schem);
} catch (IOException e) {
sender.sendMessage(C.RED + "Failed to save: " + schem.getName());
throw new IOException(e);
} }
} catch (Exception e) { } catch (Exception e) {
Iris.info(C.RED + "Failed to convert: " + schem.getName());
if (sender.isPlayer()) {
sender.sendMessage(C.RED + "Failed to convert: " + schem.getName()); 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()) { for (IrisObjectPlacement i : biome.getObjects()) {
if (i.getPlace().contains(object)) { if (i.getPlace().contains(object)) {

View File

@@ -69,7 +69,7 @@ public class PlannedPiece {
this.setRotation(rot); this.setRotation(rot);
this.ogObject = data.getObjectLoader().load(piece.getObject()); this.ogObject = data.getObjectLoader().load(piece.getObject());
this.object = structure.rotated(piece, rotation); 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.piece.setLoadKey(piece.getLoadKey());
this.object.setLoadKey(piece.getObject()); this.object.setLoadKey(piece.getObject());
this.ogObject.setLoadKey(piece.getObject()); this.ogObject.setLoadKey(piece.getObject());

View File

@@ -98,6 +98,8 @@ public class IrisObject extends IrisRegistrant {
@Getter @Getter
@Setter @Setter
private transient Vector3i center; private transient Vector3i center;
@Getter
private transient Vector3i shrinkOffset;
public IrisObject(int w, int h, int d) { public IrisObject(int w, int h, int d) {
blocks = new VectorMap<>(); blocks = new VectorMap<>();
@@ -106,6 +108,7 @@ public class IrisObject extends IrisRegistrant {
this.h = h; this.h = h;
this.d = d; this.d = d;
center = new Vector3i(w / 2, h / 2, d / 2); center = new Vector3i(w / 2, h / 2, d / 2);
shrinkOffset = new Vector3i(0, 0, 0);
var lock = new ReentrantReadWriteLock(); var lock = new ReentrantReadWriteLock();
readLock = lock.readLock(); readLock = lock.readLock();
writeLock = lock.writeLock(); 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())); blocks.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), B.get(din.readUTF()));
} }
if (din.available() == 0)
return;
try { try {
int size = din.readInt(); int size = din.readInt();
@@ -313,7 +319,6 @@ public class IrisObject extends IrisRegistrant {
} }
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);
} }
} }
@@ -323,7 +328,7 @@ public class IrisObject extends IrisRegistrant {
this.h = din.readInt(); this.h = din.readInt();
this.d = din.readInt(); this.d = din.readInt();
if (!din.readUTF().equals("Iris V2 IOB;")) { if (!din.readUTF().equals("Iris V2 IOB;")) {
return; throw new HeaderException();
} }
center = new Vector3i(w / 2, h / 2, d / 2); center = new Vector3i(w / 2, h / 2, d / 2);
int s = din.readShort(); int s = din.readShort();
@@ -470,16 +475,14 @@ public class IrisObject extends IrisRegistrant {
} }
public void read(File file) throws IOException { public void read(File file) throws IOException {
var fin = new BufferedInputStream(new FileInputStream(file)); try (var fin = new BufferedInputStream(new FileInputStream(file))) {
try {
read(fin); read(fin);
fin.close();
} catch (Throwable e) { } catch (Throwable e) {
if (!(e instanceof HeaderException))
Iris.reportError(e); Iris.reportError(e);
fin.close(); try (var fin = new BufferedInputStream(new FileInputStream(file))) {
fin = new BufferedInputStream(new FileInputStream(file));
readLegacy(fin); readLegacy(fin);
fin.close(); }
} }
} }
@@ -504,8 +507,9 @@ public class IrisObject extends IrisRegistrant {
} }
public void shrinkwrap() { public void shrinkwrap() {
BlockVector min = new BlockVector(); if (blocks.isEmpty()) return;
BlockVector max = new BlockVector(); 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()) { for (BlockVector i : blocks.keys()) {
min.setX(Math.min(min.getX(), i.getX())); min.setX(Math.min(min.getX(), i.getX()));
@@ -520,6 +524,31 @@ public class IrisObject extends IrisRegistrant {
h = max.getBlockY() - min.getBlockY() + 1; h = max.getBlockY() - min.getBlockY() + 1;
d = max.getBlockZ() - min.getBlockZ() + 1; d = max.getBlockZ() - min.getBlockZ() + 1;
center = new Vector3i(w / 2, h / 2, d / 2); 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() { public void clean() {
@@ -1150,8 +1179,8 @@ public class IrisObject extends IrisRegistrant {
blocks = d; blocks = d;
states = dx; states = dx;
writeLock.unlock();
shrinkwrap(); shrinkwrap();
writeLock.unlock();
} }
public void place(Location at) { public void place(Location at) {
@@ -1389,4 +1418,10 @@ public class IrisObject extends IrisRegistrant {
@Override @Override
public void scanForErrors(JSONObject p, VolmitSender sender) { 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.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.bukkit.Axis; import org.bukkit.Axis;
import org.bukkit.Material;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.data.*; import org.bukkit.block.data.*;
import org.bukkit.block.data.type.RedstoneWire;
import org.bukkit.block.data.type.Wall; import org.bukkit.block.data.type.Wall;
import org.bukkit.block.structure.StructureRotation;
import org.bukkit.util.BlockVector; import org.bukkit.util.BlockVector;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -101,15 +101,15 @@ public class IrisObjectRotation {
return e.rotateCopy(this); return e.rotateCopy(this);
} }
public IrisJigsawPiece rotateCopy(IrisJigsawPiece v) { public IrisJigsawPiece rotateCopy(IrisJigsawPiece v, IrisPosition offset) {
IrisJigsawPiece piece = v.copy(); IrisJigsawPiece piece = v.copy();
for (IrisJigsawPieceConnector i : piece.getConnectors()) { for (IrisJigsawPieceConnector i : piece.getConnectors()) {
i.setPosition(rotate(i.getPosition())); i.setPosition(rotate(i.getPosition()).add(offset));
i.setDirection(rotate(i.getDirection())); i.setDirection(rotate(i.getDirection()));
} }
try { try {
var translate = piece.getPlacementOptions().getTranslate(); 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()); translate.setX(pos.getX()).setY(pos.getY()).setZ(pos.getZ());
} catch (NullPointerException ignored) {} } catch (NullPointerException ignored) {}
@@ -259,14 +259,14 @@ public class IrisObjectRotation {
g.setRotation(face); g.setRotation(face);
} else if (d instanceof Orientable) { } else if (d instanceof Orientable g) {
BlockFace f = getFace(((Orientable) d).getAxis()); BlockFace f = getFace(g.getAxis());
BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ()); BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ());
bv = rotate(bv.clone(), spinx, spiny, spinz); bv = rotate(bv.clone(), spinx, spiny, spinz);
Axis a = getAxis(bv); Axis a = getAxis(bv);
if (!a.equals(((Orientable) d).getAxis()) && ((Orientable) d).getAxes().contains(a)) { if (!a.equals(g.getAxis()) && g.getAxes().contains(a)) {
((Orientable) d).setAxis(a); g.setAxis(a);
} }
} else if (d instanceof MultipleFacing g) { } else if (d instanceof MultipleFacing g) {
List<BlockFace> faces = new KList<>(); List<BlockFace> faces = new KList<>();
@@ -304,14 +304,22 @@ public class IrisObjectRotation {
for (BlockFace i : WALL_FACES) { for (BlockFace i : WALL_FACES) {
wall.setHeight(i, faces.getOrDefault(i, Wall.Height.NONE)); wall.setHeight(i, faces.getOrDefault(i, Wall.Height.NONE));
} }
} else if (d.getMaterial().equals(Material.NETHER_PORTAL) && d instanceof Orientable g) { } else if (d instanceof RedstoneWire wire) {
//TODO: Fucks up logs Map<BlockFace, RedstoneWire.Connection> faces = new HashMap<>();
BlockFace f = faceForAxis(g.getAxis());
BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ()); 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); bv = rotate(bv.clone(), spinx, spiny, spinz);
BlockFace t = getFace(bv); BlockFace r = getFace(bv);
Axis a = !g.getAxes().contains(Axis.Y) ? axisFor(t) : axisFor2D(t); if (allowed.contains(r))
((Orientable) d).setAxis(a); faces.put(r, connection);
}
for (BlockFace i : allowed) {
wire.setFace(i, faces.getOrDefault(i, RedstoneWire.Connection.NONE));
}
} }
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);

View File

@@ -360,6 +360,7 @@ public class B {
public static boolean isFoliagePlantable(BlockData d) { public static boolean isFoliagePlantable(BlockData d) {
return d.getMaterial().equals(Material.GRASS_BLOCK) return d.getMaterial().equals(Material.GRASS_BLOCK)
|| d.getMaterial().equals(Material.MOSS_BLOCK)
|| d.getMaterial().equals(Material.ROOTED_DIRT) || d.getMaterial().equals(Material.ROOTED_DIRT)
|| d.getMaterial().equals(Material.DIRT) || d.getMaterial().equals(Material.DIRT)
|| d.getMaterial().equals(Material.COARSE_DIRT) || d.getMaterial().equals(Material.COARSE_DIRT)
@@ -368,6 +369,7 @@ public class B {
public static boolean isFoliagePlantable(Material d) { public static boolean isFoliagePlantable(Material d) {
return d.equals(Material.GRASS_BLOCK) return d.equals(Material.GRASS_BLOCK)
|| d.equals(Material.MOSS_BLOCK)
|| d.equals(Material.DIRT) || d.equals(Material.DIRT)
|| d.equals(TALL_GRASS) || d.equals(TALL_GRASS)
|| d.equals(TALL_SEAGRASS) || 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.Iris;
import com.volmit.iris.util.plugin.VolmitSender; 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.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
@@ -495,6 +496,14 @@ public enum C {
return STRIP_COLOR_PATTERN.matcher(input).replaceAll(""); 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 * DyeColor to ChatColor
* *

View File

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

View File

@@ -56,7 +56,7 @@ public class Bindings {
options.setEnvironment(BuildConstants.ENVIRONMENT); options.setEnvironment(BuildConstants.ENVIRONMENT);
options.setBeforeSend((event, hint) -> { options.setBeforeSend((event, hint) -> {
if (suppress(event.getThrowable())) return null; 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()); event.setTag("iris.nms", INMS.get().getClass().getCanonicalName());
var context = IrisContext.get(); var context = IrisContext.get();
if (context != null) event.getContexts().set("engine", context.asContext()); if (context != null) event.getContexts().set("engine", context.asContext());
@@ -67,6 +67,7 @@ public class Bindings {
Sentry.configureScope(scope -> { Sentry.configureScope(scope -> {
if (settings.includeServerId) scope.setUser(ServerID.asUser()); if (settings.includeServerId) scope.setUser(ServerID.asUser());
scope.addAttachment(Attachments.PLUGINS); scope.addAttachment(Attachments.PLUGINS);
scope.addAttachment(Attachments.SAFEGUARD);
scope.setTag("server", Bukkit.getVersion()); scope.setTag("server", Bukkit.getVersion());
scope.setTag("server.type", Bukkit.getName()); scope.setTag("server.type", Bukkit.getName());
scope.setTag("server.api", Bukkit.getBukkitVersion()); 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.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.volmit.iris.core.safeguard.IrisSafeguard;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import io.sentry.Attachment; import io.sentry.Attachment;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -12,6 +13,7 @@ import java.util.concurrent.Callable;
public class Attachments { public class Attachments {
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
public static final Attachment PLUGINS = jsonProvider(Attachments::plugins, "plugins.json"); 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) { public static Attachment json(Object object, String name) {
return new Attachment(GSON.toJson(object).getBytes(StandardCharsets.UTF_8), name, "application/json", "event.attachment", true); 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 @BlockCoordinates
@Suppress("UNCHECKED_CAST")
fun get(x: Int, z: Int): T? { fun get(x: Int, z: Int): T? {
if (!cache) { if (!cache) {
return stream.get((this.x + x).toDouble(), (this.z + z).toDouble()) 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.data.Varint
import com.volmit.iris.util.mantle.flag.MantleFlag import com.volmit.iris.util.mantle.flag.MantleFlag
import com.volmit.iris.util.parallel.AtomicBooleanArray 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.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import java.io.DataInput import java.io.DataInput
@@ -22,9 +25,21 @@ abstract class FlaggedChunk() {
abstract fun isClosed(): Boolean 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()) { for (i in 0 until flags.length()) {
flags.set(i, other.flags.get(i)) launch { locks[i].lock() }.start()
}
}
action.run()
for (i in 0 until flags.length()) {
flags[i] = other.flags[i]
}
for (i in 0 until flags.length()) {
locks[i].unlock()
} }
} }