mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-08-16 08:15:50 +00:00
Merge branch 'refs/heads/dev' into feat/kts
# Conflicts: # core/build.gradle.kts # core/src/main/java/com/volmit/iris/Iris.java # core/src/main/java/com/volmit/iris/core/link/data/MythicMobsDataProvider.java # core/src/main/java/com/volmit/iris/util/misc/SlimJar.java # gradle/libs.versions.toml
This commit is contained in:
commit
12c2c71739
@ -37,7 +37,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "com.volmit"
|
||||
version = "3.6.11-1.20.1-1.21.5"
|
||||
version = "3.7.0-1.20.1-1.21.7"
|
||||
|
||||
apply<ApiGenerator>()
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import io.github.slimjar.func.slimjar
|
||||
import io.github.slimjar.resolver.data.Mirror
|
||||
import org.ajoberstar.grgit.Grgit
|
||||
import java.net.URI
|
||||
|
||||
/*
|
||||
@ -26,6 +27,7 @@ plugins {
|
||||
alias(libs.plugins.shadow)
|
||||
alias(libs.plugins.sentry)
|
||||
alias(libs.plugins.slimjar)
|
||||
alias(libs.plugins.grgit)
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.kotlin.lombok)
|
||||
}
|
||||
@ -154,6 +156,15 @@ tasks {
|
||||
"version" to rootProject.version,
|
||||
"apiVersion" to apiVersion,
|
||||
"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") {
|
||||
expand(inputs.properties)
|
||||
@ -164,6 +175,7 @@ tasks {
|
||||
mergeServiceFiles()
|
||||
//minimize()
|
||||
relocate("io.github.slimjar", "$lib.slimjar")
|
||||
exclude("modules/loader-agent.isolated-jar")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,10 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.IrisWorlds;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.link.IrisPapiExpansion;
|
||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||
import com.volmit.iris.core.link.MythicMobsLink;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
@ -62,15 +62,11 @@ import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||
import io.github.slimjar.app.builder.ApplicationBuilder;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.Command;
|
||||
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.event.*;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
@ -84,6 +80,7 @@ import java.io.*;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -97,7 +94,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
public static Iris instance;
|
||||
public static Bindings.Adventure audiences;
|
||||
public static MultiverseCoreLink linkMultiverseCore;
|
||||
public static MythicMobsLink linkMythicMobs;
|
||||
public static IrisCompat compat;
|
||||
public static FileWatcher configWatcher;
|
||||
private static VolmitSender sender;
|
||||
@ -439,11 +435,11 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
|
||||
public Iris() {
|
||||
instance = this;
|
||||
SlimJar.load(getDataFolder("cache", "libraries"));
|
||||
}
|
||||
|
||||
private void enable() {
|
||||
instance = this;
|
||||
services = new KMap<>();
|
||||
setupAudience();
|
||||
Bindings.setupSentry();
|
||||
@ -456,7 +452,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
getSender().setTag(getTag());
|
||||
IrisSafeguard.splash(true);
|
||||
linkMultiverseCore = new MultiverseCoreLink();
|
||||
linkMythicMobs = new MythicMobsLink();
|
||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||
services.values().forEach(IrisService::onEnable);
|
||||
services.values().forEach(this::registerListener);
|
||||
@ -472,48 +467,34 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
IrisSafeguard.splash(false);
|
||||
|
||||
autoStartStudio();
|
||||
checkForBukkitWorlds();
|
||||
checkForBukkitWorlds(s -> true);
|
||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
||||
});
|
||||
}
|
||||
|
||||
private void checkForBukkitWorlds() {
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
public void checkForBukkitWorlds(Predicate<String> filter) {
|
||||
try {
|
||||
fc.load(new File("bukkit.yml"));
|
||||
ConfigurationSection section = fc.getConfigurationSection("worlds");
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
IrisWorlds.readBukkitWorlds().forEach((s, generator) -> {
|
||||
try {
|
||||
if (Bukkit.getWorld(s) != null || !filter.test(s)) return;
|
||||
|
||||
for (String s : section.getKeys(false)) {
|
||||
ConfigurationSection entry = section.getConfigurationSection(s);
|
||||
if (!entry.contains("generator", true)) {
|
||||
continue;
|
||||
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
||||
var gen = getDefaultWorldGenerator(s, generator);
|
||||
var dim = loadDimension(s, generator);
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
reportError(e);
|
||||
|
@ -4,10 +4,14 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
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.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.misc.ServerProperties;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -25,6 +29,7 @@ public class IrisWorlds {
|
||||
|
||||
private IrisWorlds(KMap<String, String> worlds) {
|
||||
this.worlds = worlds;
|
||||
readBukkitWorlds().forEach(this::put0);
|
||||
save();
|
||||
}
|
||||
|
||||
@ -50,14 +55,33 @@ public class IrisWorlds {
|
||||
}
|
||||
|
||||
public void put(String name, String type) {
|
||||
String old = worlds.put(name, type);
|
||||
if (!type.equals(old))
|
||||
dirty = true;
|
||||
put0(name, type);
|
||||
save();
|
||||
}
|
||||
|
||||
public Stream<File> getFolders() {
|
||||
return worlds.keySet().stream().map(k -> new File(Bukkit.getWorldContainer(), k));
|
||||
private void put0(String name, String type) {
|
||||
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() {
|
||||
@ -76,4 +100,27 @@ public class IrisWorlds {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicIntegerArray;
|
||||
import java.util.stream.Stream;
|
||||
@ -140,6 +141,7 @@ public class ServerConfigurator {
|
||||
var loader = data.getDimensionLoader();
|
||||
return loader.loadAll(loader.getPossibleKeys())
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(ServerConfigurator::verifyDataPackInstalled)
|
||||
.toList()
|
||||
.contains(false);
|
||||
@ -235,14 +237,13 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
public static Stream<IrisData> allPacks() {
|
||||
return Stream.concat(listFiles(Iris.instance.getDataFolder("packs")),
|
||||
IrisWorlds.get().getFolders().map(w -> new File(w, "iris/pack")))
|
||||
return Stream.concat(listFiles(Iris.instance.getDataFolder("packs"))
|
||||
.filter(File::isDirectory)
|
||||
.filter( base -> {
|
||||
var content = new File(base, "dimensions").listFiles();
|
||||
return content != null && content.length > 0;
|
||||
})
|
||||
.map(IrisData::get);
|
||||
.map(IrisData::get), IrisWorlds.get().getPacks());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -280,6 +281,7 @@ public class ServerConfigurator {
|
||||
var loader = data.getDimensionLoader();
|
||||
return loader.loadAll(loader.getPossibleKeys())
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.peek(this::merge);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -46,18 +46,20 @@ import com.volmit.iris.util.interpolation.InterpolationMethod;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.parallel.SyncExecutor;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import com.volmit.iris.util.scheduling.jobs.ParallelQueueJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
@ -76,8 +78,7 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -91,18 +92,19 @@ public class CommandStudio implements DecreeExecutor {
|
||||
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
|
||||
}
|
||||
|
||||
//TODO fix pack trimming
|
||||
@Decree(description = "Download a project.", aliases = "dl")
|
||||
public void download(
|
||||
@Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project")
|
||||
String pack,
|
||||
@Param(name = "branch", description = "The branch to download from", defaultValue = "master")
|
||||
String branch,
|
||||
@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
boolean trim,
|
||||
//@Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false")
|
||||
//boolean trim,
|
||||
@Param(name = "overwrite", description = "Whether or not to overwrite the pack with the downloaded one", aliases = "force", defaultValue = "false")
|
||||
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)
|
||||
@ -161,70 +163,77 @@ public class CommandStudio implements DecreeExecutor {
|
||||
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
|
||||
int radius
|
||||
) {
|
||||
if (IrisToolbelt.isIrisWorld(player().getWorld())) {
|
||||
VolmitSender sender = sender();
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(player().getWorld());
|
||||
Engine engine = plat.getEngine();
|
||||
try {
|
||||
Chunk cx = player().getLocation().getChunk();
|
||||
KList<Runnable> js = new KList<>();
|
||||
BurstExecutor b = MultiBurst.burst.burst();
|
||||
b.setMulticore(false);
|
||||
int rad = engine.getMantle().getRadius();
|
||||
for (int i = -(radius + rad); i <= radius + rad; i++) {
|
||||
for (int j = -(radius + rad); j <= radius + rad; j++) {
|
||||
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
int finalJ = j;
|
||||
int finalI = i;
|
||||
b.queue(() -> plat.injectChunkReplacement(player().getWorld(), finalI + cx.getX(), finalJ + cx.getZ(), (f) -> {
|
||||
synchronized (js) {
|
||||
js.add(f);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
b.complete();
|
||||
sender().sendMessage(C.GREEN + "Regenerating " + Form.f(js.size()) + " Sections");
|
||||
QueueJob<Runnable> r = new QueueJob<>() {
|
||||
final KList<Future<?>> futures = new KList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
futures.add(J.sfut(runnable));
|
||||
|
||||
if (futures.size() > 64) {
|
||||
while (futures.isNotEmpty()) {
|
||||
try {
|
||||
futures.remove(0).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
};
|
||||
r.queue(js);
|
||||
r.execute(sender());
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Unable to parse view-distance");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
World world = player().getWorld();
|
||||
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||
sender().sendMessage(C.RED + "You must be in an Iris World to use regen!");
|
||||
}
|
||||
|
||||
VolmitSender sender = sender();
|
||||
var loc = player().getLocation().clone();
|
||||
|
||||
J.a(() -> {
|
||||
DecreeContext.touch(sender);
|
||||
PlatformChunkGenerator plat = IrisToolbelt.access(world);
|
||||
Engine engine = plat.getEngine();
|
||||
try (SyncExecutor executor = new SyncExecutor(20)) {
|
||||
int x = loc.getBlockX() >> 4;
|
||||
int z = loc.getBlockZ() >> 4;
|
||||
|
||||
int rad = engine.getMantle().getRadius();
|
||||
var mantle = engine.getMantle().getMantle();
|
||||
var chunkMap = new KMap<Position2, MantleChunk>();
|
||||
for (int i = -(radius + rad); i <= radius + rad; i++) {
|
||||
for (int j = -(radius + rad); j <= radius + rad; j++) {
|
||||
int xx = i + x, zz = j + z;
|
||||
if (Math.abs(i) <= radius && Math.abs(j) <= radius) {
|
||||
mantle.deleteChunk(xx, zz);
|
||||
continue;
|
||||
}
|
||||
chunkMap.put(new Position2(xx, zz), mantle.getChunk(xx, zz));
|
||||
mantle.deleteChunk(xx, zz);
|
||||
}
|
||||
}
|
||||
|
||||
ParallelQueueJob<Position2> job = new ParallelQueueJob<>() {
|
||||
@Override
|
||||
public void execute(Position2 p) {
|
||||
plat.injectChunkReplacement(world, p.getX(), p.getZ(), executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regenerating";
|
||||
}
|
||||
};
|
||||
for (int i = -radius; i <= radius; i++) {
|
||||
for (int j = -radius; j <= radius; j++) {
|
||||
job.queue(new Position2(i + x, j + z));
|
||||
}
|
||||
}
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
job.execute(sender(), latch::countDown);
|
||||
latch.await();
|
||||
|
||||
int sections = mantle.getWorldHeight() >> 4;
|
||||
chunkMap.forEach((pos, chunk) -> {
|
||||
var c = mantle.getChunk(pos.getX(), pos.getZ());
|
||||
for (MantleFlag flag : MantleFlag.values()) {
|
||||
c.flag(flag, chunk.isFlagged(flag));
|
||||
}
|
||||
c.clear();
|
||||
for (int y = 0; y < sections; y++) {
|
||||
var slice = chunk.get(y);
|
||||
if (slice == null) continue;
|
||||
var s = c.getOrCreate(y);
|
||||
slice.getSliceMap().forEach(s::putSlice);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
sender().sendMessage("Error while regenerating chunks");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Decree(description = "Convert objects in the \"convert\" folder")
|
||||
|
@ -1,24 +1,33 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.core.link.data.DataType;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ExternalDataProvider {
|
||||
public abstract class ExternalDataProvider implements Listener {
|
||||
|
||||
@NonNull
|
||||
private final String pluginId;
|
||||
@ -53,7 +62,9 @@ public abstract class ExternalDataProvider {
|
||||
* @throws MissingResourceException when the blockId is invalid
|
||||
*/
|
||||
@NotNull
|
||||
public abstract 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 {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExternalDataProvider#getItemStack(Identifier)
|
||||
@ -73,7 +84,9 @@ public abstract class ExternalDataProvider {
|
||||
* @throws MissingResourceException when the itemId is invalid
|
||||
*/
|
||||
@NotNull
|
||||
public abstract ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException;
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used for placing blocks that need to use the plugins api
|
||||
@ -85,9 +98,43 @@ public abstract class ExternalDataProvider {
|
||||
*/
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {}
|
||||
|
||||
public abstract @NotNull Identifier[] getBlockTypes();
|
||||
/**
|
||||
* Spawns a mob in the specified location using the given engine and entity identifier.
|
||||
*
|
||||
* @param location The location in the world where the mob should spawn. Must not be null.
|
||||
* @param entityId The identifier of the mob entity to spawn. Must not be null.
|
||||
* @return The spawned {@link Entity} if successful, or null if the mob could not be spawned.
|
||||
*/
|
||||
@Nullable
|
||||
public Entity spawnMob(@NotNull Location location, @NotNull Identifier entityId) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find Entity!", entityId.namespace(), entityId.key());
|
||||
}
|
||||
|
||||
public abstract @NotNull Identifier[] getItemTypes();
|
||||
public abstract @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType);
|
||||
|
||||
public abstract boolean isValidProvider(@NotNull Identifier id, boolean isItem);
|
||||
public abstract boolean isValidProvider(@NotNull Identifier id, DataType dataType);
|
||||
|
||||
protected static Pair<Float, BlockFace> parseYawAndFace(@NotNull Engine engine, @NotNull Block block, @NotNull KMap<@NotNull String, @NotNull String> state) {
|
||||
float yaw = 0;
|
||||
BlockFace face = BlockFace.NORTH;
|
||||
|
||||
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||
RNG rng = new RNG(seed);
|
||||
if ("true".equals(state.get("randomYaw"))) {
|
||||
yaw = rng.f(0, 360);
|
||||
} else if (state.containsKey("yaw")) {
|
||||
yaw = Float.parseFloat(state.get("yaw"));
|
||||
}
|
||||
if ("true".equals(state.get("randomFace"))) {
|
||||
BlockFace[] faces = BlockFace.values();
|
||||
face = faces[rng.i(0, faces.length - 1)];
|
||||
} else if (state.containsKey("face")) {
|
||||
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||
}
|
||||
if (face == BlockFace.SELF) {
|
||||
face = BlockFace.NORTH;
|
||||
}
|
||||
|
||||
return new Pair<>(yaw, face);
|
||||
}
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class ItemAdderDataProvider extends ExternalDataProvider {
|
||||
|
||||
private KList<String> itemNamespaces, blockNamespaces;
|
||||
|
||||
public ItemAdderDataProvider() {
|
||||
super("ItemsAdder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.itemNamespaces = new KList<>();
|
||||
this.blockNamespaces = new KList<>();
|
||||
|
||||
for (Identifier i : getItemTypes()) {
|
||||
itemNamespaces.addIfMissing(i.namespace());
|
||||
}
|
||||
for (Identifier i : getBlockTypes()) {
|
||||
blockNamespaces.addIfMissing(i.namespace());
|
||||
Iris.info("Found ItemAdder Block: " + i);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
return CustomBlock.getBaseBlockData(blockId.toString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
||||
if (stack == null) {
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
}
|
||||
return stack.getItemStack();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> keys = new KList<>();
|
||||
for (String s : CustomBlock.getNamespacedIdsInRegistry()) {
|
||||
keys.add(Identifier.fromString(s));
|
||||
}
|
||||
return keys.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> keys = new KList<>();
|
||||
for (String s : CustomStack.getNamespacedIdsInRegistry()) {
|
||||
keys.add(Identifier.fromString(s));
|
||||
}
|
||||
return keys.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public enum DataType implements BiPredicate<ExternalDataProvider, Identifier> {
|
||||
ITEM,
|
||||
BLOCK,
|
||||
ENTITY;
|
||||
|
||||
@Override
|
||||
public boolean test(ExternalDataProvider dataProvider, Identifier identifier) {
|
||||
if (!dataProvider.isValidProvider(identifier, this)) return false;
|
||||
try {
|
||||
switch (this) {
|
||||
case ITEM -> dataProvider.getItemStack(identifier);
|
||||
case BLOCK -> dataProvider.getBlockData(identifier);
|
||||
case ENTITY -> {}
|
||||
}
|
||||
return true;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Predicate<Identifier> asPredicate(ExternalDataProvider dataProvider) {
|
||||
return i -> test(dataProvider, i);
|
||||
}
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
package com.volmit.iris.core.link;
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import com.willfp.ecoitems.items.EcoItem;
|
||||
import com.willfp.ecoitems.items.EcoItems;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class EcoItemsDataProvider extends ExternalDataProvider {
|
||||
@ -34,12 +36,6 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
@ -48,30 +44,18 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
|
||||
return itemStack.get(item).clone();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (EcoItem item : EcoItems.INSTANCE.values()) {
|
||||
try {
|
||||
Identifier key = Identifier.fromNamespacedKey(id.get(item));
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType != DataType.ITEM) return List.of();
|
||||
return EcoItems.INSTANCE.values()
|
||||
.stream()
|
||||
.map(x -> Identifier.fromNamespacedKey(id.get(x)))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
return id.namespace().equalsIgnoreCase("ecoitems") && dataType == DataType.ITEM;
|
||||
}
|
||||
}
|
@ -1,13 +1,15 @@
|
||||
package com.volmit.iris.core.link;
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.ssomar.score.api.executableitems.ExecutableItemsAPI;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -21,12 +23,6 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
||||
Iris.info("Setting up ExecutableItems Link...");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
@ -35,30 +31,19 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
|
||||
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return new Identifier[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : ExecutableItemsAPI.getExecutableItemsManager().getExecutableItemIdsList()) {
|
||||
try {
|
||||
Identifier key = new Identifier("executable_items", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType != DataType.ITEM) return List.of();
|
||||
return ExecutableItemsAPI.getExecutableItemsManager()
|
||||
.getExecutableItemIdsList()
|
||||
.stream()
|
||||
.map(name -> new Identifier("executable_items", name))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
||||
return key.namespace().equalsIgnoreCase("executable_items") && isItem;
|
||||
public boolean isValidProvider(@NotNull Identifier key, DataType dataType) {
|
||||
return key.namespace().equalsIgnoreCase("executable_items") && dataType == DataType.ITEM;
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
package com.volmit.iris.core.link;
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
@ -18,6 +19,8 @@ import org.bukkit.block.data.type.Leaves;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.function.Supplier;
|
||||
@ -89,41 +92,20 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : blockDataMap.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (String name : itemDataField.keySet()) {
|
||||
try {
|
||||
Identifier key = new Identifier("hmcleaves", name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return List.of();
|
||||
return (dataType == DataType.BLOCK ? blockDataMap.keySet() : itemDataField.keySet())
|
||||
.stream()
|
||||
.map(x -> new Identifier("hmcleaves", x))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return false;
|
||||
return (dataType == DataType.ITEM ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
|
||||
}
|
||||
|
||||
private <C, T> Map<String, T> getMap(C config, String name) {
|
@ -0,0 +1,89 @@
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class ItemAdderDataProvider extends ExternalDataProvider {
|
||||
|
||||
private KList<String> itemNamespaces, blockNamespaces;
|
||||
|
||||
public ItemAdderDataProvider() {
|
||||
super("ItemsAdder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.itemNamespaces = new KList<>();
|
||||
this.blockNamespaces = new KList<>();
|
||||
|
||||
for (Identifier i : getTypes(DataType.ITEM)) {
|
||||
itemNamespaces.addIfMissing(i.namespace());
|
||||
}
|
||||
for (Identifier i : getTypes(DataType.BLOCK)) {
|
||||
blockNamespaces.addIfMissing(i.namespace());
|
||||
Iris.info("Found ItemAdder Block: " + i);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
|
||||
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
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
|
||||
CustomStack stack = CustomStack.getInstance(itemId.toString());
|
||||
if (stack == null) {
|
||||
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
|
||||
}
|
||||
return stack.getItemStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||
CustomBlock.place(blockId.toString(), block.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
return switch (dataType) {
|
||||
case ENTITY -> List.of();
|
||||
case ITEM -> CustomStack.getNamespacedIdsInRegistry()
|
||||
.stream()
|
||||
.map(Identifier::fromString)
|
||||
.toList();
|
||||
case BLOCK -> CustomBlock.getNamespacedIdsInRegistry()
|
||||
.stream()
|
||||
.map(Identifier::fromString)
|
||||
.toList();
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return false;
|
||||
return dataType == DataType.ITEM ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.volmit.iris.core.link;
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
@ -14,6 +16,8 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
|
||||
public class KGeneratorsDataProvider extends ExternalDataProvider {
|
||||
@ -54,35 +58,17 @@ public class KGeneratorsDataProvider extends ExternalDataProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier[] getBlockTypes() {
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return List.of();
|
||||
return Main.getGenerators().getAll().stream()
|
||||
.map(gen -> new Identifier("kgenerators", gen.getId()))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getBlockData(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identifier[] getItemTypes() {
|
||||
return Main.getGenerators().getAll().stream()
|
||||
.map(gen -> new Identifier("kgenerators", gen.getId()))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getItemStack(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return false;
|
||||
return "kgenerators".equalsIgnoreCase(id.namespace());
|
||||
}
|
||||
}
|
@ -1,21 +1,24 @@
|
||||
package com.volmit.iris.core.link;
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.block.CustomBlock;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||
|
||||
@ -85,52 +88,35 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
|
||||
return item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (Integer id : api().getCustomBlocks().getBlockIds()) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems", String.valueOf(id));
|
||||
if (getBlockData(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
return switch (dataType) {
|
||||
case ENTITY -> List.of();
|
||||
case BLOCK -> api().getCustomBlocks().getBlockIds().stream().map(id -> new Identifier("mmoitems", String.valueOf(id)))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
case ITEM -> {
|
||||
Supplier<Collection<Identifier>> supplier = () -> api().getTypes()
|
||||
.getAll()
|
||||
.stream()
|
||||
.flatMap(type -> api()
|
||||
.getTemplates()
|
||||
.getTemplateNames(type)
|
||||
.stream()
|
||||
.map(name -> new Identifier("mmoitems_" + type.getId(), name)))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
Runnable run = () -> {
|
||||
for (Type type : api().getTypes().getAll()) {
|
||||
for (String name : api().getTemplates().getTemplateNames(type)) {
|
||||
try {
|
||||
Identifier key = new Identifier("mmoitems_" + type.getId(), name);
|
||||
if (getItemStack(key) != null)
|
||||
names.add(key);
|
||||
} catch (MissingResourceException ignored) {
|
||||
}
|
||||
}
|
||||
if (Bukkit.isPrimaryThread()) yield supplier.get();
|
||||
else yield J.sfut(supplier).join();
|
||||
}
|
||||
};
|
||||
if (Bukkit.isPrimaryThread()) run.run();
|
||||
else {
|
||||
try {
|
||||
J.sfut(run).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
Iris.error("Failed getting MMOItems item types!");
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return false;
|
||||
return dataType == DataType.ITEM ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
|
||||
}
|
||||
|
||||
private MMOItems api() {
|
@ -16,19 +16,18 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
|
||||
import io.lumine.mythiccrucible.MythicCrucible;
|
||||
@ -37,11 +36,11 @@ import io.lumine.mythiccrucible.items.ItemManager;
|
||||
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
|
||||
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -88,69 +87,27 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
||||
.generateItemStack(1));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||
if (item.getBlockData() == null) continue;
|
||||
try {
|
||||
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||
if (getBlockData(key) != null) {
|
||||
Iris.info("getBlockTypes: Block loaded '" + item.getInternalName() + "'");
|
||||
names.add(key);
|
||||
}
|
||||
} catch (MissingResourceException ignored) {}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
for (CrucibleItem item : this.itemManager.getItems()) {
|
||||
try {
|
||||
Identifier key = new Identifier("crucible", item.getInternalName());
|
||||
if (getItemStack(key) != null) {
|
||||
Iris.info("getItemTypes: Item loaded '" + item.getInternalName() + "'");
|
||||
names.add(key);
|
||||
}
|
||||
} catch (MissingResourceException ignored) {}
|
||||
}
|
||||
return names.toArray(new Identifier[0]);
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
return itemManager.getItems()
|
||||
.stream()
|
||||
.map(i -> new Identifier("crucible", i.getInternalName()))
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
var parsedState = ExternalDataSVC.parseState(blockId);
|
||||
var state = parsedState.getB();
|
||||
blockId = parsedState.getA();
|
||||
|
||||
Optional<CrucibleItem> item = itemManager.getItem(blockId.key());
|
||||
if (item.isEmpty()) return;
|
||||
FurnitureItemContext furniture = item.get().getFurnitureData();
|
||||
if (furniture == null) return;
|
||||
|
||||
float yaw = 0;
|
||||
BlockFace face = BlockFace.NORTH;
|
||||
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||
RNG rng = new RNG(seed);
|
||||
if ("true".equals(state.get("randomYaw"))) {
|
||||
yaw = rng.f(0, 360);
|
||||
} else if (state.containsKey("yaw")) {
|
||||
yaw = Float.parseFloat(state.get("yaw"));
|
||||
}
|
||||
if ("true".equals(state.get("randomFace"))) {
|
||||
BlockFace[] faces = BlockFace.values();
|
||||
face = faces[rng.i(0, faces.length - 1)];
|
||||
} else if (state.containsKey("face")) {
|
||||
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||
}
|
||||
if (face == BlockFace.SELF) {
|
||||
face = BlockFace.NORTH;
|
||||
}
|
||||
|
||||
var pair = parseYawAndFace(engine, block, state);
|
||||
BiomeColor type = null;
|
||||
Chroma color = null;
|
||||
try {
|
||||
@ -161,11 +118,12 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
|
||||
if (biomeColor == null) return;
|
||||
color = Chroma.of(biomeColor.getRGB());
|
||||
}
|
||||
furniture.place(block, face, yaw, color);
|
||||
furniture.place(block, pair.getB(), pair.getA(), color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
|
||||
public boolean isValidProvider(@NotNull Identifier key, DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return false;
|
||||
return key.namespace().equalsIgnoreCase("crucible");
|
||||
}
|
||||
}
|
@ -1,25 +1,7 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
package com.volmit.iris.core.link;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import io.lumine.mythic.api.adapters.AbstractLocation;
|
||||
import io.lumine.mythic.api.config.MythicLineConfig;
|
||||
@ -30,60 +12,60 @@ import io.lumine.mythic.bukkit.events.MythicConditionLoadEvent;
|
||||
import io.lumine.mythic.core.skills.SkillCondition;
|
||||
import io.lumine.mythic.core.utils.annotations.MythicCondition;
|
||||
import io.lumine.mythic.core.utils.annotations.MythicField;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class MythicMobsLink {
|
||||
|
||||
public MythicMobsLink() {
|
||||
if (getPlugin() == null) return;
|
||||
Iris.instance.registerListener(new ConditionListener());
|
||||
public class MythicMobsDataProvider extends ExternalDataProvider {
|
||||
public MythicMobsDataProvider() {
|
||||
super("MythicMobs");
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return getPlugin() != null;
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin("MythicMobs");
|
||||
@Override
|
||||
public @Nullable Entity spawnMob(@NotNull Location location, @NotNull Identifier entityId) throws MissingResourceException {
|
||||
var mm = MythicBukkit.inst().getMobManager().spawnMob(entityId.key(), location);
|
||||
if (mm == null) throw new MissingResourceException("Failed to find mob!", entityId.namespace(), entityId.key());
|
||||
return mm.getEntity().getBukkitEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn a mythic mob at this location
|
||||
*
|
||||
* @param mob The mob
|
||||
* @param location The location
|
||||
* @return The mob, or null if it can't be spawned
|
||||
*/
|
||||
public @Nullable Entity spawnMob(String mob, Location location) {
|
||||
return isEnabled() ? MythicBukkit.inst().getMobManager().spawnMob(mob, location).getEntity().getBukkitEntity() : null;
|
||||
@Override
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType != DataType.ENTITY) return List.of();
|
||||
return MythicBukkit.inst()
|
||||
.getMobManager()
|
||||
.getMobNames()
|
||||
.stream()
|
||||
.map(name -> new Identifier("mythicmobs", name))
|
||||
.toList();
|
||||
}
|
||||
|
||||
public Collection<String> getMythicMobTypes() {
|
||||
return isEnabled() ? MythicBukkit.inst().getMobManager().getMobNames() : List.of();
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
return id.namespace().equalsIgnoreCase("mythicmobs") && dataType == DataType.ENTITY;
|
||||
}
|
||||
|
||||
private static class ConditionListener implements Listener {
|
||||
@EventHandler
|
||||
public void on(MythicConditionLoadEvent event) {
|
||||
switch (event.getConditionName()) {
|
||||
case "irisbiome" -> event.register(new IrisBiomeCondition(event.getConditionName(), event.getConfig()));
|
||||
case "irisregion" -> event.register(new IrisRegionCondition(event.getConditionName(), event.getConfig()));
|
||||
}
|
||||
@EventHandler
|
||||
public void on(MythicConditionLoadEvent event) {
|
||||
switch (event.getConditionName()) {
|
||||
case "irisbiome" -> event.register(new IrisBiomeCondition(event.getConditionName(), event.getConfig()));
|
||||
case "irisregion" -> event.register(new IrisRegionCondition(event.getConditionName(), event.getConfig()));
|
||||
}
|
||||
}
|
||||
|
||||
@MythicCondition(author = "CrazyDev22", name = "irisbiome", description = "Tests if the target is within the given list of biomes")
|
||||
public static class IrisBiomeCondition extends SkillCondition implements ILocationCondition {
|
||||
@MythicField(name = "biome", aliases = {"b"}, description = "A list of biomes to check")
|
||||
private Set<String> biomes = Sets.newConcurrentHashSet();
|
||||
private Set<String> biomes = ConcurrentHashMap.newKeySet();
|
||||
@MythicField(name = "surface", aliases = {"s"}, description = "If the biome check should only be performed on the surface")
|
||||
private boolean surface;
|
||||
|
||||
@ -107,10 +89,10 @@ public class MythicMobsLink {
|
||||
}
|
||||
}
|
||||
|
||||
@MythicCondition(author = "CrazyDev22", name = "irisbiome", description = "Tests if the target is within the given list of biomes")
|
||||
@MythicCondition(author = "CrazyDev22", name = "irisregion", description = "Tests if the target is within the given list of biomes")
|
||||
public static class IrisRegionCondition extends SkillCondition implements ILocationCondition {
|
||||
@MythicField(name = "region", aliases = {"r"}, description = "A list of regions to check")
|
||||
private Set<String> regions = Sets.newConcurrentHashSet();
|
||||
private Set<String> regions = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public IrisRegionCondition(String line, MythicLineConfig mlc) {
|
||||
super(line);
|
@ -1,28 +1,30 @@
|
||||
package com.volmit.iris.core.link;
|
||||
package com.volmit.iris.core.link.data;
|
||||
|
||||
import com.nexomc.nexo.api.NexoBlocks;
|
||||
import com.nexomc.nexo.api.NexoFurniture;
|
||||
import com.nexomc.nexo.api.NexoItems;
|
||||
import com.nexomc.nexo.items.ItemBuilder;
|
||||
import com.volmit.iris.core.link.ExternalDataProvider;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.data.cache.Cache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.MapMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@ -69,9 +71,9 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
|
||||
@Override
|
||||
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
|
||||
var pair = ExternalDataSVC.parseState(blockId);
|
||||
var state = pair.getB();
|
||||
blockId = pair.getA();
|
||||
var statePair = ExternalDataSVC.parseState(blockId);
|
||||
var state = statePair.getB();
|
||||
blockId = statePair.getA();
|
||||
|
||||
if (NexoBlocks.isCustomBlock(blockId.key())) {
|
||||
NexoBlocks.place(blockId.key(), block.getLocation());
|
||||
@ -81,26 +83,8 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
if (!NexoFurniture.isFurniture(blockId.key()))
|
||||
return;
|
||||
|
||||
float yaw = 0;
|
||||
BlockFace face = BlockFace.NORTH;
|
||||
|
||||
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
|
||||
RNG rng = new RNG(seed);
|
||||
if ("true".equals(state.get("randomYaw"))) {
|
||||
yaw = rng.f(0, 360);
|
||||
} else if (state.containsKey("yaw")) {
|
||||
yaw = Float.parseFloat(state.get("yaw"));
|
||||
}
|
||||
if ("true".equals(state.get("randomFace"))) {
|
||||
BlockFace[] faces = BlockFace.values();
|
||||
face = faces[rng.i(0, faces.length - 1)];
|
||||
} else if (state.containsKey("face")) {
|
||||
face = BlockFace.valueOf(state.get("face").toUpperCase());
|
||||
}
|
||||
if (face == BlockFace.SELF) {
|
||||
face = BlockFace.NORTH;
|
||||
}
|
||||
ItemDisplay display = NexoFurniture.place(blockId.key(), block.getLocation(), yaw, face);
|
||||
var pair = parseYawAndFace(engine, block, state);
|
||||
ItemDisplay display = NexoFurniture.place(blockId.key(), block.getLocation(), pair.getA(), pair.getB());
|
||||
if (display == null) return;
|
||||
ItemStack itemStack = display.getItemStack();
|
||||
if (itemStack == null) return;
|
||||
@ -114,46 +98,31 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
|
||||
if (biomeColor == null) return;
|
||||
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
|
||||
if (itemStack.getItemMeta() instanceof PotionMeta meta) {
|
||||
meta.setColor(potionColor);
|
||||
itemStack.setItemMeta(meta);
|
||||
var meta = itemStack.getItemMeta();
|
||||
switch (meta) {
|
||||
case LeatherArmorMeta armor -> armor.setColor(potionColor);
|
||||
case PotionMeta potion -> potion.setColor(potionColor);
|
||||
case MapMeta map -> map.setColor(potionColor);
|
||||
case null, default -> {}
|
||||
}
|
||||
itemStack.setItemMeta(meta);
|
||||
}
|
||||
display.setItemStack(itemStack);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return NexoItems.itemNames().stream()
|
||||
public @NotNull Collection<@NotNull Identifier> getTypes(@NotNull DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return List.of();
|
||||
return NexoItems.itemNames()
|
||||
.stream()
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getBlockData(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
return NexoItems.itemNames().stream()
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
return getItemStack(i) != null;
|
||||
} catch (MissingResourceException e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toArray(Identifier[]::new);
|
||||
.filter(dataType.asPredicate(this))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
|
||||
public boolean isValidProvider(@NotNull Identifier id, DataType dataType) {
|
||||
if (dataType == DataType.ENTITY) return false;
|
||||
return "nexo".equalsIgnoreCase(id.namespace());
|
||||
}
|
||||
|
@ -24,22 +24,23 @@ import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class INMS {
|
||||
private static final Map<String, String> REVISION = Map.of(
|
||||
"1.20.5", "v1_20_R4",
|
||||
"1.20.6", "v1_20_R4",
|
||||
"1.21", "v1_21_R1",
|
||||
"1.21.1", "v1_21_R1",
|
||||
"1.21.2", "v1_21_R2",
|
||||
"1.21.3", "v1_21_R2",
|
||||
"1.21.4", "v1_21_R3",
|
||||
"1.21.5", "v1_21_R4",
|
||||
"1.21.6", "v1_21_R5",
|
||||
"1.21.7", "v1_21_R5"
|
||||
private static final Version CURRENT = Boolean.getBoolean("iris.no-version-limit") ?
|
||||
new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, null) :
|
||||
new Version(21, 8, null);
|
||||
|
||||
private static final List<Version> REVISION = List.of(
|
||||
new Version(21, 6, "v1_21_R5"),
|
||||
new Version(21, 5, "v1_21_R4"),
|
||||
new Version(21, 4, "v1_21_R3"),
|
||||
new Version(21, 2, "v1_21_R2"),
|
||||
new Version(21, 0, "v1_21_R1"),
|
||||
new Version(20, 5, "v1_20_R4")
|
||||
);
|
||||
|
||||
private static final List<Version> PACKS = List.of(
|
||||
new Version(21, 5, "31100"),
|
||||
new Version(21, 4, "31020"),
|
||||
new Version(21, 2, "31000"),
|
||||
new Version(20, 1, "3910")
|
||||
@ -47,7 +48,7 @@ public class INMS {
|
||||
|
||||
//@done
|
||||
private static final INMSBinding binding = bind();
|
||||
public static final String OVERWORLD_TAG = getOverworldTag();
|
||||
public static final String OVERWORLD_TAG = getTag(PACKS, "3910");
|
||||
|
||||
public static INMSBinding get() {
|
||||
return binding;
|
||||
@ -61,7 +62,7 @@ public class INMS {
|
||||
try {
|
||||
String name = Bukkit.getServer().getClass().getCanonicalName();
|
||||
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
|
||||
return getTag(REVISION, "BUKKIT");
|
||||
} else {
|
||||
return name.split("\\Q.\\E")[3];
|
||||
}
|
||||
@ -99,7 +100,7 @@ public class INMS {
|
||||
return new NMSBinding1X();
|
||||
}
|
||||
|
||||
private static String getOverworldTag() {
|
||||
private static String getTag(List<Version> versions, String def) {
|
||||
var version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.", 3);
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
@ -110,13 +111,16 @@ public class INMS {
|
||||
} else if (version.length == 2) {
|
||||
major = Integer.parseInt(version[1]);
|
||||
}
|
||||
if (CURRENT.major < major || CURRENT.minor < minor) {
|
||||
return versions.getFirst().tag;
|
||||
}
|
||||
|
||||
for (var p : PACKS) {
|
||||
for (var p : versions) {
|
||||
if (p.major > major || p.minor > minor)
|
||||
continue;
|
||||
return p.tag;
|
||||
}
|
||||
return "3910";
|
||||
return def;
|
||||
}
|
||||
|
||||
private record Version(int major, int minor, String tag) {}
|
||||
|
@ -153,12 +153,11 @@ public class IrisPregenerator {
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
double d = (long) (totalChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
||||
double d = (long) (generated.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
||||
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
|
||||
((totalChunks.get() - generated.get() - cached.get()) * ((double) (M.ms() - startTime.get()) / ((double) generated.get() - cached.get()))) :
|
||||
((totalChunks.get() - generated.get()) * ((double) (M.ms() - startTime.get()) / (double) generated.get())) :
|
||||
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
|
||||
((totalChunks.get() - generated.get() - cached.get()) / chunksPerSecond.getAverage()) * 1000
|
||||
);
|
||||
((totalChunks.get() - generated.get()) / chunksPerSecond.getAverage()) * 1000);
|
||||
return Double.isFinite(d) && d != INVALID ? (long) d : 0;
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,12 @@
|
||||
package com.volmit.iris.core.project;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.link.data.DataType;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.loader.ResourceLoader;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.object.annotations.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
@ -39,7 +42,6 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SchemaBuilder {
|
||||
private static final String SYMBOL_LIMIT__N = "*";
|
||||
@ -268,16 +270,18 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
KList<String> list = new KList<>();
|
||||
list.addAll(Iris.linkMythicMobs.getMythicMobTypes().stream().map(s -> "MythicMobs:" + s).collect(Collectors.toList()));
|
||||
//TODO add Citizens stuff here too
|
||||
KList<String> list = Iris.service(ExternalDataSVC.class)
|
||||
.getAllIdentifiers(DataType.ENTITY)
|
||||
.stream()
|
||||
.map(Identifier::toString)
|
||||
.collect(KList.collector());
|
||||
j.put("enum", list.toJSONStringArray());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Mythic Mob Type";
|
||||
fancyType = "Custom Mob Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files.");
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Custom Mob Type (use ctrl+space for auto complete!)");
|
||||
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
String key = "enum-font";
|
||||
|
||||
|
@ -1,15 +1,13 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
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.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.agent.Agent;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.misc.ServerProperties;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
@ -21,6 +19,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.volmit.iris.Iris.getJavaVersion;
|
||||
import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
|
||||
@ -187,27 +186,9 @@ public class ServerBootSFG {
|
||||
}
|
||||
|
||||
private static KSet<String> getDimensionTypes() {
|
||||
var bukkit = YamlConfiguration.loadConfiguration(ServerProperties.BUKKIT_YML);
|
||||
var worlds = bukkit.getConfigurationSection("worlds");
|
||||
if (worlds == null) return new KSet<>();
|
||||
|
||||
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;
|
||||
return IrisWorlds.get()
|
||||
.getDimensions()
|
||||
.map(IrisDimension::getDimensionTypeKey)
|
||||
.collect(Collectors.toCollection(KSet::new));
|
||||
}
|
||||
}
|
||||
|
@ -20,16 +20,21 @@ package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.link.*;
|
||||
import com.volmit.iris.core.link.data.DataType;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.io.JarScanner;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -47,43 +52,12 @@ public class ExternalDataSVC implements IrisService {
|
||||
Iris.info("Loading ExternalDataProvider...");
|
||||
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||
|
||||
providers.add(new NexoDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("Nexo") != null) {
|
||||
Iris.info("Nexo found, loading NexoDataProvider...");
|
||||
}
|
||||
providers.add(new MythicCrucibleDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
|
||||
Iris.info("MythicCrucible found, loading MythicCrucibleDataProvider...");
|
||||
}
|
||||
providers.add(new ItemAdderDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
|
||||
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
|
||||
}
|
||||
providers.add(new ExecutableItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
|
||||
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
|
||||
}
|
||||
providers.add(new HMCLeavesDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("HMCLeaves") != null) {
|
||||
Iris.info("BlockAdder found, loading HMCLeavesDataProvider...");
|
||||
}
|
||||
providers.add(new MMOItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) {
|
||||
Iris.info("MMOItems found, loading MMOItemsDataProvider...");
|
||||
}
|
||||
providers.add(new EcoItemsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("EcoItems") != null) {
|
||||
Iris.info("EcoItems found, loading EcoItemsDataProvider...");
|
||||
}
|
||||
providers.add(new KGeneratorsDataProvider());
|
||||
if (Bukkit.getPluginManager().getPlugin("KGenerators") != null) {
|
||||
Iris.info("KGenerators found, loading KGeneratorsDataProvider...");
|
||||
}
|
||||
|
||||
providers.addAll(createProviders());
|
||||
for (ExternalDataProvider p : providers) {
|
||||
if (p.isReady()) {
|
||||
activeProviders.add(p);
|
||||
p.init();
|
||||
Iris.instance.registerListener(p);
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
|
||||
}
|
||||
}
|
||||
@ -99,6 +73,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
|
||||
activeProviders.add(edp);
|
||||
edp.init();
|
||||
Iris.instance.registerListener(edp);
|
||||
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
|
||||
});
|
||||
}
|
||||
@ -113,6 +88,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
if (provider.isReady()) {
|
||||
activeProviders.add(provider);
|
||||
provider.init();
|
||||
Iris.instance.registerListener(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +96,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
var pair = parseState(key);
|
||||
Identifier mod = pair.getA();
|
||||
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mod, false)).findFirst();
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mod, DataType.BLOCK)).findFirst();
|
||||
if (provider.isEmpty())
|
||||
return Optional.empty();
|
||||
try {
|
||||
@ -132,7 +108,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
}
|
||||
|
||||
public Optional<ItemStack> getItemStack(Identifier key, KMap<String, Object> customNbt) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, DataType.ITEM)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
|
||||
return Optional.empty();
|
||||
@ -146,7 +122,7 @@ public class ExternalDataSVC implements IrisService {
|
||||
}
|
||||
|
||||
public void processUpdate(Engine engine, Block block, Identifier blockId) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(blockId, false)).findFirst();
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(blockId, DataType.BLOCK)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded material \"%s\"!", blockId);
|
||||
return;
|
||||
@ -154,16 +130,24 @@ public class ExternalDataSVC implements IrisService {
|
||||
provider.get().processUpdate(engine, block, blockId);
|
||||
}
|
||||
|
||||
public Identifier[] getAllBlockIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
public Entity spawnMob(Location location, Identifier mobId) {
|
||||
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mobId, DataType.ENTITY)).findFirst();
|
||||
if (provider.isEmpty()) {
|
||||
Iris.warn("No matching Provider found for modded mob \"%s\"!", mobId);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return provider.get().spawnMob(location, mobId);
|
||||
} catch (MissingResourceException e) {
|
||||
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Identifier[] getAllItemIdentifiers() {
|
||||
KList<Identifier> names = new KList<>();
|
||||
activeProviders.forEach(p -> names.add(p.getItemTypes()));
|
||||
return names.toArray(new Identifier[0]);
|
||||
public Collection<Identifier> getAllIdentifiers(DataType dataType) {
|
||||
return activeProviders.stream()
|
||||
.flatMap(p -> p.getTypes(dataType).stream())
|
||||
.toList();
|
||||
}
|
||||
|
||||
public static Pair<Identifier, KMap<String, String>> parseState(Identifier key) {
|
||||
@ -188,4 +172,21 @@ public class ExternalDataSVC implements IrisService {
|
||||
.collect(Collectors.joining(",", key.key() + "[", "]"));
|
||||
return new Identifier(key.namespace(), path);
|
||||
}
|
||||
|
||||
private static KList<ExternalDataProvider> createProviders() {
|
||||
JarScanner jar = new JarScanner(Iris.instance.getJarFile(), "com.volmit.iris.core.link.data", false);
|
||||
J.attempt(jar::scan);
|
||||
KList<ExternalDataProvider> providers = new KList<>();
|
||||
|
||||
for (Class<?> c : jar.getClasses()) {
|
||||
if (ExternalDataProvider.class.isAssignableFrom(c)) {
|
||||
try {
|
||||
ExternalDataProvider p = (ExternalDataProvider) c.getDeclaredConstructor().newInstance();
|
||||
if (p.getPlugin() != null) Iris.info(p.getPluginId() + " found, loading " + c.getSimpleName() + "...");
|
||||
providers.add(p);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
@ -250,30 +249,25 @@ public class StudioSVC implements IrisService {
|
||||
return;
|
||||
}
|
||||
|
||||
File dimensions = new File(dir, "dimensions");
|
||||
IrisData data = IrisData.get(dir);
|
||||
String[] dimensions = data.getDimensionLoader().getPossibleKeys();
|
||||
|
||||
if (!(dimensions.exists() && dimensions.isDirectory())) {
|
||||
sender.sendMessage("Invalid Format. Missing dimensions folder");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dimensions.listFiles() == null) {
|
||||
if (dimensions == null || dimensions.length == 0) {
|
||||
sender.sendMessage("No dimension file found in the extracted zip file.");
|
||||
sender.sendMessage("Check it is there on GitHub and report this to staff!");
|
||||
} else if (dimensions.listFiles().length != 1) {
|
||||
} else if (dimensions.length != 1) {
|
||||
sender.sendMessage("Dimensions folder must have 1 file in it");
|
||||
return;
|
||||
}
|
||||
|
||||
File dim = dimensions.listFiles()[0];
|
||||
IrisDimension d = data.getDimensionLoader().load(dimensions[0]);
|
||||
|
||||
if (!dim.isFile()) {
|
||||
if (d == null) {
|
||||
sender.sendMessage("Invalid dimension (folder) in dimensions folder");
|
||||
return;
|
||||
}
|
||||
|
||||
String key = dim.getName().split("\\Q.\\E")[0];
|
||||
IrisDimension d = new Gson().fromJson(IO.readAll(dim), IrisDimension.class);
|
||||
String key = d.getLoadKey();
|
||||
sender.sendMessage("Importing " + d.getName() + " (" + key + ")");
|
||||
File packEntry = new File(packs, key);
|
||||
|
||||
|
@ -46,13 +46,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
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
|
||||
*/
|
||||
@Data
|
||||
@Accessors(fluent = true, chain = true)
|
||||
public class IrisCreator {
|
||||
private static final File BUKKIT_YML = new File("bukkit.yml");
|
||||
/**
|
||||
* 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.engine.object.*;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
import com.volmit.iris.util.reflect.WrappedField;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
@ -47,6 +47,7 @@ import com.volmit.iris.util.mantle.flag.MantleFlag;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
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.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
@ -224,6 +225,12 @@ public class IrisEngine implements Engine {
|
||||
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) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
|
@ -231,6 +231,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
@ChunkCoordinates
|
||||
IrisJigsawStructure getStructureAt(int x, int z);
|
||||
|
||||
@BlockCoordinates
|
||||
IrisJigsawStructure getStructureAt(int x, int y, int z);
|
||||
|
||||
@BlockCoordinates
|
||||
default IrisBiome getCaveBiome(int x, int z) {
|
||||
return getComplex().getCaveBiomeStream().get(x, z);
|
||||
@ -262,7 +265,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
getMantle().updateBlock(x, y, z);
|
||||
}
|
||||
if (data instanceof IrisCustomData) {
|
||||
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM, true);
|
||||
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM_ACTIVE, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
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.scheduling.J;
|
||||
import lombok.Data;
|
||||
@ -149,11 +150,13 @@ public class PlannedStructure {
|
||||
}
|
||||
|
||||
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);
|
||||
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(), 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;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.mantle.MantleChunk;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.Matter;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import lombok.Data;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.Vector;
|
||||
@ -71,6 +72,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
||||
Set<IrisPosition> returnset = new HashSet<>();
|
||||
int ceilrad = (int) Math.ceil(radius);
|
||||
double r2 = Math.pow(radius, 2);
|
||||
|
||||
for (IrisPosition v : vset) {
|
||||
int tipx = v.getX();
|
||||
@ -80,7 +82,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
|
||||
for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) {
|
||||
for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) {
|
||||
if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= radius) {
|
||||
if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= r2) {
|
||||
returnset.add(new IrisPosition(loopx, loopy, loopz));
|
||||
}
|
||||
}
|
||||
@ -113,7 +115,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
for (double d : pars) {
|
||||
sum += Math.pow(d, 2);
|
||||
}
|
||||
return Math.sqrt(sum);
|
||||
return sum;
|
||||
}
|
||||
|
||||
private static double lengthSq(double x, double y, double z) {
|
||||
@ -453,6 +455,62 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
* @param <T> the type of data to apply to the mantle
|
||||
*/
|
||||
public <T> void setLineConsumer(List<IrisPosition> vectors, double radius, boolean filled, Function3<Integer, Integer, Integer, T> data) {
|
||||
Set<IrisPosition> vset = cleanup(vectors);
|
||||
vset = getBallooned(vset, radius);
|
||||
|
||||
if (!filled) {
|
||||
vset = getHollowed(vset);
|
||||
}
|
||||
|
||||
setConsumer(vset, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set lines for points
|
||||
*
|
||||
* @param vectors the points
|
||||
* @param radius the radius
|
||||
* @param filled hollow or filled?
|
||||
* @param data the data to set
|
||||
* @param <T> the type of data to apply to the mantle
|
||||
*/
|
||||
public <T> void setNoiseMasked(List<IrisPosition> vectors, double radius, double threshold, CNG shape, Set<IrisPosition> masks, boolean filled, Function3<Integer, Integer, Integer, T> data) {
|
||||
Set<IrisPosition> vset = cleanup(vectors);
|
||||
vset = masks == null ? getBallooned(vset, radius) : getMasked(vset, masks, radius);
|
||||
vset.removeIf(p -> shape.noise(p.getX(), p.getY(), p.getZ()) < threshold);
|
||||
|
||||
if (!filled) {
|
||||
vset = getHollowed(vset);
|
||||
}
|
||||
|
||||
setConsumer(vset, data);
|
||||
}
|
||||
|
||||
private static Set<IrisPosition> getMasked(Set<IrisPosition> vectors, Set<IrisPosition> masks, double radius) {
|
||||
Set<IrisPosition> vset = new KSet<>();
|
||||
int ceil = (int) Math.ceil(radius);
|
||||
double r2 = Math.pow(radius, 2);
|
||||
|
||||
for (IrisPosition v : vectors) {
|
||||
int tipX = v.getX();
|
||||
int tipY = v.getY();
|
||||
int tipZ = v.getZ();
|
||||
|
||||
for (int x = -ceil; x <= ceil; x++) {
|
||||
for (int y = -ceil; y <= ceil; y++) {
|
||||
for (int z = -ceil; z <= ceil; z++) {
|
||||
if (hypot(x, y, z) > r2 || !masks.contains(new IrisPosition(x, y, z)))
|
||||
continue;
|
||||
vset.add(new IrisPosition(tipX + x, tipY + y, tipZ + z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vset;
|
||||
}
|
||||
|
||||
private static Set<IrisPosition> cleanup(List<IrisPosition> vectors) {
|
||||
Set<IrisPosition> vset = new KSet<>();
|
||||
|
||||
for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) {
|
||||
@ -504,13 +562,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
vset = getBallooned(vset, radius);
|
||||
|
||||
if (!filled) {
|
||||
vset = getHollowed(vset);
|
||||
}
|
||||
|
||||
setConsumer(vset, data);
|
||||
return vset;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,31 +62,31 @@ public class IrisCarving {
|
||||
|
||||
@BlockCoordinates
|
||||
public void doCarving(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int depth) {
|
||||
doCarving(writer, rng, engine, x, y, z, depth, -1);
|
||||
doCarving(writer, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, depth, -1);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
public void doCarving(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
public void doCarving(MantleWriter writer, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
int nextRecursion = recursion + 1;
|
||||
|
||||
if (caves.isNotEmpty()) {
|
||||
for (IrisCavePlacer i : caves) {
|
||||
if (recursion > i.getMaxRecursion()) continue;
|
||||
i.generateCave(writer, rng, engine, x, y, z, nextRecursion, waterHint);
|
||||
i.generateCave(writer, rng, base, engine, x, y, z, nextRecursion, waterHint);
|
||||
}
|
||||
}
|
||||
|
||||
if (ravines.isNotEmpty()) {
|
||||
for (IrisRavinePlacer i : ravines) {
|
||||
if (recursion > i.getMaxRecursion()) continue;
|
||||
i.generateRavine(writer, rng, engine, x, y, z, nextRecursion, waterHint);
|
||||
i.generateRavine(writer, rng, base, engine, x, y, z, nextRecursion, waterHint);
|
||||
}
|
||||
}
|
||||
|
||||
if (spheres.isNotEmpty()) {
|
||||
for (IrisSphere i : spheres) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
i.generate(rng, engine, writer, x, y, z);
|
||||
i.generate(base, engine, writer, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,7 +94,7 @@ public class IrisCarving {
|
||||
if (elipsoids.isNotEmpty()) {
|
||||
for (IrisElipsoid i : elipsoids) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
i.generate(rng, engine, writer, x, y, z);
|
||||
i.generate(base, engine, writer, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,7 +102,7 @@ public class IrisCarving {
|
||||
if (pyramids.isNotEmpty()) {
|
||||
for (IrisPyramid i : pyramids) {
|
||||
if (rng.nextInt(i.getRarity()) == 0) {
|
||||
i.generate(rng, engine, writer, x, y, z);
|
||||
i.generate(base, engine, writer, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,11 @@ import com.volmit.iris.engine.mantle.MantleWriter;
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.MatterCavern;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@ -55,6 +57,9 @@ public class IrisCave extends IrisRegistrant {
|
||||
@Desc("Limit the worm from ever getting higher or lower than this range")
|
||||
private IrisRange verticalRange = new IrisRange(3, 255);
|
||||
|
||||
@Desc("Shape of the caves")
|
||||
private IrisCaveShape shape = new IrisCaveShape();
|
||||
|
||||
@Override
|
||||
public String getFolderName() {
|
||||
return "caves";
|
||||
@ -66,12 +71,12 @@ public class IrisCave extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z) {
|
||||
generate(writer, rng, engine, x, y, z, 0, -1, true);
|
||||
generate(writer, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, 0, -1, true);
|
||||
}
|
||||
|
||||
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint, boolean breakSurface) {
|
||||
double girth = getWorm().getGirth().get(rng, x, z, engine.getData());
|
||||
KList<IrisPosition> points = getWorm().generate(rng, engine.getData(), writer, verticalRange, x, y, z, breakSurface, girth + 9);
|
||||
public void generate(MantleWriter writer, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint, boolean breakSurface) {
|
||||
double girth = getWorm().getGirth().get(base.nextParallelRNG(465156), x, z, engine.getData());
|
||||
KList<IrisPosition> points = getWorm().generate(base.nextParallelRNG(784684), engine.getData(), writer, verticalRange, x, y, z, breakSurface, girth + 9);
|
||||
int highestWater = Math.max(waterHint, -1);
|
||||
|
||||
if (highestWater == -1) {
|
||||
@ -87,17 +92,19 @@ public class IrisCave extends IrisRegistrant {
|
||||
}
|
||||
|
||||
|
||||
int h = Math.min(Math.max(highestWater, waterHint), engine.getDimension().getFluidHeight());
|
||||
int h = Math.min(highestWater, engine.getDimension().getFluidHeight());
|
||||
|
||||
for (IrisPosition i : points) {
|
||||
fork.doCarving(writer, rng, engine, i.getX(), i.getY(), i.getZ(), recursion, h);
|
||||
fork.doCarving(writer, rng, base, engine, i.getX(), i.getY(), i.getZ(), recursion, h);
|
||||
}
|
||||
|
||||
MatterCavern c = new MatterCavern(true, customBiome, (byte) 0);
|
||||
MatterCavern w = new MatterCavern(true, customBiome, (byte) 1);
|
||||
|
||||
writer.setLineConsumer(points,
|
||||
girth, true,
|
||||
CNG cng = shape.getNoise(base.nextParallelRNG(8131545), engine);
|
||||
KSet<IrisPosition> mask = shape.getMasked(rng, engine);
|
||||
writer.setNoiseMasked(points,
|
||||
girth, cng.noise(x, y, z), cng, mask, true,
|
||||
(xf, yf, zf) -> yf <= h ? w : c);
|
||||
}
|
||||
|
||||
@ -107,6 +114,6 @@ public class IrisCave extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public int getMaxSize(IrisData data, int depth) {
|
||||
return getWorm().getMaxDistance() + fork.getMaxRange(data, depth);
|
||||
return (int) (Math.ceil(getWorm().getGirth().getMax() * 2) + getWorm().getMaxDistance() + fork.getMaxRange(data, depth));
|
||||
}
|
||||
}
|
||||
|
@ -64,10 +64,10 @@ public class IrisCavePlacer implements IRare {
|
||||
}
|
||||
|
||||
public void generateCave(MantleWriter mantle, RNG rng, Engine engine, int x, int y, int z) {
|
||||
generateCave(mantle, rng, engine, x, y, z, 0, -1);
|
||||
generateCave(mantle, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, 0, -1);
|
||||
}
|
||||
|
||||
public void generateCave(MantleWriter mantle, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
public void generateCave(MantleWriter mantle, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
if (fail.get()) {
|
||||
return;
|
||||
}
|
||||
@ -86,13 +86,13 @@ public class IrisCavePlacer implements IRare {
|
||||
}
|
||||
|
||||
if (y == -1) {
|
||||
int h = (int) caveStartHeight.get(rng, x, z, data);
|
||||
int h = (int) caveStartHeight.get(base, x, z, data);
|
||||
int ma = breakSurface ? h : (int) (engine.getComplex().getHeightStream().get(x, z) - 9);
|
||||
y = Math.min(h, ma);
|
||||
}
|
||||
|
||||
try {
|
||||
cave.generate(mantle, rng, engine, x + rng.nextInt(15), y, z + rng.nextInt(15), recursion, waterHint, breakSurface);
|
||||
cave.generate(mantle, rng, base, engine, x + rng.nextInt(15), y, z + rng.nextInt(15), recursion, waterHint, breakSurface);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
fail.set(true);
|
||||
|
@ -0,0 +1,76 @@
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Snippet("cave-shape")
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Desc("Cave Shape")
|
||||
@Data
|
||||
public class IrisCaveShape {
|
||||
private transient final KMap<IrisPosition, KSet<IrisPosition>> cache = new KMap<>();
|
||||
|
||||
@Desc("Noise used for the shape of the cave")
|
||||
private IrisGeneratorStyle noise = new IrisGeneratorStyle();
|
||||
@RegistryListResource(IrisObject.class)
|
||||
@Desc("Object used as mask for the shape of the cave")
|
||||
private String object = null;
|
||||
@Desc("Rotation to apply to objects before using them as mask")
|
||||
private IrisObjectRotation objectRotation = new IrisObjectRotation();
|
||||
|
||||
public CNG getNoise(RNG rng, Engine engine) {
|
||||
return noise.create(rng, engine.getData());
|
||||
}
|
||||
|
||||
public KSet<IrisPosition> getMasked(RNG rng, Engine engine) {
|
||||
if (object == null) return null;
|
||||
return cache.computeIfAbsent(randomRotation(rng), pos -> {
|
||||
var rotated = new KSet<IrisPosition>();
|
||||
engine.getData().getObjectLoader().load(object).getBlocks().forEach((vector, data) -> {
|
||||
if (data.getMaterial().isAir()) return;
|
||||
rotated.add(new IrisPosition(objectRotation.rotate(vector, pos.getX(), pos.getY(), pos.getZ())));
|
||||
});
|
||||
return rotated;
|
||||
});
|
||||
}
|
||||
|
||||
private IrisPosition randomRotation(RNG rng) {
|
||||
if (objectRotation == null || !objectRotation.canRotate())
|
||||
return new IrisPosition(0,0,0);
|
||||
return new IrisPosition(
|
||||
randomDegree(rng, objectRotation.getXAxis()),
|
||||
randomDegree(rng, objectRotation.getYAxis()),
|
||||
randomDegree(rng, objectRotation.getZAxis())
|
||||
);
|
||||
}
|
||||
|
||||
private int randomDegree(RNG rng, IrisAxisRotationClamp clamp) {
|
||||
if (!clamp.isEnabled()) return 0;
|
||||
if (clamp.isLocked()) return (int) clamp.getMax();
|
||||
double interval = clamp.getInterval();
|
||||
if (interval < 1) interval = 1;
|
||||
|
||||
double min = clamp.getMin(), max = clamp.getMax();
|
||||
double value = (interval * (Math.ceil(Math.abs(rng.d(0, 360) / interval)))) % 360D;
|
||||
if (clamp.isUnlimited()) return (int) value;
|
||||
|
||||
if (min > max) {
|
||||
max = clamp.getMin();
|
||||
min = clamp.getMax();
|
||||
}
|
||||
return (int) (double) M.clip(value, min, max);
|
||||
}
|
||||
}
|
@ -20,8 +20,10 @@ package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.annotations.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@ -451,24 +453,13 @@ public class IrisEntity extends IrisRegistrant {
|
||||
}
|
||||
|
||||
if (isSpecialType()) {
|
||||
if (specialType.toLowerCase().startsWith("mythicmobs:")) {
|
||||
return Iris.linkMythicMobs.spawnMob(specialType.substring(11), at);
|
||||
} else {
|
||||
Iris.warn("Invalid mob type to spawn: '" + specialType + "'!");
|
||||
return null;
|
||||
}
|
||||
return Iris.service(ExternalDataSVC.class).spawnMob(at, Identifier.fromString(specialType));
|
||||
}
|
||||
|
||||
|
||||
return INMS.get().spawnEntity(at, getType(), getReason());
|
||||
}
|
||||
|
||||
public boolean isCitizens() {
|
||||
return false;
|
||||
|
||||
// TODO: return Iris.linkCitizens.supported() && someType is not empty;
|
||||
}
|
||||
|
||||
public boolean isSpecialType() {
|
||||
return specialType != null && !specialType.equals("");
|
||||
}
|
||||
|
@ -93,13 +93,13 @@ public class IrisRavine extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z) {
|
||||
generate(writer, rng, engine, x, y, z, 0, -1);
|
||||
generate(writer, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, 0, -1);
|
||||
}
|
||||
|
||||
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
KList<IrisPosition> pos = getWorm().generate(rng, engine.getData(), writer, null, x, y, z, true, 0);
|
||||
CNG dg = depthStyle.getGenerator().createNoCache(rng, engine.getData());
|
||||
CNG bw = baseWidthStyle.getGenerator().createNoCache(rng, engine.getData());
|
||||
public void generate(MantleWriter writer, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
KList<IrisPosition> pos = getWorm().generate(base.nextParallelRNG(879615), engine.getData(), writer, null, x, y, z, true, 0);
|
||||
CNG dg = depthStyle.getGenerator().create(base.nextParallelRNG(7894156), engine.getData());
|
||||
CNG bw = baseWidthStyle.getGenerator().create(base.nextParallelRNG(15315456), engine.getData());
|
||||
int highestWater = Math.max(waterHint, -1);
|
||||
boolean water = false;
|
||||
|
||||
@ -134,7 +134,7 @@ public class IrisRavine extends IrisRegistrant {
|
||||
int width = (int) Math.round(bw.fitDouble(baseWidthStyle.getMin(), baseWidthStyle.getMax(), p.getX(), p.getZ()));
|
||||
int surface = (int) Math.round(rsurface - depth * 0.45);
|
||||
|
||||
fork.doCarving(writer, rng, engine, p.getX(), rng.i(surface - depth, surface), p.getZ(), recursion, Math.max(highestWater, waterHint));
|
||||
fork.doCarving(writer, rng, base, engine, p.getX(), rng.i(surface - depth, surface), p.getZ(), recursion, highestWater);
|
||||
|
||||
for (int i = surface + depth; i >= surface; i--) {
|
||||
if (i % ribThickness == 0) {
|
||||
|
@ -60,10 +60,10 @@ public class IrisRavinePlacer implements IRare {
|
||||
}
|
||||
|
||||
public void generateRavine(MantleWriter mantle, RNG rng, Engine engine, int x, int y, int z) {
|
||||
generateRavine(mantle, rng, engine, x, y, z, 0, -1);
|
||||
generateRavine(mantle, rng, new RNG(engine.getSeedManager().getCarve()), engine, x, y, z, 0, -1);
|
||||
}
|
||||
|
||||
public void generateRavine(MantleWriter mantle, RNG rng, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
public void generateRavine(MantleWriter mantle, RNG rng, RNG base, Engine engine, int x, int y, int z, int recursion, int waterHint) {
|
||||
if (fail.get()) {
|
||||
return;
|
||||
}
|
||||
@ -84,7 +84,7 @@ public class IrisRavinePlacer implements IRare {
|
||||
try {
|
||||
int xx = x + rng.nextInt(15);
|
||||
int zz = z + rng.nextInt(15);
|
||||
ravine.generate(mantle, rng, engine, xx, y, zz, recursion, waterHint);
|
||||
ravine.generate(mantle, rng, base, engine, xx, y, zz, recursion, waterHint);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
fail.set(true);
|
||||
|
@ -71,9 +71,9 @@ public class IrisWorm {
|
||||
IrisPosition start = new IrisPosition(x, y, z);
|
||||
KList<IrisPosition> pos = new KList<>();
|
||||
KSet<IrisPosition> check = allowLoops ? null : new KSet<>();
|
||||
CNG gx = xStyle.getGenerator().createNoCache(new RNG(rng.lmax()), data);
|
||||
CNG gy = yStyle.getGenerator().createNoCache(new RNG(rng.lmax()), data);
|
||||
CNG gz = zStyle.getGenerator().createNoCache(new RNG(rng.lmax()), data);
|
||||
CNG gx = xStyle.getGenerator().create(rng.nextParallelRNG(14567), data);
|
||||
CNG gy = yStyle.getGenerator().create(rng.nextParallelRNG(64789), data);
|
||||
CNG gz = zStyle.getGenerator().create(rng.nextParallelRNG(34790), data);
|
||||
|
||||
while (itr-- > 0) {
|
||||
IrisPosition current = new IrisPosition(Math.round(cx), Math.round(cy), Math.round(cz));
|
||||
|
@ -64,12 +64,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@ -95,8 +93,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
@Setter
|
||||
private volatile StudioGenerator studioGenerator;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey) {
|
||||
setup = new AtomicBoolean(false);
|
||||
studioGenerator = null;
|
||||
@ -114,8 +110,8 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
if (initialized || !world.name().equals(event.getWorld().getName()))
|
||||
return;
|
||||
if (!world.name().equals(event.getWorld().getName())) return;
|
||||
Iris.instance.unregisterListener(this);
|
||||
world.setRawWorldSeed(event.getWorld().getSeed());
|
||||
if (initialize(event.getWorld())) return;
|
||||
|
||||
@ -140,7 +136,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
}
|
||||
spawnChunks.complete(INMS.get().getSpawnChunkCount(world));
|
||||
Iris.instance.unregisterListener(this);
|
||||
initialized = true;
|
||||
IrisWorlds.get().put(world.getName(), dimensionKey);
|
||||
return true;
|
||||
}
|
||||
@ -205,50 +200,57 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectChunkReplacement(World world, int x, int z, Consumer<Runnable> jobs) {
|
||||
public void injectChunkReplacement(World world, int x, int z, Executor syncExecutor) {
|
||||
try {
|
||||
loadLock.acquire();
|
||||
IrisBiomeStorage st = new IrisBiomeStorage();
|
||||
TerrainChunk tc = TerrainChunk.createUnsafe(world, st);
|
||||
Hunk<BlockData> blocks = Hunk.view(tc);
|
||||
Hunk<Biome> biomes = Hunk.view(tc, tc.getMinHeight(), tc.getMaxHeight());
|
||||
this.world.bind(world);
|
||||
getEngine().generate(x << 4, z << 4, blocks, biomes, true);
|
||||
Iris.debug("Regenerated " + x + " " + z);
|
||||
int t = 0;
|
||||
getEngine().generate(x << 4, z << 4, tc, false);
|
||||
|
||||
Chunk c = PaperLib.getChunkAtAsync(world, x, z)
|
||||
.thenApply(d -> {
|
||||
d.addPluginChunkTicket(Iris.instance);
|
||||
|
||||
for (Entity ee : d.getEntities()) {
|
||||
if (ee instanceof Player) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ee.remove();
|
||||
}
|
||||
|
||||
engine.getWorldManager().onChunkLoad(d, false);
|
||||
return d;
|
||||
}).get();
|
||||
|
||||
|
||||
KList<CompletableFuture<?>> futures = new KList<>(1 + getEngine().getHeight() >> 4);
|
||||
for (int i = getEngine().getHeight() >> 4; i >= 0; i--) {
|
||||
if (!world.isChunkLoaded(x, z)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Chunk c = world.getChunkAt(x, z);
|
||||
for (Entity ee : c.getEntities()) {
|
||||
if (ee instanceof Player) {
|
||||
continue;
|
||||
}
|
||||
|
||||
J.s(ee::remove);
|
||||
}
|
||||
|
||||
J.s(() -> engine.getWorldManager().onChunkLoad(c, false));
|
||||
|
||||
int finalI = i;
|
||||
jobs.accept(() -> {
|
||||
|
||||
int finalI = i << 4;
|
||||
futures.add(CompletableFuture.runAsync(() -> {
|
||||
for (int xx = 0; xx < 16; xx++) {
|
||||
for (int yy = 0; yy < 16; yy++) {
|
||||
for (int zz = 0; zz < 16; zz++) {
|
||||
if (yy + (finalI << 4) >= engine.getHeight() || yy + (finalI << 4) < 0) {
|
||||
if (yy + finalI >= engine.getHeight() || yy + finalI < 0) {
|
||||
continue;
|
||||
}
|
||||
c.getBlock(xx, yy + (finalI << 4) + world.getMinHeight(), zz)
|
||||
.setBlockData(tc.getBlockData(xx, yy + (finalI << 4) + world.getMinHeight(), zz), false);
|
||||
int y = yy + finalI + world.getMinHeight();
|
||||
c.getBlock(xx, y, zz).setBlockData(tc.getBlockData(xx, y, zz), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, syncExecutor));
|
||||
}
|
||||
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
.thenRunAsync(() -> {
|
||||
c.removePluginChunkTicket(Iris.instance);
|
||||
c.unload();
|
||||
}, syncExecutor)
|
||||
.get();
|
||||
Iris.debug("Regenerated " + x + " " + z);
|
||||
|
||||
loadLock.release();
|
||||
} catch (Throwable e) {
|
||||
loadLock.release();
|
||||
|
@ -28,7 +28,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public interface PlatformChunkGenerator extends Hotloadable, DataProvider {
|
||||
@Nullable
|
||||
@ -42,7 +42,7 @@ public interface PlatformChunkGenerator extends Hotloadable, DataProvider {
|
||||
@NotNull
|
||||
EngineTarget getTarget();
|
||||
|
||||
void injectChunkReplacement(World world, int x, int z, Consumer<Runnable> jobs);
|
||||
void injectChunkReplacement(World world, int x, int z, Executor syncExecutor);
|
||||
|
||||
void close();
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.util.collection;
|
||||
|
||||
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.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
@ -306,6 +307,18 @@ public class KList<T> extends ArrayList<T> implements List<T> {
|
||||
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) {
|
||||
for (T i : copy()) {
|
||||
if (t.test(i)) {
|
||||
|
@ -21,6 +21,7 @@ package com.volmit.iris.util.data;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.link.Identifier;
|
||||
import com.volmit.iris.core.link.data.DataType;
|
||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
@ -673,7 +674,7 @@ public class B {
|
||||
}
|
||||
}
|
||||
|
||||
for (Identifier id : Iris.service(ExternalDataSVC.class).getAllBlockIdentifiers())
|
||||
for (Identifier id : Iris.service(ExternalDataSVC.class).getAllIdentifiers(DataType.BLOCK))
|
||||
bt.add(id.toString());
|
||||
bt.addAll(custom.k());
|
||||
|
||||
@ -688,7 +689,7 @@ public class B {
|
||||
bt.add(v);
|
||||
}
|
||||
|
||||
for (Identifier id : Iris.service(ExternalDataSVC.class).getAllItemIdentifiers())
|
||||
for (Identifier id : Iris.service(ExternalDataSVC.class).getAllIdentifiers(DataType.ITEM))
|
||||
bt.add(id.toString());
|
||||
|
||||
return bt.toArray(new String[0]);
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
package com.volmit.iris.util.function;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface NastyFunction<T, R> {
|
||||
R run(T t);
|
||||
R run(T t) throws Throwable;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import org.dom4j.io.XMLWriter;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
@ -598,6 +599,25 @@ public class IO {
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyDirectory(Path source, Path target) throws IOException {
|
||||
Files.walk(source).forEach(sourcePath -> {
|
||||
Path targetPath = target.resolve(source.relativize(sourcePath));
|
||||
|
||||
try {
|
||||
if (Files.isDirectory(sourcePath)) {
|
||||
if (!Files.exists(targetPath)) {
|
||||
Files.createDirectories(targetPath);
|
||||
}
|
||||
} else {
|
||||
Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to copy " + targetPath);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally close an <code>Reader</code>.
|
||||
* <p>
|
||||
|
@ -48,7 +48,6 @@ import org.bukkit.Chunk;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@ -59,16 +58,18 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
*/
|
||||
|
||||
public class Mantle {
|
||||
private static final int LOCK_SIZE = Short.MAX_VALUE;
|
||||
|
||||
private final File dataFolder;
|
||||
@Getter
|
||||
private final int worldHeight;
|
||||
private final Map<Long, Long> lastUse;
|
||||
private final Map<Long, TectonicPlate> loadedRegions;
|
||||
private final KMap<Long, Long> lastUse;
|
||||
private final KMap<Long, TectonicPlate> loadedRegions;
|
||||
private final HyperLock hyperLock;
|
||||
private final AtomicBoolean closed;
|
||||
private final MultiBurst ioBurst;
|
||||
private final AtomicBoolean ioTrim;
|
||||
private final AtomicBoolean ioTectonicUnload;
|
||||
private final Semaphore ioTrim;
|
||||
private final Semaphore ioTectonicUnload;
|
||||
private final AtomicDouble adjustedIdleDuration;
|
||||
private final KSet<Long> toUnload;
|
||||
|
||||
@ -84,8 +85,8 @@ public class Mantle {
|
||||
this.closed = new AtomicBoolean(false);
|
||||
this.dataFolder = dataFolder;
|
||||
this.worldHeight = worldHeight;
|
||||
this.ioTrim = new AtomicBoolean(false);
|
||||
this.ioTectonicUnload = new AtomicBoolean(false);
|
||||
this.ioTrim = new Semaphore(LOCK_SIZE, true);
|
||||
this.ioTectonicUnload = new Semaphore(LOCK_SIZE, true);
|
||||
loadedRegions = new KMap<>();
|
||||
lastUse = new KMap<>();
|
||||
ioBurst = MultiBurst.burst;
|
||||
@ -422,19 +423,19 @@ public class Mantle {
|
||||
throw new RuntimeException("The Mantle is closed");
|
||||
}
|
||||
|
||||
adjustedIdleDuration.set(baseIdleDuration);
|
||||
double idleDuration = baseIdleDuration;
|
||||
if (loadedRegions.size() > tectonicLimit) {
|
||||
// todo update this correctly and maybe do something when its above a 100%
|
||||
adjustedIdleDuration.set(Math.max(adjustedIdleDuration.get() - (1000 * (((loadedRegions.size() - tectonicLimit) / (double) tectonicLimit) * 100) * 0.4), 4000));
|
||||
idleDuration = Math.max(idleDuration - (1000 * (((loadedRegions.size() - tectonicLimit) / (double) tectonicLimit) * 100) * 0.4), 4000);
|
||||
}
|
||||
adjustedIdleDuration.set(idleDuration);
|
||||
|
||||
ioTrim.set(true);
|
||||
ioTrim.acquireUninterruptibly(LOCK_SIZE);
|
||||
try {
|
||||
double adjustedIdleDuration = this.adjustedIdleDuration.get();
|
||||
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration, 0));
|
||||
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(idleDuration, 0));
|
||||
|
||||
if (lastUse.isEmpty()) return;
|
||||
double unloadTime = M.ms() - adjustedIdleDuration;
|
||||
double unloadTime = M.ms() - idleDuration;
|
||||
for (long id : lastUse.keySet()) {
|
||||
hyperLock.withLong(id, () -> {
|
||||
Long lastUseTime = lastUse.get(id);
|
||||
@ -447,7 +448,7 @@ public class Mantle {
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
} finally {
|
||||
ioTrim.set(false);
|
||||
ioTrim.release(LOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,9 +461,10 @@ public class Mantle {
|
||||
BurstExecutor burst = ioBurst.burst(toUnload.size());
|
||||
burst.setMulticore(toUnload.size() > tectonicLimit);
|
||||
|
||||
ioTectonicUnload.set(true);
|
||||
ioTectonicUnload.acquireUninterruptibly(LOCK_SIZE);
|
||||
try {
|
||||
for (long id : toUnload) {
|
||||
double unloadTime = M.ms() - adjustedIdleDuration.get();
|
||||
burst.queue(() -> hyperLock.withLong(id, () -> {
|
||||
TectonicPlate m = loadedRegions.get(id);
|
||||
if (m == null) {
|
||||
@ -471,17 +473,21 @@ public class Mantle {
|
||||
return;
|
||||
}
|
||||
|
||||
var used = lastUse.getOrDefault(id, 0L);
|
||||
if (!toUnload.contains(id) || used >= unloadTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.inUse()) {
|
||||
Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ());
|
||||
lastUse.put(id, M.ms());
|
||||
toUnload.remove(id);
|
||||
use(id);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
m.write(fileForRegion(dataFolder, id, false));
|
||||
oldFileForRegion(dataFolder, id).delete();
|
||||
loadedRegions.remove(id);
|
||||
loadedRegions.remove(id, m);
|
||||
lastUse.remove(id);
|
||||
toUnload.remove(id);
|
||||
i.incrementAndGet();
|
||||
@ -497,7 +503,7 @@ public class Mantle {
|
||||
e.printStackTrace();
|
||||
burst.complete();
|
||||
} finally {
|
||||
ioTectonicUnload.set(false);
|
||||
ioTectonicUnload.release(LOCK_SIZE);
|
||||
}
|
||||
return i.get();
|
||||
}
|
||||
@ -513,30 +519,39 @@ public class Mantle {
|
||||
*/
|
||||
@RegionCoordinates
|
||||
private TectonicPlate get(int x, int z) {
|
||||
if (ioTrim.get() || ioTectonicUnload.get()) {
|
||||
boolean trim = ioTrim.tryAcquire();
|
||||
boolean unload = ioTectonicUnload.tryAcquire();
|
||||
try {
|
||||
if (!trim || !unload) {
|
||||
try {
|
||||
return getSafe(x, z).get();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Long key = key(x, z);
|
||||
TectonicPlate p = loadedRegions.get(key);
|
||||
|
||||
if (p != null && !p.isClosed()) {
|
||||
use(key);
|
||||
return p;
|
||||
}
|
||||
|
||||
try {
|
||||
return getSafe(x, z).get();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread intterruption (hotload?)");
|
||||
Iris.reportError(e);
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread execution exception (engine close?)");
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
TectonicPlate p = loadedRegions.get(key(x, z));
|
||||
|
||||
if (p != null) {
|
||||
return p;
|
||||
}
|
||||
|
||||
try {
|
||||
return getSafe(x, z).get();
|
||||
} catch (InterruptedException e) {
|
||||
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread intterruption (hotload?)");
|
||||
Iris.reportError(e);
|
||||
} catch (ExecutionException e) {
|
||||
Iris.warn("Failed to get Tectonic Plate " + x + " " + z + " Due to a thread execution exception (engine close?)");
|
||||
Iris.reportError(e);
|
||||
} finally {
|
||||
if (trim) ioTrim.release();
|
||||
if (unload) ioTectonicUnload.release();
|
||||
}
|
||||
|
||||
Iris.warn("Retrying to get " + x + " " + z + " Mantle Region");
|
||||
@ -553,19 +568,12 @@ public class Mantle {
|
||||
*/
|
||||
@RegionCoordinates
|
||||
private Future<TectonicPlate> getSafe(int x, int z) {
|
||||
Long k = key(x, z);
|
||||
TectonicPlate p = loadedRegions.get(k);
|
||||
|
||||
if (p != null) {
|
||||
lastUse.put(k, M.ms());
|
||||
return CompletableFuture.completedFuture(p);
|
||||
}
|
||||
|
||||
return ioBurst.completeValue(() -> hyperLock.withResult(x, z, () -> {
|
||||
lastUse.put(k, M.ms());
|
||||
Long k = key(x, z);
|
||||
use(k);
|
||||
TectonicPlate region = loadedRegions.get(k);
|
||||
|
||||
if (region != null) {
|
||||
if (region != null && !region.isClosed()) {
|
||||
return region;
|
||||
}
|
||||
|
||||
@ -593,16 +601,23 @@ public class Mantle {
|
||||
Iris.debug("Created new Tectonic Plate (Due to Load Failure) " + C.DARK_GREEN + x + " " + z);
|
||||
}
|
||||
|
||||
use(k);
|
||||
return region;
|
||||
}
|
||||
|
||||
region = new TectonicPlate(worldHeight, x, z);
|
||||
loadedRegions.put(k, region);
|
||||
Iris.debug("Created new Tectonic Plate " + C.DARK_GREEN + x + " " + z);
|
||||
use(k);
|
||||
return region;
|
||||
}));
|
||||
}
|
||||
|
||||
private void use(Long key) {
|
||||
lastUse.put(key, M.ms());
|
||||
toUnload.remove(key);
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.volmit.iris.util.matter.Matter;
|
||||
import com.volmit.iris.util.matter.MatterSlice;
|
||||
import com.volmit.iris.util.parallel.AtomicBooleanArray;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
@ -118,9 +119,11 @@ public class MantleChunk {
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws InterruptedException {
|
||||
@SneakyThrows
|
||||
public void close() {
|
||||
closed.set(true);
|
||||
ref.acquire(Integer.MAX_VALUE);
|
||||
ref.release(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public boolean inUse() {
|
||||
@ -130,6 +133,10 @@ public class MantleChunk {
|
||||
public MantleChunk use() {
|
||||
if (closed.get()) throw new IllegalStateException("Chunk is closed!");
|
||||
ref.acquireUninterruptibly();
|
||||
if (closed.get()) {
|
||||
ref.release();
|
||||
throw new IllegalStateException("Chunk is closed!");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -220,6 +227,7 @@ public class MantleChunk {
|
||||
* @throws IOException shit happens
|
||||
*/
|
||||
public void write(DataOutputStream dos) throws IOException {
|
||||
close();
|
||||
dos.writeByte(x);
|
||||
dos.writeByte(z);
|
||||
dos.writeByte(sections.length());
|
||||
|
@ -39,6 +39,7 @@ import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
|
||||
/**
|
||||
@ -52,6 +53,7 @@ public class TectonicPlate {
|
||||
|
||||
private final int sectionHeight;
|
||||
private final AtomicReferenceArray<MantleChunk> chunks;
|
||||
private final AtomicBoolean closed;
|
||||
|
||||
@Getter
|
||||
private final int x;
|
||||
@ -67,6 +69,7 @@ public class TectonicPlate {
|
||||
public TectonicPlate(int worldHeight, int x, int z) {
|
||||
this.sectionHeight = worldHeight >> 4;
|
||||
this.chunks = new AtomicReferenceArray<>(1024);
|
||||
this.closed = new AtomicBoolean(false);
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
@ -143,6 +146,7 @@ public class TectonicPlate {
|
||||
}
|
||||
|
||||
public void close() throws InterruptedException {
|
||||
closed.set(true);
|
||||
for (int i = 0; i < chunks.length(); i++) {
|
||||
MantleChunk chunk = chunks.get(i);
|
||||
if (chunk != null) {
|
||||
@ -151,6 +155,10 @@ public class TectonicPlate {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return closed.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a chunk exists in this plate or not (same as get(x, z) != null)
|
||||
*
|
||||
|
@ -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.JigsawPieceContainer;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@Sliced
|
||||
public class JigsawStructureMatter extends RawMatter<JigsawPieceContainer> {
|
||||
public JigsawStructureMatter() {
|
||||
this(1,1,1);
|
||||
}
|
||||
|
||||
public JigsawStructureMatter(int width, int height, int depth) {
|
||||
super(width, height, depth, JigsawPieceContainer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Palette<JigsawPieceContainer> getGlobalPalette() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNode(JigsawPieceContainer b, DataOutputStream dos) throws IOException {
|
||||
dos.writeUTF(b.getLoadKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JigsawPieceContainer readNode(DataInputStream din) throws IOException {
|
||||
return new JigsawPieceContainer(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.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import oshi.SystemInfo;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.HashMap;
|
||||
@ -45,6 +47,9 @@ public class Bindings {
|
||||
if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) return;
|
||||
Iris.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings.");
|
||||
Iris.info("Your server ID is: " + ServerID.ID);
|
||||
var resource = Iris.instance.getResource("plugin.yml");
|
||||
YamlConfiguration desc = resource != null ? YamlConfiguration.loadConfiguration(new InputStreamReader(resource)) : new YamlConfiguration();
|
||||
|
||||
Sentry.init(options -> {
|
||||
options.setDsn("https://b16ecc222e9c1e0c48faecacb906fd89@o4509451052646400.ingest.de.sentry.io/4509452722765904");
|
||||
if (settings.debug) {
|
||||
@ -55,6 +60,7 @@ public class Bindings {
|
||||
options.setAttachServerName(false);
|
||||
options.setEnableUncaughtExceptionHandler(false);
|
||||
options.setRelease(Iris.instance.getDescription().getVersion());
|
||||
options.setEnvironment(desc.getString("environment", "production"));
|
||||
options.setBeforeSend((event, hint) -> {
|
||||
if (suppress(event.getThrowable())) return null;
|
||||
event.setTag("iris.safeguard", IrisSafeguard.mode());
|
||||
@ -71,6 +77,7 @@ public class Bindings {
|
||||
scope.setTag("server", Bukkit.getVersion());
|
||||
scope.setTag("server.type", Bukkit.getName());
|
||||
scope.setTag("server.api", Bukkit.getBukkitVersion());
|
||||
scope.setTag("iris.commit", desc.getString("commit", "unknown"));
|
||||
});
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(Sentry::close));
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package com.volmit.iris.util.misc;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@ -22,12 +25,13 @@ public class ServerProperties {
|
||||
String bukkitYml = "bukkit.yml";
|
||||
String levelName = null;
|
||||
|
||||
for (int i = 0; i < args.length - 1; i++) {
|
||||
switch (args[i]) {
|
||||
case "-c", "--config" -> propertiesPath = args[i + 1];
|
||||
case "-b", "--bukkit-settings" -> bukkitYml = args[i + 1];
|
||||
case "-w", "--level-name", "--world" -> levelName = args[i + 1];
|
||||
}
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
String next = i < args.length - 1 ? args[i + 1] : null;
|
||||
|
||||
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);
|
||||
@ -41,4 +45,19 @@ public class ServerProperties {
|
||||
if (levelName != null) LEVEL_NAME = levelName;
|
||||
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,15 +1,32 @@
|
||||
package com.volmit.iris.util.misc;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.container.Pair;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import io.github.slimjar.app.builder.ApplicationBuilder;
|
||||
import io.github.slimjar.injector.loader.IsolatedInjectableClassLoader;
|
||||
import io.github.slimjar.injector.loader.factory.InjectableFactory;
|
||||
import io.github.slimjar.logging.ProcessLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SlimJar {
|
||||
private static final Logger LOGGER = Logger.getLogger("Iris");
|
||||
private static final String NAME = "Iris";
|
||||
private static final Logger LOGGER = Logger.getLogger(NAME);
|
||||
private static final 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 AtomicBoolean loaded = new AtomicBoolean();
|
||||
|
||||
@ -23,15 +40,85 @@ public class SlimJar {
|
||||
localRepository = new File(".iris/libraries");
|
||||
}
|
||||
|
||||
ApplicationBuilder.appending("Iris")
|
||||
.downloadDirectoryPath(localRepository.toPath())
|
||||
.logger((message, args) -> {
|
||||
if (!message.startsWith("Loaded library ")) return;
|
||||
LOGGER.info(message.formatted(args));
|
||||
})
|
||||
.build();
|
||||
LOGGER.info("Loading libraries...");
|
||||
load(localRepository.toPath(), new ProcessLogger() {
|
||||
@Override
|
||||
public void info(@NotNull String message, @Nullable Object... args) {
|
||||
if (!DEBUG) return;
|
||||
LOGGER.info(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) {
|
||||
if (!DEBUG) return;
|
||||
LOGGER.info(message.formatted(args));
|
||||
}
|
||||
});
|
||||
LOGGER.info("Libraries loaded successfully!");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void load(Path downloadPath, ProcessLogger logger) {
|
||||
try {
|
||||
loadSpigot(downloadPath, logger);
|
||||
} catch (Throwable e) {
|
||||
Iris.warn("Failed to inject the library loader, falling back to application builder");
|
||||
ApplicationBuilder.appending(NAME)
|
||||
.injectableFactory(InjectableFactory.selecting(InjectableFactory.ERROR, InjectableFactory.INJECTABLE, InjectableFactory.WRAPPED, InjectableFactory.UNSAFE))
|
||||
.downloadDirectoryPath(downloadPath)
|
||||
.logger(logger)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadSpigot(Path downloadPath, ProcessLogger logger) throws Throwable {
|
||||
var current = SlimJar.class.getClassLoader();
|
||||
var libraryLoaderField = current.getClass().getDeclaredField("libraryLoader");
|
||||
libraryLoaderField.setAccessible(true);
|
||||
if (!ClassLoader.class.isAssignableFrom(libraryLoaderField.getType())) throw new IllegalStateException("Failed to find library loader");
|
||||
final var libraryLoader = (ClassLoader) libraryLoaderField.get(current);
|
||||
|
||||
final var pair = findRemapper();
|
||||
final var remapper = pair.getA();
|
||||
final var factory = pair.getB();
|
||||
final var classpath = new KList<URL>();
|
||||
|
||||
ApplicationBuilder.injecting(NAME, classpath::add)
|
||||
.downloadDirectoryPath(downloadPath)
|
||||
.logger(logger)
|
||||
.build();
|
||||
|
||||
final var urls = remapper.andThen(KList::new)
|
||||
.apply(classpath.convertNasty(url -> Path.of(url.toURI())))
|
||||
.convertNasty(path -> path.toUri().toURL())
|
||||
.toArray(URL[]::new);
|
||||
libraryLoaderField.set(current, factory.apply(urls, libraryLoader == null ? current.getParent() : libraryLoader));
|
||||
}
|
||||
|
||||
private static Pair<Function<List<Path>, List<Path>>, BiFunction<URL[], ClassLoader, URLClassLoader>> findRemapper() {
|
||||
Function<List<Path>, List<Path>> mapper = null;
|
||||
BiFunction<URL[], ClassLoader, URLClassLoader> factory = null;
|
||||
if (!DISABLE_REMAPPER) {
|
||||
try {
|
||||
var libraryLoader = Class.forName("org.bukkit.plugin.java.LibraryLoader");
|
||||
var mapperField = libraryLoader.getDeclaredField("REMAPPER");
|
||||
var factoryField = libraryLoader.getDeclaredField("LIBRARY_LOADER_FACTORY");
|
||||
mapperField.setAccessible(true);
|
||||
factoryField.setAccessible(true);
|
||||
mapper = (Function<List<Path>, List<Path>>) mapperField.get(null);
|
||||
factory = (BiFunction<URL[], ClassLoader, URLClassLoader>) factoryField.get(null);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
if (mapper == null) mapper = Function.identity();
|
||||
if (factory == null) factory = (urls, parent) -> new IsolatedInjectableClassLoader(urls, List.of(), parent);
|
||||
return new Pair<>(mapper, factory);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.volmit.iris.util.parallel;
|
||||
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.scheduling.SR;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class SyncExecutor implements Executor, AutoCloseable {
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
private final Queue<Runnable> queue = new ConcurrentLinkedQueue<>();
|
||||
private final AtomicBoolean closed = new AtomicBoolean(false);
|
||||
|
||||
public SyncExecutor(int msPerTick) {
|
||||
new SR() {
|
||||
@Override
|
||||
public void run() {
|
||||
var time = M.ms() + msPerTick;
|
||||
while (time > M.ms()) {
|
||||
Runnable r = queue.poll();
|
||||
if (r == null) break;
|
||||
r.run();
|
||||
}
|
||||
|
||||
if (closed.get() && queue.isEmpty()) {
|
||||
cancel();
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Runnable command) {
|
||||
if (closed.get()) throw new IllegalStateException("Executor is closed!");
|
||||
queue.add(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
closed.set(true);
|
||||
latch.await();
|
||||
}
|
||||
}
|
@ -240,6 +240,21 @@ public class J {
|
||||
return f;
|
||||
}
|
||||
|
||||
public static <T> CompletableFuture<T> sfut(Supplier<T> r) {
|
||||
CompletableFuture<T> f = new CompletableFuture<>();
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled(Iris.instance)) {
|
||||
return null;
|
||||
}
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () -> {
|
||||
try {
|
||||
f.complete(r.get());
|
||||
} catch (Throwable e) {
|
||||
f.completeExceptionally(e);
|
||||
}
|
||||
});
|
||||
return f;
|
||||
}
|
||||
|
||||
public static CompletableFuture sfut(Runnable r, int delay) {
|
||||
CompletableFuture f = new CompletableFuture();
|
||||
|
||||
|
@ -5,6 +5,8 @@ load: STARTUP
|
||||
authors: [ cyberpwn, NextdoorPsycho, Vatuu ]
|
||||
website: volmit.com
|
||||
description: More than a Dimension!
|
||||
environment: '${environment}'
|
||||
commit: '${commit}'
|
||||
commands:
|
||||
iris:
|
||||
aliases: [ ir, irs ]
|
||||
|
@ -5,10 +5,11 @@
|
||||
[versions]
|
||||
# Plugins
|
||||
shadow = "9.0.0-rc1" # https://plugins.gradle.org/plugin/com.gradleup.shadow
|
||||
slimjar = "2.0.6" # https://plugins.gradle.org/plugin/de.crazydev22.slimjar
|
||||
slimjar = "2.1.2" # https://plugins.gradle.org/plugin/de.crazydev22.slimjar
|
||||
download = "5.6.0" # https://plugins.gradle.org/plugin/de.undercouch.download
|
||||
runPaper = "2.3.1" # https://plugins.gradle.org/plugin/xyz.jpenilla.run-paper
|
||||
sentryPlugin = "5.8.0" # https://github.com/getsentry/sentry-android-gradle-plugin
|
||||
grgit = "5.3.2" # https://github.com/ajoberstar/grgit
|
||||
|
||||
# Core Libraries
|
||||
lombok = "1.18.38"
|
||||
@ -116,3 +117,4 @@ runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" }
|
||||
sentry = { id = "io.sentry.jvm.gradle", version.ref = "sentryPlugin" }
|
||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||
kotlin-lombok = { id = "org.jetbrains.kotlin.plugin.lombok", version.ref = "kotlin" }
|
||||
grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" }
|
||||
|
Loading…
x
Reference in New Issue
Block a user