mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-08-16 16:26:12 +00:00
Merge branch 'dev' into feat/datapack_structures
This commit is contained in:
commit
d11c8c990a
@ -1,5 +1,6 @@
|
|||||||
import io.github.slimjar.func.slimjar
|
import io.github.slimjar.func.slimjarHelper
|
||||||
import io.github.slimjar.resolver.data.Mirror
|
import io.github.slimjar.resolver.data.Mirror
|
||||||
|
import org.ajoberstar.grgit.Grgit
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -26,6 +27,7 @@ plugins {
|
|||||||
alias(libs.plugins.shadow)
|
alias(libs.plugins.shadow)
|
||||||
alias(libs.plugins.sentry)
|
alias(libs.plugins.sentry)
|
||||||
alias(libs.plugins.slimjar)
|
alias(libs.plugins.slimjar)
|
||||||
|
alias(libs.plugins.grgit)
|
||||||
}
|
}
|
||||||
|
|
||||||
val apiVersion = "1.19"
|
val apiVersion = "1.19"
|
||||||
@ -65,7 +67,7 @@ dependencies {
|
|||||||
compileOnly(libs.multiverseCore)
|
compileOnly(libs.multiverseCore)
|
||||||
|
|
||||||
// Shaded
|
// Shaded
|
||||||
implementation(slimjar())
|
implementation(slimjarHelper("spigot"))
|
||||||
|
|
||||||
// Dynamically Loaded
|
// Dynamically Loaded
|
||||||
slim(libs.paralithic)
|
slim(libs.paralithic)
|
||||||
@ -138,6 +140,15 @@ tasks {
|
|||||||
"version" to rootProject.version,
|
"version" to rootProject.version,
|
||||||
"apiVersion" to apiVersion,
|
"apiVersion" to apiVersion,
|
||||||
"main" to main,
|
"main" to main,
|
||||||
|
"environment" to if (project.hasProperty("release")) "production" else "development",
|
||||||
|
"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())
|
||||||
|
"unknown"
|
||||||
|
}()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
filesMatching("**/plugin.yml") {
|
filesMatching("**/plugin.yml") {
|
||||||
expand(inputs.properties)
|
expand(inputs.properties)
|
||||||
@ -148,6 +159,7 @@ tasks {
|
|||||||
mergeServiceFiles()
|
mergeServiceFiles()
|
||||||
//minimize()
|
//minimize()
|
||||||
relocate("io.github.slimjar", "$lib.slimjar")
|
relocate("io.github.slimjar", "$lib.slimjar")
|
||||||
|
exclude("modules/loader-agent.isolated-jar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import com.google.gson.JsonObject;
|
|||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.IrisWorlds;
|
||||||
import com.volmit.iris.core.ServerConfigurator;
|
import com.volmit.iris.core.ServerConfigurator;
|
||||||
import com.volmit.iris.core.link.IrisPapiExpansion;
|
import com.volmit.iris.core.link.IrisPapiExpansion;
|
||||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||||
@ -65,9 +66,6 @@ import org.bukkit.*;
|
|||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.*;
|
import org.bukkit.event.*;
|
||||||
import org.bukkit.generator.BiomeProvider;
|
import org.bukkit.generator.BiomeProvider;
|
||||||
@ -81,6 +79,7 @@ import java.io.*;
|
|||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
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;
|
||||||
|
|
||||||
@ -436,8 +435,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
|
|
||||||
public Iris() {
|
public Iris() {
|
||||||
instance = this;
|
instance = this;
|
||||||
SlimJar.debug(IrisSettings.get().getSentry().isDebug());
|
SlimJar.load();
|
||||||
SlimJar.load(getDataFolder("cache", "libraries"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enable() {
|
private void enable() {
|
||||||
@ -467,48 +465,34 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
IrisSafeguard.splash(false);
|
IrisSafeguard.splash(false);
|
||||||
|
|
||||||
autoStartStudio();
|
autoStartStudio();
|
||||||
checkForBukkitWorlds();
|
checkForBukkitWorlds(s -> true);
|
||||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||||
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForBukkitWorlds() {
|
public void checkForBukkitWorlds(Predicate<String> filter) {
|
||||||
FileConfiguration fc = new YamlConfiguration();
|
|
||||||
try {
|
try {
|
||||||
fc.load(new File("bukkit.yml"));
|
IrisWorlds.readBukkitWorlds().forEach((s, generator) -> {
|
||||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
try {
|
||||||
if (section == null) {
|
if (Bukkit.getWorld(s) != null || !filter.test(s)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String s : section.getKeys(false)) {
|
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
||||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
var gen = getDefaultWorldGenerator(s, generator);
|
||||||
if (!entry.contains("generator", true)) {
|
var dim = loadDimension(s, generator);
|
||||||
continue;
|
assert dim != null && gen != null;
|
||||||
|
|
||||||
|
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||||
|
WorldCreator c = new WorldCreator(s)
|
||||||
|
.generator(gen)
|
||||||
|
.environment(dim.getEnvironment());
|
||||||
|
INMS.get().createWorld(c);
|
||||||
|
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.error("Failed to load world " + s + "!");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
String generator = entry.getString("generator");
|
|
||||||
if (generator.startsWith("Iris:")) {
|
|
||||||
generator = generator.split("\\Q:\\E")[1];
|
|
||||||
} else if (generator.equalsIgnoreCase("Iris")) {
|
|
||||||
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Bukkit.getWorld(s) != null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
|
||||||
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
|
||||||
WorldCreator c = new WorldCreator(s)
|
|
||||||
.generator(getDefaultWorldGenerator(s, generator))
|
|
||||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
|
||||||
INMS.get().createWorld(c);
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
reportError(e);
|
reportError(e);
|
||||||
|
@ -23,7 +23,6 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
import com.volmit.iris.util.json.JSONException;
|
import com.volmit.iris.util.json.JSONException;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.misc.SlimJar;
|
|
||||||
import com.volmit.iris.util.misc.getHardware;
|
import com.volmit.iris.util.misc.getHardware;
|
||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -87,7 +86,6 @@ public class IrisSettings {
|
|||||||
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
Iris.error("Configuration Error in settings.json! " + ee.getClass().getSimpleName() + ": " + ee.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SlimJar.debug(settings.general.debug);
|
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,14 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||||
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.misc.ServerProperties;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -25,6 +29,7 @@ public class IrisWorlds {
|
|||||||
|
|
||||||
private IrisWorlds(KMap<String, String> worlds) {
|
private IrisWorlds(KMap<String, String> worlds) {
|
||||||
this.worlds = worlds;
|
this.worlds = worlds;
|
||||||
|
readBukkitWorlds().forEach(this::put0);
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,14 +55,33 @@ public class IrisWorlds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void put(String name, String type) {
|
public void put(String name, String type) {
|
||||||
String old = worlds.put(name, type);
|
put0(name, type);
|
||||||
if (!type.equals(old))
|
|
||||||
dirty = true;
|
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<File> getFolders() {
|
private void put0(String name, String type) {
|
||||||
return worlds.keySet().stream().map(k -> new File(Bukkit.getWorldContainer(), k));
|
String old = worlds.put(name, type);
|
||||||
|
if (!type.equals(old))
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KMap<String, String> getWorlds() {
|
||||||
|
return readBukkitWorlds().put(worlds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<IrisData> getPacks() {
|
||||||
|
return getDimensions()
|
||||||
|
.map(IrisDimension::getLoader)
|
||||||
|
.filter(Objects::nonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<IrisDimension> getDimensions() {
|
||||||
|
return readBukkitWorlds()
|
||||||
|
.put(worlds)
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.map(entry -> Iris.loadDimension(entry.getKey(), entry.getValue()))
|
||||||
|
.filter(Objects::nonNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clean() {
|
public void clean() {
|
||||||
@ -76,4 +100,27 @@ public class IrisWorlds {
|
|||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static KMap<String, String> readBukkitWorlds() {
|
||||||
|
var bukkit = YamlConfiguration.loadConfiguration(ServerProperties.BUKKIT_YML);
|
||||||
|
var worlds = bukkit.getConfigurationSection("worlds");
|
||||||
|
if (worlds == null) return new KMap<>();
|
||||||
|
|
||||||
|
var result = new KMap<String, String>();
|
||||||
|
for (String world : worlds.getKeys(false)) {
|
||||||
|
var gen = worlds.getString(world + ".generator");
|
||||||
|
if (gen == null) continue;
|
||||||
|
|
||||||
|
String loadKey;
|
||||||
|
if (gen.equalsIgnoreCase("iris")) {
|
||||||
|
loadKey = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||||
|
} else if (gen.startsWith("Iris:")) {
|
||||||
|
loadKey = gen.substring(5);
|
||||||
|
} else continue;
|
||||||
|
|
||||||
|
result.put(world, loadKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,14 +237,13 @@ public class ServerConfigurator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<IrisData> allPacks() {
|
public static Stream<IrisData> allPacks() {
|
||||||
return Stream.concat(listFiles(Iris.instance.getDataFolder("packs")),
|
return Stream.concat(listFiles(Iris.instance.getDataFolder("packs"))
|
||||||
IrisWorlds.get().getFolders().map(w -> new File(w, "iris/pack")))
|
|
||||||
.filter(File::isDirectory)
|
.filter(File::isDirectory)
|
||||||
.filter( base -> {
|
.filter( base -> {
|
||||||
var content = new File(base, "dimensions").listFiles();
|
var content = new File(base, "dimensions").listFiles();
|
||||||
return content != null && content.length > 0;
|
return content != null && content.length > 0;
|
||||||
})
|
})
|
||||||
.map(IrisData::get);
|
.map(IrisData::get), IrisWorlds.get().getPacks());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -20,15 +20,12 @@ package com.volmit.iris.core.commands;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
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.pregenerator.ChunkUpdater;
|
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||||
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;
|
||||||
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.IrisWorld;
|
|
||||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
@ -44,21 +41,17 @@ import com.volmit.iris.util.scheduling.J;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldCreator;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static com.volmit.iris.Iris.service;
|
|
||||||
import static com.volmit.iris.core.service.EditSVC.deletingWorld;
|
import static com.volmit.iris.core.service.EditSVC.deletingWorld;
|
||||||
|
import static com.volmit.iris.util.misc.ServerProperties.BUKKIT_YML;
|
||||||
import static org.bukkit.Bukkit.getServer;
|
import static org.bukkit.Bukkit.getServer;
|
||||||
|
|
||||||
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
||||||
@ -130,6 +123,7 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
worldCreation = false;
|
worldCreation = false;
|
||||||
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||||
|
if (main) sender().sendMessage(C.GREEN + "Your world will automatically be set as the main world when the server restarts.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@ -394,17 +388,19 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GREEN + "Set debug to: " + to);
|
sender().sendMessage(C.GREEN + "Set debug to: " + to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO fix pack trimming
|
||||||
@Decree(description = "Download a project.", aliases = "dl")
|
@Decree(description = "Download a project.", aliases = "dl")
|
||||||
public void download(
|
public void download(
|
||||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||||
String pack,
|
String pack,
|
||||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "main")
|
@Param(name = "branch", description = "The branch to download from", defaultValue = "main")
|
||||||
String branch,
|
String branch,
|
||||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
//@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||||
boolean trim,
|
//boolean trim,
|
||||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||||
boolean overwrite
|
boolean overwrite
|
||||||
) {
|
) {
|
||||||
|
boolean trim = false;
|
||||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (trim ? " trimmed" : "") + (overwrite ? " overwriting" : ""));
|
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (trim ? " trimmed" : "") + (overwrite ? " overwriting" : ""));
|
||||||
if (pack.equals("overworld")) {
|
if (pack.equals("overworld")) {
|
||||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + INMS.OVERWORLD_TAG + "/overworld.zip";
|
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + INMS.OVERWORLD_TAG + "/overworld.zip";
|
||||||
@ -502,7 +498,6 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File BUKKIT_YML = new File("bukkit.yml");
|
|
||||||
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
|
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
|
||||||
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
|
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
|
||||||
|
|
||||||
@ -540,7 +535,7 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkForBukkitWorlds(world);
|
Iris.instance.checkForBukkitWorlds(world::equals);
|
||||||
sender().sendMessage(C.GREEN + world + " loaded successfully.");
|
sender().sendMessage(C.GREEN + world + " loaded successfully.");
|
||||||
}
|
}
|
||||||
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
|
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
|
||||||
@ -561,85 +556,4 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
File worldDirectory = new File(worldContainer, worldName);
|
File worldDirectory = new File(worldContainer, worldName);
|
||||||
return worldDirectory.exists() && worldDirectory.isDirectory();
|
return worldDirectory.exists() && worldDirectory.isDirectory();
|
||||||
}
|
}
|
||||||
private void checkForBukkitWorlds(String world) {
|
|
||||||
FileConfiguration fc = new YamlConfiguration();
|
|
||||||
try {
|
|
||||||
fc.load(new File("bukkit.yml"));
|
|
||||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
|
||||||
if (section == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> worldsToLoad = Collections.singletonList(world);
|
|
||||||
|
|
||||||
for (String s : section.getKeys(false)) {
|
|
||||||
if (!worldsToLoad.contains(s)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
|
||||||
if (!entry.contains("generator", true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String generator = entry.getString("generator");
|
|
||||||
if (generator.startsWith("Iris:")) {
|
|
||||||
generator = generator.split("\\Q:\\E")[1];
|
|
||||||
} else if (generator.equalsIgnoreCase("Iris")) {
|
|
||||||
generator = IrisSettings.get().getGenerator().getDefaultWorldType();
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Iris.info("2 World: %s | Generator: %s", s, generator);
|
|
||||||
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
|
||||||
WorldCreator c = new WorldCreator(s)
|
|
||||||
.generator(getDefaultWorldGenerator(s, generator))
|
|
||||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
|
||||||
INMS.get().createWorld(c);
|
|
||||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
|
||||||
Iris.debug("Default World Generator Called for " + worldName + " using ID: " + id);
|
|
||||||
IrisDimension dim;
|
|
||||||
if (id == null || id.isEmpty()) {
|
|
||||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
|
||||||
} else {
|
|
||||||
dim = IrisData.loadAnyDimension(id);
|
|
||||||
}
|
|
||||||
Iris.debug("Generator ID: " + id + " requested by bukkit/plugin");
|
|
||||||
|
|
||||||
if (dim == null) {
|
|
||||||
Iris.warn("Unable to find dimension type " + id + " Looking for online packs...");
|
|
||||||
|
|
||||||
service(StudioSVC.class).downloadSearch(new VolmitSender(Bukkit.getConsoleSender()), id, true);
|
|
||||||
dim = IrisData.loadAnyDimension(id);
|
|
||||||
|
|
||||||
if (dim == null) {
|
|
||||||
throw new RuntimeException("Can't find dimension " + id + "!");
|
|
||||||
} else {
|
|
||||||
Iris.info("Resolved missing dimension, proceeding with generation.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iris.debug("Assuming IrisDimension: " + dim.getName());
|
|
||||||
IrisWorld w = IrisWorld.builder()
|
|
||||||
.name(worldName)
|
|
||||||
.seed(1337)
|
|
||||||
.environment(dim.getEnvironment())
|
|
||||||
.worldFolder(new File(Bukkit.getWorldContainer(), worldName))
|
|
||||||
.minHeight(dim.getMinHeight())
|
|
||||||
.maxHeight(dim.getMaxHeight())
|
|
||||||
.build();
|
|
||||||
Iris.debug("Generator Config: " + w.toString());
|
|
||||||
File ff = new File(w.worldFolder(), "iris/pack");
|
|
||||||
if (!ff.exists() || ff.listFiles().length == 0) {
|
|
||||||
ff.mkdirs();
|
|
||||||
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
|
|
||||||
}
|
|
||||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -92,18 +92,19 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO fix pack trimming
|
||||||
@Decree(description = "Download a project.", aliases = "dl")
|
@Decree(description = "Download a project.", aliases = "dl")
|
||||||
public void download(
|
public void download(
|
||||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||||
String pack,
|
String pack,
|
||||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
||||||
String branch,
|
String branch,
|
||||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
//@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||||
boolean trim,
|
//boolean trim,
|
||||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||||
boolean overwrite
|
boolean overwrite
|
||||||
) {
|
) {
|
||||||
new CommandIris().download(pack, branch, trim, overwrite);
|
new CommandIris().download(pack, branch, overwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
@Decree(description = "Open a new studio world", aliases = "o", sync = true)
|
||||||
|
@ -3,10 +3,14 @@ package com.volmit.iris.core.link.data;
|
|||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||||
import com.volmit.iris.core.link.Identifier;
|
import com.volmit.iris.core.link.Identifier;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
|
import com.volmit.iris.util.data.IrisCustomData;
|
||||||
import dev.lone.itemsadder.api.CustomBlock;
|
import dev.lone.itemsadder.api.CustomBlock;
|
||||||
import dev.lone.itemsadder.api.CustomStack;
|
import dev.lone.itemsadder.api.CustomStack;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -40,7 +44,11 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
CustomBlock block = CustomBlock.getInstance(blockId.toString());
|
||||||
|
if (block == null) {
|
||||||
|
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||||
|
}
|
||||||
|
return new IrisCustomData(B.getAir(), blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -53,6 +61,11 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
|
|||||||
return stack.getItemStack();
|
return stack.getItemStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||||
|
CustomBlock.place(blockId.toString(), block.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||||
return switch (dataType) {
|
return switch (dataType) {
|
||||||
|
@ -36,7 +36,7 @@ import com.volmit.iris.util.format.C;
|
|||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.reflect.OldEnum;
|
import com.volmit.iris.util.reflect.KeyedType;
|
||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -341,14 +341,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
this.imageLoader = registerLoader(IrisImage.class);
|
this.imageLoader = registerLoader(IrisImage.class);
|
||||||
this.scriptLoader = registerLoader(IrisScript.class);
|
this.scriptLoader = registerLoader(IrisScript.class);
|
||||||
this.matterObjectLoader = registerLoader(IrisMatterObject.class);
|
this.matterObjectLoader = registerLoader(IrisMatterObject.class);
|
||||||
if (OldEnum.exists()) {
|
builder.registerTypeAdapterFactory(KeyedType::createTypeAdapter);
|
||||||
builder.registerTypeAdapterFactory(new TypeAdapterFactory() {
|
|
||||||
@Override
|
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
|
||||||
return (TypeAdapter<T>) OldEnum.create(type.getRawType());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
gson = builder.create();
|
gson = builder.create();
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import com.volmit.iris.util.collection.KMap;
|
|||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.json.JSONObject;
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
import com.volmit.iris.util.reflect.OldEnum;
|
import com.volmit.iris.util.reflect.KeyedType;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -336,10 +336,10 @@ public class SchemaBuilder {
|
|||||||
prop.put("$ref", "#/definitions/" + key);
|
prop.put("$ref", "#/definitions/" + key);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
|
|
||||||
|
} else if (KeyedType.isKeyed(k.getType())) {
|
||||||
|
fancyType = addEnum(k.getType(), prop, description, KeyedType.values(k.getType()), Function.identity());
|
||||||
} else if (k.getType().isEnum()) {
|
} else if (k.getType().isEnum()) {
|
||||||
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
} else if (OldEnum.isOldEnum(k.getType())) {
|
|
||||||
fancyType = addEnum(k.getType(), prop, description, OldEnum.values(k.getType()), OldEnum::name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "object" -> {
|
case "object" -> {
|
||||||
@ -504,10 +504,10 @@ public class SchemaBuilder {
|
|||||||
items.put("$ref", "#/definitions/" + key);
|
items.put("$ref", "#/definitions/" + key);
|
||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||||
|
} else if (KeyedType.isKeyed(t.type())) {
|
||||||
|
fancyType = addEnumList(prop, description, t, KeyedType.values(t.type()), Function.identity());
|
||||||
} else if (t.type().isEnum()) {
|
} else if (t.type().isEnum()) {
|
||||||
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||||
} else if (OldEnum.isOldEnum(t.type())) {
|
|
||||||
fancyType = addEnumList(prop, description, t, OldEnum.values(t.type()), OldEnum::name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -548,7 +548,7 @@ public class SchemaBuilder {
|
|||||||
if (value instanceof List) {
|
if (value instanceof List) {
|
||||||
d.add(" ");
|
d.add(" ");
|
||||||
d.add("* Default Value is an empty list");
|
d.add("* Default Value is an empty list");
|
||||||
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()) && !OldEnum.isOldEnum(cl)) {
|
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()) && !KeyedType.isKeyed(cl)) {
|
||||||
d.add(" ");
|
d.add(" ");
|
||||||
d.add("* Default Value is a default object (create this object to see default properties)");
|
d.add("* Default Value is a default object (create this object to see default properties)");
|
||||||
} else {
|
} else {
|
||||||
@ -596,7 +596,7 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String addEnumList(JSONObject prop, KList<String> description, ArrayType t, Object[] values, Function<Object, String> function) {
|
private <T> String addEnumList(JSONObject prop, KList<String> description, ArrayType t, T[] values, Function<T, String> function) {
|
||||||
JSONObject items = new JSONObject();
|
JSONObject items = new JSONObject();
|
||||||
var s = addEnum(t.type(), items, description, values, function);
|
var s = addEnum(t.type(), items, description, values, function);
|
||||||
prop.put("items", items);
|
prop.put("items", items);
|
||||||
@ -605,10 +605,10 @@ public class SchemaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private String addEnum(Class<?> type, JSONObject prop, KList<String> description, Object[] values, Function<Object, String> function) {
|
private <T> String addEnum(Class<?> type, JSONObject prop, KList<String> description, T[] values, Function<T, String> function) {
|
||||||
JSONArray a = new JSONArray();
|
JSONArray a = new JSONArray();
|
||||||
boolean advanced = type.isAnnotationPresent(Desc.class);
|
boolean advanced = type.isAnnotationPresent(Desc.class);
|
||||||
for (Object gg : values) {
|
for (T gg : values) {
|
||||||
if (advanced) {
|
if (advanced) {
|
||||||
try {
|
try {
|
||||||
JSONObject j = new JSONObject();
|
JSONObject j = new JSONObject();
|
||||||
@ -652,7 +652,7 @@ public class SchemaBuilder {
|
|||||||
return "boolean";
|
return "boolean";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.equals(String.class) || c.isEnum() || OldEnum.isOldEnum(c) || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
|
if (c.equals(String.class) || c.isEnum() || KeyedType.isKeyed(c)) {
|
||||||
return "string";
|
return "string";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package com.volmit.iris.core.safeguard;
|
package com.volmit.iris.core.safeguard;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisWorlds;
|
||||||
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.nms.v1X.NMSBinding1X;
|
||||||
import com.volmit.iris.engine.object.IrisDimension;
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
import com.volmit.iris.util.agent.Agent;
|
import com.volmit.iris.util.agent.Agent;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.misc.ServerProperties;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import javax.tools.JavaCompiler;
|
import javax.tools.JavaCompiler;
|
||||||
@ -21,6 +19,7 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.volmit.iris.Iris.getJavaVersion;
|
import static com.volmit.iris.Iris.getJavaVersion;
|
||||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||||
@ -187,27 +186,9 @@ public class ServerBootSFG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static KSet<String> getDimensionTypes() {
|
private static KSet<String> getDimensionTypes() {
|
||||||
var bukkit = YamlConfiguration.loadConfiguration(ServerProperties.BUKKIT_YML);
|
return IrisWorlds.get()
|
||||||
var worlds = bukkit.getConfigurationSection("worlds");
|
.getDimensions()
|
||||||
if (worlds == null) return new KSet<>();
|
.map(IrisDimension::getDimensionTypeKey)
|
||||||
|
.collect(Collectors.toCollection(KSet::new));
|
||||||
var types = new KSet<String>();
|
|
||||||
for (String world : worlds.getKeys(false)) {
|
|
||||||
var gen = worlds.getString(world + ".generator");
|
|
||||||
if (gen == null) continue;
|
|
||||||
|
|
||||||
String loadKey;
|
|
||||||
if (gen.equalsIgnoreCase("iris")) {
|
|
||||||
loadKey = IrisSettings.get().getGenerator().getDefaultWorldType();
|
|
||||||
} else if (gen.startsWith("Iris:")) {
|
|
||||||
loadKey = gen.substring(5);
|
|
||||||
} else continue;
|
|
||||||
|
|
||||||
IrisDimension dimension = Iris.loadDimension(world, loadKey);
|
|
||||||
if (dimension == null) continue;
|
|
||||||
types.add(dimension.getDimensionTypeKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
return types;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static com.volmit.iris.util.misc.ServerProperties.BUKKIT_YML;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes it a lot easier to setup an engine, world, studio or whatever
|
* Makes it a lot easier to setup an engine, world, studio or whatever
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(fluent = true, chain = true)
|
@Accessors(fluent = true, chain = true)
|
||||||
public class IrisCreator {
|
public class IrisCreator {
|
||||||
private static final File BUKKIT_YML = new File("bukkit.yml");
|
|
||||||
/**
|
/**
|
||||||
* Specify an area to pregenerate during creation
|
* Specify an area to pregenerate during creation
|
||||||
*/
|
*/
|
||||||
|
@ -21,13 +21,10 @@ package com.volmit.iris.core.tools;
|
|||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||||
import com.volmit.iris.util.reflect.WrappedField;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.WorldCreator;
|
||||||
import org.bukkit.WorldType;
|
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
import sun.misc.Unsafe;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ import com.volmit.iris.util.mantle.MantleFlag;
|
|||||||
import com.volmit.iris.util.math.M;
|
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.matter.MatterStructurePOI;
|
import com.volmit.iris.util.matter.MatterStructurePOI;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
|
||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
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;
|
||||||
@ -223,6 +224,12 @@ public class IrisEngine implements Engine {
|
|||||||
return getMantle().getJigsawComponent().guess(x, z);
|
return getMantle().getJigsawComponent().guess(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IrisJigsawStructure getStructureAt(int x, int y, int z) {
|
||||||
|
var container = getMantle().getMantle().get(x, y, z, JigsawStructureContainer.class);
|
||||||
|
return container == null ? null : container.load(getData());
|
||||||
|
}
|
||||||
|
|
||||||
private void warmupChunk(int x, int z) {
|
private void warmupChunk(int x, int z) {
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
for (int j = 0; j < 16; j++) {
|
for (int j = 0; j < 16; j++) {
|
||||||
|
@ -231,6 +231,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
IrisJigsawStructure getStructureAt(int x, int z);
|
IrisJigsawStructure getStructureAt(int x, int z);
|
||||||
|
|
||||||
|
@BlockCoordinates
|
||||||
|
IrisJigsawStructure getStructureAt(int x, int y, int z);
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
default IrisBiome getCaveBiome(int x, int z) {
|
default IrisBiome getCaveBiome(int x, int z) {
|
||||||
return getComplex().getCaveBiomeStream().get(x, z);
|
return getComplex().getCaveBiomeStream().get(x, z);
|
||||||
@ -262,7 +265,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
getMantle().updateBlock(x, y, z);
|
getMantle().updateBlock(x, y, z);
|
||||||
}
|
}
|
||||||
if (data instanceof IrisCustomData) {
|
if (data instanceof IrisCustomData) {
|
||||||
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM, true);
|
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM_ACTIVE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import com.volmit.iris.util.mantle.Mantle;
|
|||||||
import com.volmit.iris.util.math.Position2;
|
import com.volmit.iris.util.math.Position2;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
|
||||||
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -149,11 +150,13 @@ public class PlannedStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int id = rng.i(0, Integer.MAX_VALUE);
|
int id = rng.i(0, Integer.MAX_VALUE);
|
||||||
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
|
JigsawPieceContainer piece = JigsawPieceContainer.toContainer(i.getPiece());
|
||||||
|
JigsawStructureContainer structure = JigsawStructureContainer.toContainer(getStructure());
|
||||||
i.setRealPositions(xx, height, zz, placer);
|
i.setRealPositions(xx, height, zz, placer);
|
||||||
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
||||||
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
||||||
e.set(b.getX(), b.getY(), b.getZ(), container);
|
e.set(b.getX(), b.getY(), b.getZ(), structure);
|
||||||
|
e.set(b.getX(), b.getY(), b.getZ(), piece);
|
||||||
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package com.volmit.iris.util.collection;
|
package com.volmit.iris.util.collection;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.AtomicDoubleArray;
|
import com.google.common.util.concurrent.AtomicDoubleArray;
|
||||||
|
import com.volmit.iris.util.function.NastyFunction;
|
||||||
import com.volmit.iris.util.json.JSONArray;
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
@ -306,6 +307,18 @@ public class KList<T> extends ArrayList<T> implements List<T> {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this list into another list type. Such as GList<Integer> to
|
||||||
|
* GList<String>. list.convertNasty((i) -> "" + i);
|
||||||
|
*/
|
||||||
|
public <V> KList<V> convertNasty(NastyFunction<T, V> converter) throws Throwable {
|
||||||
|
KList<V> v = new KList<V>(size());
|
||||||
|
for (final var t : this) {
|
||||||
|
v.addNonNull(converter.run(t));
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
public KList<T> removeWhere(Predicate<T> t) {
|
public KList<T> removeWhere(Predicate<T> t) {
|
||||||
for (T i : copy()) {
|
for (T i : copy()) {
|
||||||
if (t.test(i)) {
|
if (t.test(i)) {
|
||||||
|
@ -0,0 +1,137 @@
|
|||||||
|
package com.volmit.iris.util.data.registry;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.Keyed;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.Registry;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public interface KeyedRegistry<T> {
|
||||||
|
@NonNull Map<NamespacedKey, T> map();
|
||||||
|
|
||||||
|
@Nullable T get(@NonNull NamespacedKey key);
|
||||||
|
@Nullable NamespacedKey keyOf(@NonNull T value);
|
||||||
|
|
||||||
|
default boolean isEmpty() {
|
||||||
|
return map().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
default Optional<T> find(@NonNull String @NonNull ... keys) {
|
||||||
|
if (keys.length == 0) throw new IllegalArgumentException("Need at least one key");
|
||||||
|
for (final String key : keys) {
|
||||||
|
final T t = get(NamespacedKey.minecraft(key));
|
||||||
|
if (t != null) {
|
||||||
|
return Optional.of(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
default Optional<T> find(@NonNull NamespacedKey @NonNull ... keys) {
|
||||||
|
if (keys.length == 0) throw new IllegalArgumentException("Need at least one key");
|
||||||
|
for (final NamespacedKey key : keys) {
|
||||||
|
final T t = get(key);
|
||||||
|
if (t != null) {
|
||||||
|
return Optional.of(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract(value = "null -> null; !null -> new", pure = true)
|
||||||
|
static <T> KeyedRegistry<T> wrapped(Map<NamespacedKey, T> map) {
|
||||||
|
if (map == null) return null;
|
||||||
|
return new MappedRegistry<>(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract(value = "null -> null; !null -> new", pure = true)
|
||||||
|
static <T extends Keyed> KeyedRegistry<T> wrapped(Registry<T> registry) {
|
||||||
|
if (registry == null) return null;
|
||||||
|
return new BukkitRegistry<>(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract(value = "_ -> new", pure = true)
|
||||||
|
static <T> KeyedRegistry<T> wrapped(@NonNull Collection<@NonNull KeyedRegistry<T>> registries) {
|
||||||
|
return new CompoundRegistry<>(registries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
record MappedRegistry<T>(Map<NamespacedKey, T> map) implements KeyedRegistry<T> {
|
||||||
|
@Override
|
||||||
|
public @Nullable T get(@NonNull NamespacedKey key) {
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable NamespacedKey keyOf(@NonNull T value) {
|
||||||
|
return map.entrySet().stream()
|
||||||
|
.filter(e -> e.getValue().equals(value))
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record BukkitRegistry<T extends Keyed>(Registry<T> registry) implements KeyedRegistry<T> {
|
||||||
|
@Override
|
||||||
|
public @NonNull Map<NamespacedKey, T> map() {
|
||||||
|
return registry.stream().collect(Collectors.toMap(Keyed::getKey, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable T get(@NonNull NamespacedKey key) {
|
||||||
|
return registry.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull NamespacedKey keyOf(@NonNull T value) {
|
||||||
|
return value.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record CompoundRegistry<T>(Collection<KeyedRegistry<T>> registries) implements KeyedRegistry<T> {
|
||||||
|
@Override
|
||||||
|
public @NonNull Map<NamespacedKey, T> map() {
|
||||||
|
final KMap<NamespacedKey, T> m = new KMap<>();
|
||||||
|
for (final KeyedRegistry<T> registry : registries) {
|
||||||
|
m.put(registry.map());
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable T get(@NonNull NamespacedKey key) {
|
||||||
|
for (final KeyedRegistry<T> registry : registries) {
|
||||||
|
final T t = registry.get(key);
|
||||||
|
if (t != null) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable NamespacedKey keyOf(@NonNull T value) {
|
||||||
|
for (final KeyedRegistry<T> registry : registries) {
|
||||||
|
final NamespacedKey key = registry.keyOf(value);
|
||||||
|
if (key != null) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return registries.isEmpty() || registries.stream().allMatch(KeyedRegistry::isEmpty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.volmit.iris.util.data.registry;
|
||||||
|
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class RegistryTypeAdapter<T> extends TypeAdapter<T> {
|
||||||
|
private final KeyedRegistry<T> registry;
|
||||||
|
|
||||||
|
private RegistryTypeAdapter(KeyedRegistry<T> type) {
|
||||||
|
this.registry = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static <T> RegistryTypeAdapter<T> of(@NonNull Class<T> type) {
|
||||||
|
final var registry = RegistryUtil.lookup(type);
|
||||||
|
return registry.isEmpty() ? null : new RegistryTypeAdapter<>(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(JsonWriter out, T value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final var key = registry.keyOf(value);
|
||||||
|
if (key == null) out.nullValue();
|
||||||
|
else out.value(key.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T read(JsonReader in) throws IOException {
|
||||||
|
final NamespacedKey key = NamespacedKey.fromString(in.nextString());
|
||||||
|
return key == null ? null : registry.get(key);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,8 @@ package com.volmit.iris.util.data.registry;
|
|||||||
|
|
||||||
import com.volmit.iris.core.nms.container.Pair;
|
import com.volmit.iris.core.nms.container.Pair;
|
||||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Keyed;
|
import org.bukkit.Keyed;
|
||||||
@ -13,116 +15,78 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.volmit.iris.util.data.registry.KeyedRegistry.wrapped;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class RegistryUtil {
|
public class RegistryUtil {
|
||||||
private static final AtomicCache<RegistryLookup> registryLookup = new AtomicCache<>();
|
private static final AtomicCache<RegistryLookup> registryLookup = new AtomicCache<>();
|
||||||
private static final Map<Class<?>, Map<NamespacedKey, Keyed>> KEYED_REGISTRY = new HashMap<>();
|
private static final KMap<Class<?>, KeyedRegistry<Object>> CACHE = new KMap<>();
|
||||||
private static final Map<Class<?>, Map<NamespacedKey, Object>> ENUM_REGISTRY = new HashMap<>();
|
|
||||||
private static final Map<Class<?>, Registry<Keyed>> REGISTRY = new HashMap<>();
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static <T> T find(@NonNull Class<T> typeClass, @NonNull String... keys) {
|
public static <T> T find(@NonNull Class<T> typeClass, @NonNull String... keys) {
|
||||||
return find(typeClass, defaultLookup(), keys);
|
return find(typeClass, Arrays.stream(keys).map(NamespacedKey::minecraft).toArray(NamespacedKey[]::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static <T> T find(@NonNull Class<T> typeClass, @Nullable Lookup<T> lookup, @NonNull String... keys) {
|
|
||||||
return find(typeClass, lookup, Arrays.stream(keys).map(NamespacedKey::minecraft).toArray(NamespacedKey[]::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T find(@NonNull Class<T> typeClass, @NonNull NamespacedKey... keys) {
|
public static <T> T find(@NonNull Class<T> typeClass, @NonNull NamespacedKey... keys) {
|
||||||
return find(typeClass, defaultLookup(), keys);
|
return lookup(typeClass).find(keys).orElseThrow(() -> new IllegalArgumentException("No element found for keys: " + Arrays.toString(keys)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static <T> T find(@NonNull Class<T> typeClass, @Nullable Lookup<T> lookup, @NonNull NamespacedKey... keys) {
|
public static <T> KeyedRegistry<T> lookup(@NonNull Class<T> typeClass) {
|
||||||
if (keys.length == 0) throw new IllegalArgumentException("Need at least one key");
|
return (KeyedRegistry<T>) CACHE.computeIfAbsent(typeClass, $ -> {
|
||||||
Registry<Keyed> registry = null;
|
final var registries = new KList<KeyedRegistry<Object>>();
|
||||||
if (Keyed.class.isAssignableFrom(typeClass)) {
|
if (Keyed.class.isAssignableFrom(typeClass)) {
|
||||||
registry = getRegistry(typeClass.asSubclass(Keyed.class));
|
var bukkit = wrapped(getRegistry(typeClass.asSubclass(Keyed.class)));
|
||||||
}
|
if (bukkit == null) {
|
||||||
if (registry == null) {
|
bukkit = Arrays.stream(Registry.class.getDeclaredFields())
|
||||||
registry = REGISTRY.computeIfAbsent(typeClass, t -> Arrays.stream(Registry.class.getDeclaredFields())
|
.filter(field -> Modifier.isStatic(field.getModifiers()) && Modifier.isPublic(field.getModifiers()))
|
||||||
.filter(field -> Modifier.isStatic(field.getModifiers()) && Modifier.isPublic(field.getModifiers()))
|
.filter(field -> Registry.class.isAssignableFrom(field.getType()))
|
||||||
.filter(field -> Registry.class.isAssignableFrom(field.getType()))
|
.filter(field -> ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0].equals(typeClass))
|
||||||
.filter(field -> ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0].equals(t))
|
.map(field -> {
|
||||||
.map(field -> {
|
try {
|
||||||
try {
|
return (Registry<Keyed>) field.get(null);
|
||||||
return (Registry<Keyed>) field.get(null);
|
} catch (IllegalAccessException e) {
|
||||||
} catch (IllegalAccessException e) {
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
})
|
||||||
})
|
.filter(Objects::nonNull)
|
||||||
.filter(Objects::nonNull)
|
.findFirst()
|
||||||
.findFirst()
|
.map(KeyedRegistry::wrapped)
|
||||||
.orElse(null));
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (registry != null) {
|
registries.addNonNull((KeyedRegistry<Object>) (Object) bukkit);
|
||||||
for (NamespacedKey key : keys) {
|
|
||||||
Keyed value = registry.get(key);
|
|
||||||
if (value != null)
|
|
||||||
return (T) value;
|
|
||||||
}
|
}
|
||||||
}
|
registries.add(getKeyedValues(typeClass));
|
||||||
|
registries.add(getEnumValues(typeClass));
|
||||||
|
|
||||||
if (lookup != null)
|
return wrapped(registries);
|
||||||
return lookup.find(typeClass, keys);
|
});
|
||||||
throw new IllegalArgumentException("No element found for keys: " + Arrays.toString(keys));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
private static KeyedRegistry<Object> getKeyedValues(@NonNull Class<?> typeClass) {
|
||||||
public static <T> T findByField(@NonNull Class<T> typeClass, @NonNull NamespacedKey... keys) {
|
return wrapped(Arrays.stream(typeClass.getDeclaredFields())
|
||||||
var values = KEYED_REGISTRY.computeIfAbsent(typeClass, RegistryUtil::getKeyedValues);
|
|
||||||
for (NamespacedKey key : keys) {
|
|
||||||
var value = values.get(key);
|
|
||||||
if (value != null)
|
|
||||||
return (T) value;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("No element found for keys: " + Arrays.toString(keys));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static <T> T findByEnum(@NonNull Class<T> typeClass, @NonNull NamespacedKey... keys) {
|
|
||||||
var values = ENUM_REGISTRY.computeIfAbsent(typeClass, RegistryUtil::getEnumValues);
|
|
||||||
for (NamespacedKey key : keys) {
|
|
||||||
var value = values.get(key);
|
|
||||||
if (value != null)
|
|
||||||
return (T) value;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("No element found for keys: " + Arrays.toString(keys));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static <T> Lookup<T> defaultLookup() {
|
|
||||||
return Lookup.combine(RegistryUtil::findByField, RegistryUtil::findByEnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<NamespacedKey, Keyed> getKeyedValues(@NonNull Class<?> typeClass) {
|
|
||||||
return Arrays.stream(typeClass.getDeclaredFields())
|
|
||||||
.filter(field -> Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()))
|
.filter(field -> Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()))
|
||||||
.filter(field -> Keyed.class.isAssignableFrom(field.getType()))
|
.filter(field -> Keyed.class.isAssignableFrom(field.getType()))
|
||||||
.map(field -> {
|
.map(field -> {
|
||||||
try {
|
try {
|
||||||
return (Keyed) field.get(null);
|
final var value = (Keyed) field.get(null);
|
||||||
|
return new Pair<>(value.getKey(), value);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toMap(Keyed::getKey, Function.identity()));
|
.collect(Collectors.toMap(Pair::getA, Pair::getB)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<NamespacedKey, Object> getEnumValues(@NonNull Class<?> typeClass) {
|
private static KeyedRegistry<Object> getEnumValues(@NonNull Class<?> typeClass) {
|
||||||
return Arrays.stream(typeClass.getDeclaredFields())
|
return wrapped(Arrays.stream(typeClass.getDeclaredFields())
|
||||||
.filter(field -> Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()))
|
.filter(field -> Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()))
|
||||||
.filter(field -> typeClass.isAssignableFrom(field.getType()))
|
.filter(field -> typeClass.isAssignableFrom(field.getType()))
|
||||||
.map(field -> {
|
.map(field -> {
|
||||||
@ -133,28 +97,10 @@ public class RegistryUtil {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toMap(Pair::getA, Pair::getB));
|
.collect(Collectors.toMap(Pair::getA, Pair::getB)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface Lookup<T> {
|
|
||||||
@NonNull
|
|
||||||
T find(@NonNull Class<T> typeClass, @NonNull NamespacedKey... keys);
|
|
||||||
|
|
||||||
static <T> Lookup<T> combine(@NonNull Lookup<T>... lookups) {
|
|
||||||
if (lookups.length == 0) throw new IllegalArgumentException("Need at least one lookup");
|
|
||||||
return (typeClass, keys) -> {
|
|
||||||
for (Lookup<T> lookup : lookups) {
|
|
||||||
try {
|
|
||||||
return lookup.find(typeClass, keys);
|
|
||||||
} catch (IllegalArgumentException ignored) {}
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("No element found for keys: " + Arrays.toString(keys));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static <T extends Keyed> Registry<T> getRegistry(@NotNull Class<T> type) {
|
private static <T extends Keyed> Registry<T> getRegistry(@NotNull Class<T> type) {
|
||||||
RegistryLookup lookup = registryLookup.aquire(() -> {
|
RegistryLookup lookup = registryLookup.aquire(() -> {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package com.volmit.iris.util.function;
|
package com.volmit.iris.util.function;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
public interface NastyFunction<T, R> {
|
public interface NastyFunction<T, R> {
|
||||||
R run(T t);
|
R run(T t) throws Throwable;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,6 @@ import org.bukkit.Chunk;
|
|||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@ -58,16 +57,18 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class Mantle {
|
public class Mantle {
|
||||||
|
private static final int LOCK_SIZE = Short.MAX_VALUE;
|
||||||
|
|
||||||
private final File dataFolder;
|
private final File dataFolder;
|
||||||
@Getter
|
@Getter
|
||||||
private final int worldHeight;
|
private final int worldHeight;
|
||||||
private final Map<Long, Long> lastUse;
|
private final KMap<Long, Long> lastUse;
|
||||||
private final Map<Long, TectonicPlate> loadedRegions;
|
private final KMap<Long, TectonicPlate> loadedRegions;
|
||||||
private final HyperLock hyperLock;
|
private final HyperLock hyperLock;
|
||||||
private final AtomicBoolean closed;
|
private final AtomicBoolean closed;
|
||||||
private final MultiBurst ioBurst;
|
private final MultiBurst ioBurst;
|
||||||
private final AtomicBoolean ioTrim;
|
private final Semaphore ioTrim;
|
||||||
private final AtomicBoolean ioTectonicUnload;
|
private final Semaphore ioTectonicUnload;
|
||||||
private final AtomicDouble adjustedIdleDuration;
|
private final AtomicDouble adjustedIdleDuration;
|
||||||
private final KSet<Long> toUnload;
|
private final KSet<Long> toUnload;
|
||||||
|
|
||||||
@ -83,8 +84,8 @@ public class Mantle {
|
|||||||
this.closed = new AtomicBoolean(false);
|
this.closed = new AtomicBoolean(false);
|
||||||
this.dataFolder = dataFolder;
|
this.dataFolder = dataFolder;
|
||||||
this.worldHeight = worldHeight;
|
this.worldHeight = worldHeight;
|
||||||
this.ioTrim = new AtomicBoolean(false);
|
this.ioTrim = new Semaphore(LOCK_SIZE, true);
|
||||||
this.ioTectonicUnload = new AtomicBoolean(false);
|
this.ioTectonicUnload = new Semaphore(LOCK_SIZE, true);
|
||||||
loadedRegions = new KMap<>();
|
loadedRegions = new KMap<>();
|
||||||
lastUse = new KMap<>();
|
lastUse = new KMap<>();
|
||||||
ioBurst = MultiBurst.burst;
|
ioBurst = MultiBurst.burst;
|
||||||
@ -428,7 +429,7 @@ public class Mantle {
|
|||||||
}
|
}
|
||||||
adjustedIdleDuration.set(idleDuration);
|
adjustedIdleDuration.set(idleDuration);
|
||||||
|
|
||||||
ioTrim.set(true);
|
ioTrim.acquireUninterruptibly(LOCK_SIZE);
|
||||||
try {
|
try {
|
||||||
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(idleDuration, 0));
|
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(idleDuration, 0));
|
||||||
|
|
||||||
@ -446,7 +447,7 @@ public class Mantle {
|
|||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
} finally {
|
} finally {
|
||||||
ioTrim.set(false);
|
ioTrim.release(LOCK_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +460,7 @@ public class Mantle {
|
|||||||
BurstExecutor burst = ioBurst.burst(toUnload.size());
|
BurstExecutor burst = ioBurst.burst(toUnload.size());
|
||||||
burst.setMulticore(toUnload.size() > tectonicLimit);
|
burst.setMulticore(toUnload.size() > tectonicLimit);
|
||||||
|
|
||||||
ioTectonicUnload.set(true);
|
ioTectonicUnload.acquireUninterruptibly(LOCK_SIZE);
|
||||||
try {
|
try {
|
||||||
for (long id : toUnload) {
|
for (long id : toUnload) {
|
||||||
double unloadTime = M.ms() - adjustedIdleDuration.get();
|
double unloadTime = M.ms() - adjustedIdleDuration.get();
|
||||||
@ -478,15 +479,14 @@ public class Mantle {
|
|||||||
|
|
||||||
if (m.inUse()) {
|
if (m.inUse()) {
|
||||||
Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ());
|
Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ());
|
||||||
lastUse.put(id, M.ms());
|
use(id);
|
||||||
toUnload.remove(id);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m.write(fileForRegion(dataFolder, id, false));
|
m.write(fileForRegion(dataFolder, id, false));
|
||||||
oldFileForRegion(dataFolder, id).delete();
|
oldFileForRegion(dataFolder, id).delete();
|
||||||
loadedRegions.remove(id);
|
loadedRegions.remove(id, m);
|
||||||
lastUse.remove(id);
|
lastUse.remove(id);
|
||||||
toUnload.remove(id);
|
toUnload.remove(id);
|
||||||
i.incrementAndGet();
|
i.incrementAndGet();
|
||||||
@ -502,7 +502,7 @@ public class Mantle {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
burst.complete();
|
burst.complete();
|
||||||
} finally {
|
} finally {
|
||||||
ioTectonicUnload.set(false);
|
ioTectonicUnload.release(LOCK_SIZE);
|
||||||
}
|
}
|
||||||
return i.get();
|
return i.get();
|
||||||
}
|
}
|
||||||
@ -518,32 +518,39 @@ public class Mantle {
|
|||||||
*/
|
*/
|
||||||
@RegionCoordinates
|
@RegionCoordinates
|
||||||
private TectonicPlate get(int x, int z) {
|
private TectonicPlate get(int x, int z) {
|
||||||
if (ioTrim.get() || ioTectonicUnload.get()) {
|
boolean trim = ioTrim.tryAcquire();
|
||||||
|
boolean unload = ioTectonicUnload.tryAcquire();
|
||||||
|
try {
|
||||||
|
if (!trim || !unload) {
|
||||||
|
try {
|
||||||
|
return getSafe(x, z).get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Long key = key(x, z);
|
||||||
|
TectonicPlate p = loadedRegions.get(key);
|
||||||
|
|
||||||
|
if (p != null && !p.isClosed()) {
|
||||||
|
use(key);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return getSafe(x, z).get();
|
return getSafe(x, z).get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread intterruption (hotload?)");
|
||||||
|
Iris.reportError(e);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
e.printStackTrace();
|
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread execution exception (engine close?)");
|
||||||
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
|
if (trim) ioTrim.release();
|
||||||
Long key = key(x, z);
|
if (unload) ioTectonicUnload.release();
|
||||||
TectonicPlate p = loadedRegions.get(key);
|
|
||||||
|
|
||||||
if (p != null) {
|
|
||||||
use(key);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return getSafe(x, z).get();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread intterruption (hotload?)");
|
|
||||||
Iris.reportError(e);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread execution exception (engine close?)");
|
|
||||||
Iris.reportError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Iris.warn("Retrying to get " + x + " " + z + " Mantle Region");
|
Iris.warn("Retrying to get " + x + " " + z + " Mantle Region");
|
||||||
@ -560,19 +567,12 @@ public class Mantle {
|
|||||||
*/
|
*/
|
||||||
@RegionCoordinates
|
@RegionCoordinates
|
||||||
private Future<TectonicPlate> getSafe(int x, int z) {
|
private Future<TectonicPlate> getSafe(int x, int z) {
|
||||||
Long k = key(x, z);
|
|
||||||
TectonicPlate p = loadedRegions.get(k);
|
|
||||||
|
|
||||||
if (p != null) {
|
|
||||||
use(k);
|
|
||||||
return CompletableFuture.completedFuture(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ioBurst.completeValue(() -> hyperLock.withResult(x, z, () -> {
|
return ioBurst.completeValue(() -> hyperLock.withResult(x, z, () -> {
|
||||||
|
Long k = key(x, z);
|
||||||
use(k);
|
use(k);
|
||||||
TectonicPlate region = loadedRegions.get(k);
|
TectonicPlate region = loadedRegions.get(k);
|
||||||
|
|
||||||
if (region != null) {
|
if (region != null && !region.isClosed()) {
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,12 +600,14 @@ public class Mantle {
|
|||||||
Iris.debug("Created new Tectonic Plate (Due to Load Failure) " + C.DARK_GREEN + x + " " + z);
|
Iris.debug("Created new Tectonic Plate (Due to Load Failure) " + C.DARK_GREEN + x + " " + z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use(k);
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
region = new TectonicPlate(worldHeight, x, z);
|
region = new TectonicPlate(worldHeight, x, z);
|
||||||
loadedRegions.put(k, region);
|
loadedRegions.put(k, region);
|
||||||
Iris.debug("Created new Tectonic Plate " + C.DARK_GREEN + x + " " + z);
|
Iris.debug("Created new Tectonic Plate " + C.DARK_GREEN + x + " " + z);
|
||||||
|
use(k);
|
||||||
return region;
|
return region;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import java.nio.channels.FileChannel;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,6 +53,7 @@ public class TectonicPlate {
|
|||||||
|
|
||||||
private final int sectionHeight;
|
private final int sectionHeight;
|
||||||
private final AtomicReferenceArray<MantleChunk> chunks;
|
private final AtomicReferenceArray<MantleChunk> chunks;
|
||||||
|
private final AtomicBoolean closed;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final int x;
|
private final int x;
|
||||||
@ -67,6 +69,7 @@ public class TectonicPlate {
|
|||||||
public TectonicPlate(int worldHeight, int x, int z) {
|
public TectonicPlate(int worldHeight, int x, int z) {
|
||||||
this.sectionHeight = worldHeight >> 4;
|
this.sectionHeight = worldHeight >> 4;
|
||||||
this.chunks = new AtomicReferenceArray<>(1024);
|
this.chunks = new AtomicReferenceArray<>(1024);
|
||||||
|
this.closed = new AtomicBoolean(false);
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
@ -143,6 +146,7 @@ public class TectonicPlate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws InterruptedException {
|
public void close() throws InterruptedException {
|
||||||
|
closed.set(true);
|
||||||
for (int i = 0; i < chunks.length(); i++) {
|
for (int i = 0; i < chunks.length(); i++) {
|
||||||
MantleChunk chunk = chunks.get(i);
|
MantleChunk chunk = chunks.get(i);
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
@ -151,6 +155,10 @@ public class TectonicPlate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
return closed.get();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a chunk exists in this plate or not (same as get(x, z) != null)
|
* Check if a chunk exists in this plate or not (same as get(x, z) != null)
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.volmit.iris.util.matter.slices;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.data.palette.Palette;
|
||||||
|
import com.volmit.iris.util.matter.Sliced;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Sliced
|
||||||
|
public class JigsawStructureMatter extends RawMatter<JigsawStructureContainer> {
|
||||||
|
public JigsawStructureMatter() {
|
||||||
|
this(1,1,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JigsawStructureMatter(int width, int height, int depth) {
|
||||||
|
super(width, height, depth, JigsawStructureContainer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Palette<JigsawStructureContainer> getGlobalPalette() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeNode(JigsawStructureContainer b, DataOutputStream dos) throws IOException {
|
||||||
|
dos.writeUTF(b.getLoadKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JigsawStructureContainer readNode(DataInputStream din) throws IOException {
|
||||||
|
return new JigsawStructureContainer(din.readUTF());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.volmit.iris.util.matter.slices.container;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||||
|
|
||||||
|
public class JigsawStructureContainer extends RegistrantContainer<IrisJigsawStructure> {
|
||||||
|
public JigsawStructureContainer(String loadKey) {
|
||||||
|
super(IrisJigsawStructure.class, loadKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JigsawStructureContainer toContainer(IrisJigsawStructure structure) {
|
||||||
|
return new JigsawStructureContainer(structure.getLoadKey());
|
||||||
|
}
|
||||||
|
}
|
@ -23,9 +23,11 @@ import org.bstats.charts.SimplePie;
|
|||||||
import org.bstats.charts.SingleLineChart;
|
import org.bstats.charts.SingleLineChart;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import oshi.SystemInfo;
|
import oshi.SystemInfo;
|
||||||
|
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -45,6 +47,9 @@ public class Bindings {
|
|||||||
if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) return;
|
if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) return;
|
||||||
Iris.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings.");
|
Iris.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings.");
|
||||||
Iris.info("Your server ID is: " + ServerID.ID);
|
Iris.info("Your server ID is: " + ServerID.ID);
|
||||||
|
var resource = Iris.instance.getResource("plugin.yml");
|
||||||
|
YamlConfiguration desc = resource != null ? YamlConfiguration.loadConfiguration(new InputStreamReader(resource)) : new YamlConfiguration();
|
||||||
|
|
||||||
Sentry.init(options -> {
|
Sentry.init(options -> {
|
||||||
options.setDsn("https://b16ecc222e9c1e0c48faecacb906fd89@o4509451052646400.ingest.de.sentry.io/4509452722765904");
|
options.setDsn("https://b16ecc222e9c1e0c48faecacb906fd89@o4509451052646400.ingest.de.sentry.io/4509452722765904");
|
||||||
if (settings.debug) {
|
if (settings.debug) {
|
||||||
@ -55,6 +60,7 @@ public class Bindings {
|
|||||||
options.setAttachServerName(false);
|
options.setAttachServerName(false);
|
||||||
options.setEnableUncaughtExceptionHandler(false);
|
options.setEnableUncaughtExceptionHandler(false);
|
||||||
options.setRelease(Iris.instance.getDescription().getVersion());
|
options.setRelease(Iris.instance.getDescription().getVersion());
|
||||||
|
options.setEnvironment(desc.getString("environment", "production"));
|
||||||
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());
|
||||||
@ -71,6 +77,7 @@ public class Bindings {
|
|||||||
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());
|
||||||
|
scope.setTag("iris.commit", desc.getString("commit", "unknown"));
|
||||||
});
|
});
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(Sentry::close));
|
Runtime.getRuntime().addShutdownHook(new Thread(Sentry::close));
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.volmit.iris.util.misc;
|
package com.volmit.iris.util.misc;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -22,12 +25,13 @@ public class ServerProperties {
|
|||||||
String bukkitYml = "bukkit.yml";
|
String bukkitYml = "bukkit.yml";
|
||||||
String levelName = null;
|
String levelName = null;
|
||||||
|
|
||||||
for (int i = 0; i < args.length - 1; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
switch (args[i]) {
|
String arg = args[i];
|
||||||
case "-c", "--config" -> propertiesPath = args[i + 1];
|
String next = i < args.length - 1 ? args[i + 1] : null;
|
||||||
case "-b", "--bukkit-settings" -> bukkitYml = args[i + 1];
|
|
||||||
case "-w", "--level-name", "--world" -> levelName = args[i + 1];
|
propertiesPath = parse(arg, next, propertiesPath, "-c", "--config");
|
||||||
}
|
bukkitYml = parse(arg, next, bukkitYml, "-b", "--bukkit-settings");
|
||||||
|
levelName = parse(arg, next, levelName, "-w", "--level-name", "--world");
|
||||||
}
|
}
|
||||||
|
|
||||||
SERVER_PROPERTIES = new File(propertiesPath);
|
SERVER_PROPERTIES = new File(propertiesPath);
|
||||||
@ -41,4 +45,19 @@ public class ServerProperties {
|
|||||||
if (levelName != null) LEVEL_NAME = levelName;
|
if (levelName != null) LEVEL_NAME = levelName;
|
||||||
else LEVEL_NAME = DATA.getProperty("level-name", "world");
|
else LEVEL_NAME = DATA.getProperty("level-name", "world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String parse(
|
||||||
|
@NotNull String current,
|
||||||
|
@Nullable String next,
|
||||||
|
String fallback,
|
||||||
|
@NotNull String @NotNull ... keys
|
||||||
|
) {
|
||||||
|
for (String k : keys) {
|
||||||
|
if (current.equals(k) && next != null)
|
||||||
|
return next;
|
||||||
|
if (current.startsWith(k + "=") && current.length() > k.length() + 1)
|
||||||
|
return current.substring(k.length() + 1);
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +1,67 @@
|
|||||||
package com.volmit.iris.util.misc;
|
package com.volmit.iris.util.misc;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
import io.github.slimjar.app.builder.ApplicationBuilder;
|
import io.github.slimjar.app.builder.ApplicationBuilder;
|
||||||
|
import io.github.slimjar.app.builder.SpigotApplicationBuilder;
|
||||||
|
import io.github.slimjar.injector.loader.factory.InjectableFactory;
|
||||||
import io.github.slimjar.logging.ProcessLogger;
|
import io.github.slimjar.logging.ProcessLogger;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import static com.volmit.iris.Iris.instance;
|
||||||
|
|
||||||
public class SlimJar {
|
public class SlimJar {
|
||||||
private static final Logger LOGGER = Logger.getLogger("Iris");
|
private static final boolean DEBUG = Boolean.getBoolean("iris.debug-slimjar");
|
||||||
|
private static final boolean DISABLE_REMAPPER = Boolean.getBoolean("iris.disable-remapper");
|
||||||
|
|
||||||
private static final ReentrantLock lock = new ReentrantLock();
|
private static final ReentrantLock lock = new ReentrantLock();
|
||||||
private static final AtomicBoolean loaded = new AtomicBoolean();
|
private static final AtomicBoolean loaded = new AtomicBoolean();
|
||||||
|
|
||||||
public static void debug(boolean debug) {
|
public static void load() {
|
||||||
LOGGER.setLevel(debug ? Level.FINE : Level.INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void load(@Nullable File localRepository) {
|
|
||||||
if (loaded.get()) return;
|
if (loaded.get()) return;
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (loaded.getAndSet(true)) return;
|
if (loaded.getAndSet(true)) return;
|
||||||
if (localRepository == null) {
|
final var downloadPath = instance.getDataFolder("cache", "libraries").toPath();
|
||||||
localRepository = new File(".iris/libraries");
|
final var logger = instance.getLogger();
|
||||||
|
|
||||||
|
logger.info("Loading libraries...");
|
||||||
|
try {
|
||||||
|
new SpigotApplicationBuilder(instance)
|
||||||
|
.downloadDirectoryPath(downloadPath)
|
||||||
|
.debug(DEBUG)
|
||||||
|
.remap(!DISABLE_REMAPPER)
|
||||||
|
.build();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.warn("Failed to inject the library loader, falling back to application builder");
|
||||||
|
ApplicationBuilder.appending(instance.getName())
|
||||||
|
.injectableFactory(InjectableFactory.selecting(InjectableFactory.ERROR, InjectableFactory.INJECTABLE, InjectableFactory.WRAPPED, InjectableFactory.UNSAFE))
|
||||||
|
.downloadDirectoryPath(downloadPath)
|
||||||
|
.logger(new ProcessLogger() {
|
||||||
|
@Override
|
||||||
|
public void info(@NotNull String message, @Nullable Object... args) {
|
||||||
|
if (!DEBUG) return;
|
||||||
|
instance.getLogger().info(message.formatted(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(@NotNull String message, @Nullable Object... args) {
|
||||||
|
instance.getLogger().severe(message.formatted(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debug(@NotNull String message, @Nullable Object... args) {
|
||||||
|
if (!DEBUG) return;
|
||||||
|
instance.getLogger().info(message.formatted(args));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
logger.info("Libraries loaded successfully!");
|
||||||
LOGGER.info("Loading libraries...");
|
|
||||||
ApplicationBuilder.appending("Iris")
|
|
||||||
.downloadDirectoryPath(localRepository.toPath())
|
|
||||||
.logger(new ProcessLogger() {
|
|
||||||
@Override
|
|
||||||
public void info(@NotNull String message, @Nullable Object... args) {
|
|
||||||
LOGGER.fine(message.formatted(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void error(@NotNull String message, @Nullable Object... args) {
|
|
||||||
LOGGER.severe(message.formatted(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void debug(@NotNull String message, @Nullable Object... args) {
|
|
||||||
LOGGER.fine(message.formatted(args));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
LOGGER.info("Libraries loaded successfully!");
|
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.volmit.iris.util.reflect;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.volmit.iris.util.data.registry.RegistryTypeAdapter;
|
||||||
|
import com.volmit.iris.util.data.registry.RegistryUtil;
|
||||||
|
import org.bukkit.Keyed;
|
||||||
|
|
||||||
|
public class KeyedType {
|
||||||
|
private static final boolean KEYED_ENABLED = Boolean.getBoolean("iris.keyed-types");
|
||||||
|
private static final boolean KEYED_LENIENT = Boolean.getBoolean("iris.keyed-lenient");
|
||||||
|
|
||||||
|
public static String[] values(Class<?> type) {
|
||||||
|
if (!isKeyed(type)) return new String[0];
|
||||||
|
if (!KEYED_ENABLED) return OldEnum.values(type);
|
||||||
|
return RegistryUtil.lookup(type)
|
||||||
|
.map()
|
||||||
|
.keySet()
|
||||||
|
.stream()
|
||||||
|
.map(Object::toString)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isKeyed(Class<?> type) {
|
||||||
|
if (KEYED_ENABLED) {
|
||||||
|
if (KEYED_LENIENT) return !RegistryUtil.lookup(type).isEmpty();
|
||||||
|
else return Keyed.class.isAssignableFrom(type);
|
||||||
|
} else return OldEnum.isOldEnum(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> TypeAdapter<T> createTypeAdapter(Gson gson, TypeToken<T> type) {
|
||||||
|
if (!isKeyed(type.getRawType())) return null;
|
||||||
|
return (TypeAdapter<T>) (KEYED_ENABLED ? RegistryTypeAdapter.of(type.getRawType()) : OldEnum.create(type.getRawType()));
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,22 @@
|
|||||||
package com.volmit.iris.util.reflect;
|
package com.volmit.iris.util.reflect;
|
||||||
|
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Deprecated(since = "3.7.1")
|
||||||
public class OldEnum {
|
public class OldEnum {
|
||||||
|
|
||||||
private static final Class<?> oldEnum;
|
private static final Class<?> oldEnum;
|
||||||
private static final Method name;
|
private static final MethodHandle name;
|
||||||
|
|
||||||
public static boolean exists() {
|
public static boolean exists() {
|
||||||
return oldEnum != null;
|
return oldEnum != null;
|
||||||
@ -25,11 +27,16 @@ public class OldEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T valueOf(Class<? extends T> c, String name) {
|
public static <T> T valueOf(Class<? extends T> c, String name) {
|
||||||
try {
|
return valueOf(c, name, name.replace(".", "_"));
|
||||||
return (T) c.getDeclaredField(name).get(null);
|
}
|
||||||
} catch (Throwable e) {
|
|
||||||
return null;
|
public static <T> T valueOf(Class<? extends T> c, String... names) {
|
||||||
|
for (final String name : names) {
|
||||||
|
try {
|
||||||
|
return (T) c.getDeclaredField(name).get(null);
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String name(Object o) {
|
public static String name(Object o) {
|
||||||
@ -40,20 +47,20 @@ public class OldEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object[] values(Class<?> clazz) {
|
public static String[] values(Class<?> clazz) {
|
||||||
if (!isOldEnum(clazz)) return new Object[0];
|
if (!isOldEnum(clazz)) return new String[0];
|
||||||
return Arrays.stream(clazz.getDeclaredFields())
|
return Arrays.stream(clazz.getDeclaredFields())
|
||||||
.filter(f -> Modifier.isStatic(f.getModifiers()))
|
.filter(f -> Modifier.isStatic(f.getModifiers()))
|
||||||
.filter(f -> Modifier.isFinal(f.getModifiers()))
|
.filter(f -> Modifier.isFinal(f.getModifiers()))
|
||||||
.map(f -> {
|
.map(f -> {
|
||||||
try {
|
try {
|
||||||
return f.get(null);
|
return name(f.get(null));
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.toArray();
|
.toArray(String[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> TypeAdapter<T> create(Class<? extends T> type) {
|
public static <T> TypeAdapter<T> create(Class<? extends T> type) {
|
||||||
@ -76,10 +83,10 @@ public class OldEnum {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
Class<?> clazz = null;
|
Class<?> clazz = null;
|
||||||
Method method = null;
|
MethodHandle method = null;
|
||||||
try {
|
try {
|
||||||
clazz = Class.forName("org.bukkit.util.OldEnum");
|
clazz = Class.forName("org.bukkit.util.OldEnum");
|
||||||
method = clazz.getDeclaredMethod("name");
|
method = MethodHandles.lookup().findVirtual(clazz, "name", MethodType.methodType(String.class));
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {}
|
||||||
|
|
||||||
if (clazz == null || method == null) {
|
if (clazz == null || method == null) {
|
||||||
|
@ -5,6 +5,8 @@ load: STARTUP
|
|||||||
authors: [ cyberpwn, NextdoorPsycho, Vatuu ]
|
authors: [ cyberpwn, NextdoorPsycho, Vatuu ]
|
||||||
website: volmit.com
|
website: volmit.com
|
||||||
description: More than a Dimension!
|
description: More than a Dimension!
|
||||||
|
environment: '${environment}'
|
||||||
|
commit: '${commit}'
|
||||||
commands:
|
commands:
|
||||||
iris:
|
iris:
|
||||||
aliases: [ ir, irs ]
|
aliases: [ ir, irs ]
|
||||||
|
@ -5,17 +5,18 @@
|
|||||||
[versions]
|
[versions]
|
||||||
# Plugins
|
# Plugins
|
||||||
shadow = "9.0.0-rc1" # https://plugins.gradle.org/plugin/com.gradleup.shadow
|
shadow = "9.0.0-rc1" # https://plugins.gradle.org/plugin/com.gradleup.shadow
|
||||||
slimjar = "2.0.8" # https://plugins.gradle.org/plugin/de.crazydev22.slimjar
|
slimjar = "2.1.5" # https://plugins.gradle.org/plugin/de.crazydev22.slimjar
|
||||||
download = "5.6.0" # https://plugins.gradle.org/plugin/de.undercouch.download
|
download = "5.6.0" # https://plugins.gradle.org/plugin/de.undercouch.download
|
||||||
runPaper = "2.3.1" # https://plugins.gradle.org/plugin/xyz.jpenilla.run-paper
|
runPaper = "2.3.1" # https://plugins.gradle.org/plugin/xyz.jpenilla.run-paper
|
||||||
sentryPlugin = "5.8.0" # https://github.com/getsentry/sentry-android-gradle-plugin
|
sentryPlugin = "5.8.0" # https://github.com/getsentry/sentry-android-gradle-plugin
|
||||||
|
grgit = "5.3.2" # https://github.com/ajoberstar/grgit
|
||||||
|
|
||||||
# Core Libraries
|
# Core Libraries
|
||||||
lombok = "1.18.38"
|
lombok = "1.18.38"
|
||||||
spigot = "1.20.1-R0.1-SNAPSHOT" # https://hub.spigotmc.org/nexus/repository/snapshots/org/spigotmc/spigot-api/maven-metadata.xml
|
spigot = "1.20.1-R0.1-SNAPSHOT" # https://hub.spigotmc.org/nexus/repository/snapshots/org/spigotmc/spigot-api/maven-metadata.xml
|
||||||
log4j = "2.19.0" # https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-api
|
log4j = "2.19.0" # https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-api
|
||||||
adventure-api = "4.23.0" # https://github.com/KyoriPowered/adventure
|
adventure-api = "4.24.0" # https://github.com/KyoriPowered/adventure
|
||||||
adventure-platform = "4.4.0" # https://github.com/KyoriPowered/adventure-platform
|
adventure-platform = "4.4.1" # https://github.com/KyoriPowered/adventure-platform
|
||||||
|
|
||||||
annotations = "26.0.2" # https://central.sonatype.com/artifact/org.jetbrains/annotations
|
annotations = "26.0.2" # https://central.sonatype.com/artifact/org.jetbrains/annotations
|
||||||
paralithic = "0.8.1" # https://github.com/PolyhedralDev/Paralithic/
|
paralithic = "0.8.1" # https://github.com/PolyhedralDev/Paralithic/
|
||||||
@ -102,3 +103,4 @@ slimjar = { id = "de.crazydev22.slimjar", version.ref = "slimjar" }
|
|||||||
download = { id = "de.undercouch.download", version.ref = "download" }
|
download = { id = "de.undercouch.download", version.ref = "download" }
|
||||||
runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" }
|
runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" }
|
||||||
sentry = { id = "io.sentry.jvm.gradle", version.ref = "sentryPlugin" }
|
sentry = { id = "io.sentry.jvm.gradle", version.ref = "sentryPlugin" }
|
||||||
|
grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user