9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-23 00:59:16 +00:00

Compare commits

..

40 Commits

Author SHA1 Message Date
Julian Krings
3a74164627 implement priority to static placement component 2025-01-08 13:53:33 +01:00
Julian Krings
894de013dd Merge branch 'dev' into feat/static_placements
# Conflicts:
#	core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java
2025-01-08 13:03:30 +01:00
Julian Krings
e1a7e772cf fix floating objects (#1134) 2025-01-07 22:03:53 +01:00
Aidan Aeternum
3c6411c322 v+ 2025-01-07 11:22:52 -08:00
Aidan Aeternum
628761affa Merge pull request #1130 from VolmitSoftware/dev
3.5.2
2025-01-07 11:21:06 -08:00
Julian Krings
9a81905fdd implement static placements for structures and objects 2025-01-06 01:48:11 +01:00
Julian Krings
fa7b0f68ff Merge pull request #1129 from VolmitSoftware/feat/deposits
Feat/deposits
2025-01-05 16:25:03 +01:00
Aidan Aeternum
487d0ac237 Merge pull request #1128 from VolmitSoftware/dev
3.5.1
2025-01-04 09:57:30 -08:00
Julian Krings
e79e3fbe45 implement <1 deposit spawn chance 2025-01-04 03:46:08 +01:00
Julian Krings
23a0ab23aa fixes to deposit clump generation and placement 2025-01-04 03:41:55 +01:00
Julian Krings
c78ffab948 fix deposit clump calculation 2025-01-03 00:33:49 +01:00
Julian Krings
d58f497b71 v+ 2025-01-02 23:21:32 +01:00
Julian Krings
3284ab84c5 fix biome&region deposits being placed ^2 2025-01-02 23:15:27 +01:00
Julian Krings
5cf0ac9315 Merge pull request #1115 from VolmitSoftware/v3.4.3
V3.5.0
2025-01-02 19:37:22 +01:00
Julian Krings
4e4e820826 update overworld tag and make first setup use the tag rather than current codebase 2025-01-02 14:38:45 +01:00
Julian Krings
cb6e4570f4 add fallback loot mode 2025-01-02 13:28:20 +01:00
Julian Krings
fb59c7370d partially revert commit c93cb19563 2025-01-02 12:33:59 +01:00
Julian Krings
c16e65f0a8 add force place option to IrisJigsawStructure 2025-01-02 12:33:59 +01:00
Julian Krings
d9681edf62 relocate IrisLootEvent to the proper package 2025-01-02 12:33:59 +01:00
repix
520c156d5f Repix gradle update 2024-12-29 16:47:09 +01:00
Julian Krings
5c26ec2521 fix vanilla loottables not applying 2024-12-28 00:43:01 +01:00
Julian Krings
d192e2b6d1 add tabcomplete for vanilla loottables and fix some multi version compat 2024-12-27 18:14:29 +01:00
Julian Krings
5b60b655ed some more optimizations 2024-12-26 17:54:02 +01:00
Julian Krings
97c7ac0528 some more bstats metrics 2024-12-26 11:22:06 +01:00
Julian Krings
090ff730a7 remove item type caching for schemas 2024-12-24 10:09:22 +01:00
Julian Krings
c1f797e7c9 update bstats 2024-12-23 23:37:01 +01:00
Julian Krings
4a1a6b80a6 minor performance increase 2024-12-23 23:36:25 +01:00
Julian Krings
e189b2389c add vanilla loottables 2024-12-22 16:39:41 +01:00
Julian Krings
3265447536 woops 2024-12-14 16:43:42 +01:00
Julian Krings
8c7c9f89e1 add missing nullability annotations to data providers 2024-12-14 16:42:01 +01:00
Julian Krings
d7a991b9b3 fix NexoDataProvider 2024-12-14 16:40:04 +01:00
Julian Krings
abf6c93f2e allow custom data provider registration 2024-12-14 16:39:41 +01:00
Julian Krings
1b76a66760 update iris core to jdk 21 2024-12-14 16:23:29 +01:00
RePixelatedMC
c83ac67b47 New features 2024-12-05 10:28:04 +01:00
Julian Krings
1dca502a90 add more safety to mantle 2024-11-27 19:45:08 +01:00
Julian Krings
cacef8c8fc add legacy tile data reader 2024-11-25 20:05:21 +01:00
Julian Krings
623fd45ef4 fixes to nexo support 2024-11-24 19:00:51 +01:00
Julian Krings
007b4b0b53 whoops 2024-11-23 21:09:54 +01:00
Julian Krings
b6bacee095 replace Oraxen with Nexo support 2024-11-23 21:03:14 +01:00
Julian Krings
d5251350a1 initial 1.21.3 support 2024-11-16 20:19:28 +01:00
142 changed files with 4158 additions and 6508 deletions

View File

@@ -32,7 +32,7 @@ plugins {
id "de.undercouch.download" version "5.0.1" id "de.undercouch.download" version "5.0.1"
} }
version '3.4.3-1.19.2-1.21.1' version '3.5.2-1.19.2-1.21.3'
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED // ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
// ======================== WINDOWS ============================= // ======================== WINDOWS =============================
@@ -43,8 +43,8 @@ registerCustomOutputTask('Coco', 'D://mcsm/plugins')
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins') registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins') registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins') registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
registerCustomOutputTask('Pixel', 'D://Iris Dimension Engine/1.20.4 - Development/plugins') registerCustomOutputTask('PixelFury', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins')
registerCustomOutputTask('PixelFury', 'C://Users/RePixelatedMC/Iris/1.21 - Development-v3/plugins') registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins')
// ========================== UNIX ============================== // ========================== UNIX ==============================
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins') registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins') registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
@@ -53,6 +53,7 @@ registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugin
// ============================================================== // ==============================================================
def NMS_BINDINGS = Map.of( def NMS_BINDINGS = Map.of(
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
"v1_21_R1", "1.21.1-R0.1-SNAPSHOT", "v1_21_R1", "1.21.1-R0.1-SNAPSHOT",
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT", "v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT", "v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
@@ -62,17 +63,14 @@ def NMS_BINDINGS = Map.of(
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT", "v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT" "v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
) )
def JVM_VERSION = Map.of( def JVM_VERSION = Map.of()
"v1_21_R1", 21,
"v1_20_R4", 21,
)
NMS_BINDINGS.each { nms -> NMS_BINDINGS.each { nms ->
project(":nms:${nms.key}") { project(":nms:${nms.key}") {
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'com.volmit.nmstools' apply plugin: 'com.volmit.nmstools'
nmsTools { nmsTools {
it.jvm = JVM_VERSION.getOrDefault(nms.key, 17) it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
it.version = nms.value it.version = nms.value
} }
@@ -93,6 +91,7 @@ shadowJar {
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic' relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper' relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
relocate 'net.kyori', 'com.volmit.iris.util.kyori' relocate 'net.kyori', 'com.volmit.iris.util.kyori'
relocate 'org.bstats', 'com.volmit.util.metrics'
archiveFileName.set("Iris-${project.version}.jar") archiveFileName.set("Iris-${project.version}.jar")
} }
@@ -120,13 +119,14 @@ allprojects {
maven { url "https://repo.triumphteam.dev/snapshots" } maven { url "https://repo.triumphteam.dev/snapshots" }
maven { url "https://repo.mineinabyss.com/releases" } maven { url "https://repo.mineinabyss.com/releases" }
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' } maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
maven { url "https://repo.oraxen.com/releases" } maven { url "https://repo.nexomc.com/snapshots/" }
maven { url "https://libraries.minecraft.net" }
} }
dependencies { dependencies {
// Provided or Classpath // Provided or Classpath
compileOnly 'org.projectlombok:lombok:1.18.24' compileOnly 'org.projectlombok:lombok:1.18.36'
annotationProcessor 'org.projectlombok:lombok:1.18.24' annotationProcessor 'org.projectlombok:lombok:1.18.36'
// Shaded // Shaded
implementation 'com.dfsek:Paralithic:0.4.0' implementation 'com.dfsek:Paralithic:0.4.0'
@@ -134,6 +134,7 @@ allprojects {
implementation "net.kyori:adventure-text-minimessage:4.17.0" implementation "net.kyori:adventure-text-minimessage:4.17.0"
implementation 'net.kyori:adventure-platform-bukkit:4.3.4' implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
implementation 'net.kyori:adventure-api:4.17.0' implementation 'net.kyori:adventure-api:4.17.0'
implementation 'org.bstats:bstats-bukkit:3.1.0'
//implementation 'org.bytedeco:javacpp:1.5.10' //implementation 'org.bytedeco:javacpp:1.5.10'
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10' //implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
compileOnly 'io.lumine:Mythic-Dist:5.2.1' compileOnly 'io.lumine:Mythic-Dist:5.2.1'
@@ -151,6 +152,7 @@ allprojects {
compileOnly 'rhino:js:1.7R2' compileOnly 'rhino:js:1.7R2'
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6' compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
compileOnly 'org.apache.commons:commons-lang3:3.12.0' compileOnly 'org.apache.commons:commons-lang3:3.12.0'
compileOnly 'com.github.oshi:oshi-core:6.6.5'
} }
/** /**
@@ -177,18 +179,18 @@ allprojects {
} }
} }
if (JavaVersion.current().toString() != "17") { if (JavaVersion.current().toString() != "21") {
System.err.println() System.err.println()
System.err.println("=========================================================================================================") System.err.println("=========================================================================================================")
System.err.println("You must run gradle on Java 17. You are using " + JavaVersion.current()) System.err.println("You must run gradle on Java 21. You are using " + JavaVersion.current())
System.err.println() System.err.println()
System.err.println("=== For IDEs ===") System.err.println("=== For IDEs ===")
System.err.println("1. Configure the project for Java 17") System.err.println("1. Configure the project for Java 21")
System.err.println("2. Configure the bundled gradle to use Java 17 in settings") System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
System.err.println() System.err.println()
System.err.println("=== For Command Line (gradlew) ===") System.err.println("=== For Command Line (gradlew) ===")
System.err.println("1. Install JDK 17 from https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html") System.err.println("1. Install JDK 21 from https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html")
System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-17.0.1") System.err.println("2. Set JAVA_HOME environment variable to the new jdk installation folder such as C:\\Program Files\\Java\\jdk-21.0.4")
System.err.println("3. Open a new command prompt window to get the new environment variables if need be.") System.err.println("3. Open a new command prompt window to get the new environment variables if need be.")
System.err.println("=========================================================================================================") System.err.println("=========================================================================================================")
System.err.println() System.err.println()

View File

@@ -55,14 +55,14 @@ dependencies {
compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
compileOnly 'org.apache.logging.log4j:log4j-api:2.19.0' compileOnly 'org.apache.logging.log4j:log4j-api:2.19.0'
compileOnly 'org.apache.logging.log4j:log4j-core:2.19.0' compileOnly 'org.apache.logging.log4j:log4j-core:2.19.0'
compileOnly 'commons-io:commons-io:2.14.0' compileOnly 'commons-io:commons-io:2.13.0'
compileOnly 'commons-lang:commons-lang:2.6' compileOnly 'commons-lang:commons-lang:2.6'
compileOnly 'com.github.oshi:oshi-core:5.8.5' compileOnly 'com.github.oshi:oshi-core:5.8.5'
compileOnly 'org.lz4:lz4-java:1.8.0' compileOnly 'org.lz4:lz4-java:1.8.0'
// Third Party Integrations // Third Party Integrations
compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7' compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
compileOnly 'io.th0rgal:oraxen:1.173.0' compileOnly 'com.nexomc:nexo:0.6.0-dev.0'
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4' compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3' compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8' compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
@@ -71,6 +71,9 @@ dependencies {
//implementation files('libs/CustomItems.jar') //implementation files('libs/CustomItems.jar')
} }
java {
disableAutoTargetJvm()
}
/** /**
* Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly. * Gradle is weird sometimes, we need to delete the plugin yml from the build folder to actually filter properly.

View File

@@ -40,6 +40,7 @@ import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.platform.DummyChunkGenerator; import com.volmit.iris.engine.platform.DummyChunkGenerator;
import com.volmit.iris.core.safeguard.IrisSafeguard; import com.volmit.iris.core.safeguard.IrisSafeguard;
import com.volmit.iris.core.safeguard.UtilsSFG; import com.volmit.iris.core.safeguard.UtilsSFG;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.exceptions.IrisException; import com.volmit.iris.util.exceptions.IrisException;
@@ -55,7 +56,6 @@ import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.getHardware; import com.volmit.iris.util.misc.getHardware;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.IrisService; import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.Metrics;
import com.volmit.iris.util.plugin.VolmitPlugin; import com.volmit.iris.util.plugin.VolmitPlugin;
import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.reflect.ShadeFix; import com.volmit.iris.util.reflect.ShadeFix;
@@ -63,13 +63,13 @@ import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Queue; import com.volmit.iris.util.scheduling.Queue;
import com.volmit.iris.util.scheduling.ShurikenQueue; import com.volmit.iris.util.scheduling.ShurikenQueue;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import lombok.Getter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.serializer.ComponentSerializer; import net.kyori.adventure.text.serializer.ComponentSerializer;
import org.bukkit.Bukkit; import org.bstats.bukkit.Metrics;
import org.bukkit.GameMode; import org.bstats.charts.DrilldownPie;
import org.bukkit.Location; import org.bstats.charts.SimplePie;
import org.bukkit.WorldCreator; import org.bstats.charts.SingleLineChart;
import org.bukkit.*;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -77,34 +77,31 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.event.*;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.IllegalPluginAccessException; import org.bukkit.plugin.IllegalPluginAccessException;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import oshi.SystemInfo;
import java.io.*; import java.io.*;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory; import java.math.RoundingMode;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.net.URL; import java.net.URL;
import java.util.Date; import java.text.NumberFormat;
import java.util.Map; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.volmit.iris.core.safeguard.IrisSafeguard.*; import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware; import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
@SuppressWarnings("CanBeFinal") @SuppressWarnings("CanBeFinal")
public class Iris extends VolmitPlugin implements Listener { public class Iris extends VolmitPlugin implements Listener {
public static final String OVERWORLD_TAG = "3800"; public static final String OVERWORLD_TAG = "31000";
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>(); private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
@@ -513,11 +510,10 @@ public class Iris extends VolmitPlugin implements Listener {
continue; continue;
} }
Iris.info("2 World: %s | Generator: %s", s, generator); if (Bukkit.getWorld(s) != null)
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
continue; continue;
}
Iris.info("Loading World: %s | Generator: %s", s, generator);
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "..."); Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
new WorldCreator(s) new WorldCreator(s)
@@ -665,7 +661,48 @@ public class Iris extends VolmitPlugin implements Listener {
private void bstats() { private void bstats() {
if (IrisSettings.get().getGeneral().isPluginMetrics()) { if (IrisSettings.get().getGeneral().isPluginMetrics()) {
J.s(() -> new Metrics(Iris.instance, 8757)); J.s(() -> {
var metrics = new Metrics(Iris.instance, 24220);
metrics.addCustomChart(new SingleLineChart("custom_dimensions", () -> Bukkit.getWorlds()
.stream()
.filter(IrisToolbelt::isIrisWorld)
.mapToInt(w -> 1)
.sum()));
metrics.addCustomChart(new DrilldownPie("used_packs", () -> Bukkit.getWorlds().stream()
.map(IrisToolbelt::access)
.filter(Objects::nonNull)
.map(PlatformChunkGenerator::getTarget)
.collect(Collectors.toMap(target -> target.getDimension().getLoadKey(), target -> {
int version = target.getDimension().getVersion();
String checksum = IO.hashRecursive(target.getData().getDataFolder());
return Map.of("v" + version + " (" + checksum + ")", 1);
}, (a, b) -> {
Map<String, Integer> merged = new HashMap<>(a);
b.forEach((k, v) -> merged.merge(k, v, Integer::sum));
return merged;
}))));
var info = new SystemInfo().getHardware();
var cpu = info.getProcessor().getProcessorIdentifier();
var mem = info.getMemory();
metrics.addCustomChart(new SimplePie("cpu_model", cpu::getName));
var nf = NumberFormat.getInstance(Locale.ENGLISH);
nf.setMinimumFractionDigits(0);
nf.setMaximumFractionDigits(2);
nf.setRoundingMode(RoundingMode.HALF_UP);
metrics.addCustomChart(new DrilldownPie("memory", () -> {
double total = mem.getTotal() * 1E-9;
double alloc = Math.min(total, Runtime.getRuntime().maxMemory() * 1E-9);
return Map.of(nf.format(alloc), Map.of(nf.format(total), 1));
}));
postShutdown.add(metrics::shutdown);
});
} }
} }
@@ -812,22 +849,6 @@ public class Iris extends VolmitPlugin implements Listener {
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion()); Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); } } else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
Iris.info("Java: " + getJava()); Iris.info("Java: " + getJava());
try {
if (getCPUModel().contains("Intel")) {
Iris.info("Server Cpu: " + C.BLUE + getCPUModel());
}
if (getCPUModel().contains("Ryzen")) {
Iris.info("Server Cpu: " + C.RED + getCPUModel());
}
if (!getCPUModel().contains("Ryzen") && !getCPUModel().contains("Intel")) {
Iris.info("Server Cpu: " + C.GRAY + getCPUModel());
}
} catch (Exception e){
Iris.info("Server Cpu: " + C.DARK_RED + "Failed");
}
Iris.info("Threads: " + C.GRAY + Runtime.getRuntime().availableProcessors());
if (!instance.getServer().getVersion().contains("Purpur")) { if (!instance.getServer().getVersion().contains("Purpur")) {
if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) { if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) {
Iris.info(C.RED + " Iris requires paper or above to function properly.."); Iris.info(C.RED + " Iris requires paper or above to function properly..");

View File

@@ -47,8 +47,6 @@ public class IrisSettings {
private IrisSettingsUpdater updater = new IrisSettingsUpdater(); private IrisSettingsUpdater updater = new IrisSettingsUpdater();
public static int getThreadCount(int c) { public static int getThreadCount(int c) {
if (System.getProperty("os.name").toLowerCase().contains("win"))
return Runtime.getRuntime().availableProcessors();
return switch (c) { return switch (c) {
case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c; case -1, -2, -4 -> Runtime.getRuntime().availableProcessors() / -c;
case 0, 1, 2 -> 1; case 0, 1, 2 -> 1;
@@ -137,7 +135,6 @@ public class IrisSettings {
@Data @Data
public static class IrisSettingsConcurrency { public static class IrisSettingsConcurrency {
public int parallelism = -1; public int parallelism = -1;
public boolean windowsFullPerformance = true;
} }
@Data @Data

View File

@@ -0,0 +1,134 @@
/*
* 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.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.DeepSearchPregenerator;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.pregenerator.TurboPregenerator;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.data.Dimension;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Position2;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.IOException;
@Decree(name = "DeepSearch", aliases = "search", description = "Pregenerate your Iris worlds!")
public class CommandDeepSearch implements DecreeExecutor {
public String worldName;
@Decree(description = "DeepSearch a world")
public void start(
@Param(description = "The radius of the pregen in blocks", aliases = "size")
int radius,
@Param(description = "The world to pregen", contextual = true)
World world,
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
Vector center
) {
worldName = world.getName();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File TurboFile = new File(worldDirectory, "DeepSearch.json");
if (TurboFile.exists()) {
if (DeepSearchPregenerator.getInstance() != null) {
sender().sendMessage(C.BLUE + "DeepSearch is already in progress");
Iris.info(C.YELLOW + "DeepSearch is already in progress");
return;
} else {
try {
TurboFile.delete();
} catch (Exception e){
Iris.error("Failed to delete the old instance file of DeepSearch!");
return;
}
}
}
try {
if (sender().isPlayer() && access() == null) {
sender().sendMessage(C.RED + "The engine access for this world is null!");
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
}
DeepSearchPregenerator.DeepSearchJob DeepSearchJob = DeepSearchPregenerator.DeepSearchJob.builder()
.world(world)
.radiusBlocks(radius)
.position(0)
.build();
File SearchGenFile = new File(worldDirectory, "DeepSearch.json");
DeepSearchPregenerator pregenerator = new DeepSearchPregenerator(DeepSearchJob, SearchGenFile);
pregenerator.start();
String msg = C.GREEN + "DeepSearch started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
sender().sendMessage(msg);
Iris.info(msg);
} catch (Throwable e) {
sender().sendMessage(C.RED + "Epic fail. See console.");
Iris.reportError(e);
e.printStackTrace();
}
}
@Decree(description = "Stop the active DeepSearch task", aliases = "x")
public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
DeepSearchPregenerator DeepSearchInstance = DeepSearchPregenerator.getInstance();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File turboFile = new File(worldDirectory, "DeepSearch.json");
if (DeepSearchInstance != null) {
DeepSearchInstance.shutdownInstance(world);
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
} else if (turboFile.exists() && turboFile.delete()) {
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
} else if (turboFile.exists()) {
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
} else {
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
}
}
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
public void pause(
@Param(aliases = "world", description = "The world to pause")
World world
) {
if (TurboPregenerator.getInstance() != null) {
TurboPregenerator.setPausedTurbo(world);
sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
} else {
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File TurboFile = new File(worldDirectory, "DeepSearch.json");
if (TurboFile.exists()){
TurboPregenerator.loadTurboGenerator(world.getName());
sender().sendMessage(C.YELLOW + "Started DeepSearch back up!");
} else {
sender().sendMessage(C.YELLOW + "No active DeepSearch tasks to pause/unpause.");
}
}
}
}

View File

@@ -21,12 +21,10 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.ServerConfigurator; import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.DataVersion; import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.service.IrisEngineSVC; import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisPackBenchmarking; import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.core.tools.IrisWorldAnalytics;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension; import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.decree.DecreeExecutor; import com.volmit.iris.util.decree.DecreeExecutor;
@@ -35,6 +33,7 @@ import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param; import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.CountingDataInputStream;
import com.volmit.iris.util.io.IO; import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.TectonicPlate; import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.nbt.mca.MCAFile; import com.volmit.iris.util.nbt.mca.MCAFile;
@@ -46,7 +45,9 @@ import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4FrameInputStream; import net.jpountz.lz4.LZ4FrameInputStream;
import net.jpountz.lz4.LZ4FrameOutputStream; import net.jpountz.lz4.LZ4FrameOutputStream;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.*; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import java.io.*; import java.io.*;
import java.net.InetAddress; import java.net.InetAddress;
@@ -60,6 +61,7 @@ import java.util.zip.GZIPOutputStream;
@Decree(name = "Developer", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"dev"}) @Decree(name = "Developer", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"dev"})
public class CommandDeveloper implements DecreeExecutor { public class CommandDeveloper implements DecreeExecutor {
private CommandTurboPregen turboPregen;
private CommandUpdater updater; private CommandUpdater updater;
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true) @Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
@@ -136,23 +138,14 @@ public class CommandDeveloper implements DecreeExecutor {
@Decree(description = "Test") @Decree(description = "Test")
public void packBenchmark( public void packBenchmark(
@Param(description = "The pack to bench", aliases = {"pack"}) @Param(description = "The pack to bench", aliases = {"pack"}, defaultValue = "overworld")
IrisDimension dimension IrisDimension dimension,
@Param(description = "Radius in regions", defaultValue = "5")
int radius,
@Param(description = "Open GUI while benchmarking", defaultValue = "false")
boolean gui
) { ) {
Iris.info("test"); new IrisPackBenchmarking(dimension, radius, gui);
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1);
}
@Decree(description = "gets wg height")
public void whatHeight() {
Iris.info("test");
sender().sendMessage("Height: " + player().getWorld().getHighestBlockAt(player().getLocation(), HeightMap.MOTION_BLOCKING).getY());
}
@Decree(description = "check", aliases = {"ck"} )
public void check() {
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
} }
@Decree(description = "Upgrade to another Minecraft version") @Decree(description = "Upgrade to another Minecraft version")
@@ -170,7 +163,6 @@ public class CommandDeveloper implements DecreeExecutor {
File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca")); File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca"));
for (File mca : McaFiles) { for (File mca : McaFiles) {
MCAFile MCARegion = MCAUtil.read(mca); MCAFile MCARegion = MCAUtil.read(mca);
int i = 0;
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -178,19 +170,6 @@ public class CommandDeveloper implements DecreeExecutor {
} }
@Decree(description = "test")
public void anl (
@Param(description = "String") String world) {
try {
IrisWorldAnalytics a = new IrisWorldAnalytics(world);
a.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
@Decree(description = "UnloadChunks for good reasons.") @Decree(description = "UnloadChunks for good reasons.")
public void unloadchunks() { public void unloadchunks() {
List<World> IrisWorlds = new ArrayList<>(); List<World> IrisWorlds = new ArrayList<>();
@@ -271,7 +250,7 @@ public class CommandDeveloper implements DecreeExecutor {
VolmitSender sender = sender(); VolmitSender sender = sender();
service.submit(() -> { service.submit(() -> {
try { try {
DataInputStream raw = new DataInputStream(new FileInputStream(file)); CountingDataInputStream raw = CountingDataInputStream.wrap(new FileInputStream(file));
TectonicPlate plate = new TectonicPlate(height, raw); TectonicPlate plate = new TectonicPlate(height, raw);
raw.close(); raw.close();
@@ -290,7 +269,7 @@ public class CommandDeveloper implements DecreeExecutor {
if (size == 0) if (size == 0)
size = tmp.length(); size = tmp.length();
start = System.currentTimeMillis(); start = System.currentTimeMillis();
DataInputStream din = createInput(tmp, algorithm); CountingDataInputStream din = createInput(tmp, algorithm);
new TectonicPlate(height, din); new TectonicPlate(height, din);
din.close(); din.close();
d2 += System.currentTimeMillis() - start; d2 += System.currentTimeMillis() - start;
@@ -310,10 +289,10 @@ public class CommandDeveloper implements DecreeExecutor {
} }
} }
private DataInputStream createInput(File file, String algorithm) throws Throwable { private CountingDataInputStream createInput(File file, String algorithm) throws Throwable {
FileInputStream in = new FileInputStream(file); FileInputStream in = new FileInputStream(file);
return new DataInputStream(switch (algorithm) { return CountingDataInputStream.wrap(switch (algorithm) {
case "gzip" -> new GZIPInputStream(in); case "gzip" -> new GZIPInputStream(in);
case "lz4f" -> new LZ4FrameInputStream(in); case "lz4f" -> new LZ4FrameInputStream(in);
case "lz4b" -> new LZ4BlockInputStream(in); case "lz4b" -> new LZ4BlockInputStream(in);

View File

@@ -73,12 +73,14 @@ import static org.bukkit.Bukkit.getServer;
public class CommandIris implements DecreeExecutor { public class CommandIris implements DecreeExecutor {
private CommandStudio studio; private CommandStudio studio;
private CommandPregen pregen; private CommandPregen pregen;
private CommandLazyPregen lazyPregen;
private CommandSettings settings; private CommandSettings settings;
private CommandObject object; private CommandObject object;
private CommandJigsaw jigsaw; private CommandJigsaw jigsaw;
private CommandWhat what; private CommandWhat what;
private CommandEdit edit; private CommandEdit edit;
private CommandFind find; private CommandFind find;
private CommandSupport support;
private CommandDeveloper developer; private CommandDeveloper developer;
public static boolean worldCreation = false; public static boolean worldCreation = false;
String WorldEngine; String WorldEngine;

View File

@@ -0,0 +1,121 @@
/*
* 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.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.gui.PregeneratorJob;
import com.volmit.iris.core.pregenerator.LazyPregenerator;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Position2;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.IOException;
@Decree(name = "lazypregen", aliases = "lazy", description = "Pregenerate your Iris worlds!")
public class CommandLazyPregen implements DecreeExecutor {
public String worldName;
@Decree(description = "Pregenerate a world")
public void start(
@Param(description = "The radius of the pregen in blocks", aliases = "size")
int radius,
@Param(description = "The world to pregen", contextual = true)
World world,
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
Vector center,
@Param(aliases = "maxcpm", description = "Limit the chunks per minute the pregen will generate", defaultValue = "999999999")
int cpm,
@Param(aliases = "silent", description = "Silent generation", defaultValue = "false")
boolean silent
) {
worldName = world.getName();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File lazyFile = new File(worldDirectory, "lazygen.json");
if (lazyFile.exists()) {
sender().sendMessage(C.BLUE + "Lazy pregen is already in progress");
Iris.info(C.YELLOW + "Lazy pregen is already in progress");
return;
}
try {
if (sender().isPlayer() && access() == null) {
sender().sendMessage(C.RED + "The engine access for this world is null!");
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
}
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
.world(worldName)
.healingPosition(0)
.healing(false)
.chunksPerMinute(cpm)
.radiusBlocks(radius)
.position(0)
.silent(silent)
.build();
File lazyGenFile = new File(worldDirectory, "lazygen.json");
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, lazyGenFile);
pregenerator.start();
String msg = C.GREEN + "LazyPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
sender().sendMessage(msg);
Iris.info(msg);
} catch (Throwable e) {
sender().sendMessage(C.RED + "Epic fail. See console.");
Iris.reportError(e);
e.printStackTrace();
}
}
@Decree(description = "Stop the active pregeneration task", aliases = "x")
public void stop(
@Param(aliases = "world", description = "The world to pause")
World world
) throws IOException {
if (LazyPregenerator.getInstance() != null) {
LazyPregenerator.getInstance().shutdownInstance(world);
sender().sendMessage(C.LIGHT_PURPLE + "Closed lazygen instance for " + world.getName());
} else {
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
}
}
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
public void pause(
@Param(aliases = "world", description = "The world to pause")
World world
) {
if (LazyPregenerator.getInstance() != null) {
LazyPregenerator.getInstance().setPausedLazy(world);
sender().sendMessage(C.GREEN + "Paused/unpaused Lazy Pregen, now: " + (LazyPregenerator.getInstance().isPausedLazy(world) ? "Paused" : "Running") + ".");
} else {
sender().sendMessage(C.YELLOW + "No active Lazy Pregen tasks to pause/unpause.");
}
}
}

View File

@@ -376,9 +376,11 @@ public class CommandObject implements DecreeExecutor {
@Param(description = "The file to store it in, can use / for subfolders") @Param(description = "The file to store it in, can use / for subfolders")
String name, String name,
@Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force") @Param(description = "Overwrite existing object files", defaultValue = "false", aliases = "force")
boolean overwrite boolean overwrite,
@Param(description = "Use legacy TileState serialization if possible", defaultValue = "true")
boolean legacy
) { ) {
IrisObject o = WandSVC.createSchematic(player()); IrisObject o = WandSVC.createSchematic(player(), legacy);
if (o == null) { if (o == null) {
sender().sendMessage(C.YELLOW + "You need to hold your wand!"); sender().sendMessage(C.YELLOW + "You need to hold your wand!");

View File

@@ -26,7 +26,6 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.project.IrisProject; import com.volmit.iris.core.project.IrisProject;
import com.volmit.iris.core.service.ConversionSVC; import com.volmit.iris.core.service.ConversionSVC;
import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisConverter;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.object.*;
@@ -55,7 +54,6 @@ import com.volmit.iris.util.noise.CNG;
import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.O; import com.volmit.iris.util.scheduling.O;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
@@ -64,7 +62,6 @@ import io.papermc.lib.PaperLib;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.BlockVector; import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@@ -79,7 +76,6 @@ import java.time.temporal.ChronoUnit;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@@ -176,7 +172,7 @@ public class CommandStudio implements DecreeExecutor {
KList<Runnable> js = new KList<>(); KList<Runnable> js = new KList<>();
BurstExecutor b = MultiBurst.burst.burst(); BurstExecutor b = MultiBurst.burst.burst();
b.setMulticore(false); b.setMulticore(false);
int rad = engine.getMantle().getRealRadius(); int rad = engine.getMantle().getRadius();
for (int i = -(radius + rad); i <= radius + rad; i++) { for (int i = -(radius + rad); i <= radius + rad; i++) {
for (int j = -(radius + rad); j <= radius + rad; j++) { for (int j = -(radius + rad); j <= radius + rad; j++) {
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ()); engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());

View File

@@ -0,0 +1,82 @@
/*
* 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.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.misc.Hastebin;
import com.volmit.iris.util.misc.Platform;
import com.volmit.iris.util.misc.getHardware;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.plugin.VolmitSender;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4FrameInputStream;
import net.jpountz.lz4.LZ4FrameOutputStream;
import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import oshi.SystemInfo;
import java.io.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@Decree(name = "Support", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"support"})
public class CommandSupport implements DecreeExecutor {
@Decree(description = "report")
public void report() {
try {
if (sender().isPlayer()) sender().sendMessage(C.GOLD + "Creating report..");
if (!sender().isPlayer()) Iris.info(C.GOLD + "Creating report..");
Hastebin.enviornment(sender());
} catch (Exception e) {
Iris.info(C.RED + "Something went wrong: ");
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* 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.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.LazyPregenerator;
import com.volmit.iris.core.pregenerator.TurboPregenerator;
import com.volmit.iris.core.pregenerator.TurboPregenerator;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.IOException;
@Decree(name = "turbopregen", aliases = "turbo", description = "Pregenerate your Iris worlds!")
public class CommandTurboPregen implements DecreeExecutor {
public String worldName;
@Decree(description = "Pregenerate a world")
public void start(
@Param(description = "The radius of the pregen in blocks", aliases = "size")
int radius,
@Param(description = "The world to pregen", contextual = true)
World world,
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
Vector center
) {
worldName = world.getName();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File TurboFile = new File(worldDirectory, "turbogen.json");
if (TurboFile.exists()) {
if (TurboPregenerator.getInstance() != null) {
sender().sendMessage(C.BLUE + "Turbo pregen is already in progress");
Iris.info(C.YELLOW + "Turbo pregen is already in progress");
return;
} else {
try {
TurboFile.delete();
} catch (Exception e){
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
return;
}
}
}
try {
if (sender().isPlayer() && access() == null) {
sender().sendMessage(C.RED + "The engine access for this world is null!");
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
}
TurboPregenerator.TurboPregenJob pregenJob = TurboPregenerator.TurboPregenJob.builder()
.world(worldName)
.radiusBlocks(radius)
.position(0)
.build();
File TurboGenFile = new File(worldDirectory, "turbogen.json");
TurboPregenerator pregenerator = new TurboPregenerator(pregenJob, TurboGenFile);
pregenerator.start();
String msg = C.GREEN + "TurboPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
sender().sendMessage(msg);
Iris.info(msg);
} catch (Throwable e) {
sender().sendMessage(C.RED + "Epic fail. See console.");
Iris.reportError(e);
e.printStackTrace();
}
}
@Decree(description = "Stop the active pregeneration task", aliases = "x")
public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException {
TurboPregenerator turboPregenInstance = TurboPregenerator.getInstance();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File turboFile = new File(worldDirectory, "turbogen.json");
if (turboPregenInstance != null) {
turboPregenInstance.shutdownInstance(world);
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
} else if (turboFile.exists() && turboFile.delete()) {
sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName());
} else if (turboFile.exists()) {
Iris.error("Failed to delete the old instance file of Turbo Pregen!");
} else {
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
}
}
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
public void pause(
@Param(aliases = "world", description = "The world to pause")
World world
) {
if (TurboPregenerator.getInstance() != null) {
TurboPregenerator.setPausedTurbo(world);
sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + ".");
} else {
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File TurboFile = new File(worldDirectory, "turbogen.json");
if (TurboFile.exists()){
TurboPregenerator.loadTurboGenerator(world.getName());
sender().sendMessage(C.YELLOW + "Started Turbo Pregen back up!");
} else {
sender().sendMessage(C.YELLOW + "No active Turbo Pregen tasks to pause/unpause.");
}
}
}
}

View File

@@ -1,14 +1,13 @@
package com.volmit.iris.engine.framework; package com.volmit.iris.core.events;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.InventorySlotType; import com.volmit.iris.engine.object.InventorySlotType;
import com.volmit.iris.engine.object.IrisLootTable; import com.volmit.iris.engine.object.IrisLootTable;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.scheduling.J;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.*;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
@@ -19,28 +18,38 @@ import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootContext; import org.bukkit.loot.LootContext;
import org.bukkit.loot.LootTable; import org.bukkit.loot.LootTable;
import org.bukkit.loot.LootTables; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Random;
@Getter @Getter
public class IrisLootEvent extends Event { public class IrisLootEvent extends Event {
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
private static final LootTable EMPTY = new LootTable() {
@NotNull
@Override
public NamespacedKey getKey() {
return new NamespacedKey(Iris.instance, "empty");
}
@NotNull
@Override
public Collection<ItemStack> populateLoot(@Nullable Random random, @NotNull LootContext context) {
return List.of();
}
@Override
public void fillInventory(@NotNull Inventory inventory, @Nullable Random random, @NotNull LootContext context) {
}
};
private final Engine engine; private final Engine engine;
private final Block block; private final Block block;
private final InventorySlotType slot; private final InventorySlotType slot;
private final KList<IrisLootTable> tables; private final KList<IrisLootTable> tables;
private final Mode mode; // New field to represent the mode
// Define the different modes for the event
public enum Mode {
NORMAL,
BUKKIT_LOOT
}
/** /**
* Constructor for IrisLootEvent with mode selection. * Constructor for IrisLootEvent with mode selection.
@@ -55,42 +64,6 @@ public class IrisLootEvent extends Event {
this.block = block; this.block = block;
this.slot = slot; this.slot = slot;
this.tables = tables; this.tables = tables;
this.mode = Mode.BUKKIT_LOOT;
if (this.mode == Mode.BUKKIT_LOOT) {
triggerBukkitLootEvent();
}
}
/**
* Triggers the corresponding Bukkit loot event.
* This method integrates your custom IrisLootTables with Bukkit's LootGenerateEvent,
* allowing other plugins to modify or cancel the loot generation.
*/
private Inventory triggerBukkitLootEvent() {
if (block.getState() instanceof InventoryHolder holder) {
Inventory inventory = holder.getInventory();
inventory.clear();
List<ItemStack> loot = new ArrayList<>();
RNG rng = new RNG();
int x = block.getX(), y = block.getY(), z = block.getZ();
for (IrisLootTable table : tables)
loot.addAll(table.getLoot(false, rng, slot, block.getWorld(), x, y, z));
LootContext context = new LootContext.Builder(block.getLocation()).build();
LootTable lootTable = LootTables.EMPTY.getLootTable(); // todo: Correct structure
LootGenerateEvent bukkitEvent = new LootGenerateEvent(engine.getWorld().realWorld(), null, holder, lootTable, context, loot, true); // todo: Use the iris loottable
Bukkit.getServer().getPluginManager().callEvent(bukkitEvent);
if (!bukkitEvent.isCancelled())
inventory.setContents(bukkitEvent.getLoot().toArray(new ItemStack[0]));
return inventory;
}
return null;
} }
@Override @Override
@@ -106,4 +79,35 @@ public class IrisLootEvent extends Event {
public static HandlerList getHandlerList() { public static HandlerList getHandlerList() {
return handlers; return handlers;
} }
/**
* Triggers the corresponding Bukkit loot event.
* This method integrates your custom IrisLootTables with Bukkit's LootGenerateEvent,
* allowing other plugins to modify or cancel the loot generation.
*
* @return true when the event was canceled
*/
public static boolean callLootEvent(KList<ItemStack> loot, Inventory inv, World world, int x, int y, int z) {
InventoryHolder holder = inv.getHolder();
Location loc = new Location(world, x, y, z);
if (holder == null) {
holder = new InventoryHolder() {
@NotNull
@Override
public Inventory getInventory() {
return inv;
}
};
}
LootContext context = new LootContext.Builder(loc).build();
LootGenerateEvent event = new LootGenerateEvent(world, null, holder, EMPTY, context, loot, true);
if (!Bukkit.isPrimaryThread()) {
Iris.warn("LootGenerateEvent was not called on the main thread, please report this issue.");
Thread.dumpStack();
J.sfut(() -> Bukkit.getPluginManager().callEvent(event)).join();
} else Bukkit.getPluginManager().callEvent(event);
return event.isCancelled();
}
} }

View File

@@ -275,10 +275,8 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
n = n > 1 ? 1 : n < 0 ? 0 : n; n = n > 1 ? 1 : n < 0 ? 0 : n;
try { try {
Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n); //Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n);
//Color color = colorMode ? Color.getHSBColor((float) (n), (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n); Color color = colorMode ? Color.getHSBColor((float) (0.666f - n * 0.666f), 1f, (float) (1f - n * 0.8f)) : Color.getHSBColor(0f, 0f, (float) n);
//Color color = colorMode ? Color.getHSBColor((float) n, (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n);
int rgb = color.getRGB(); int rgb = color.getRGB();
img.setRGB(xx, z, rgb); img.setRGB(xx, z, rgb);
} catch (Throwable ignored) { } catch (Throwable ignored) {

View File

@@ -9,6 +9,7 @@ import com.willfp.ecoitems.items.EcoItems;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException; import java.util.MissingResourceException;
@@ -33,23 +34,27 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
} }
} }
@NotNull
@Override @Override
public BlockData getBlockData(Identifier blockId, 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()); throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
} }
@NotNull
@Override @Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException { public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
EcoItem item = EcoItems.INSTANCE.getByID(itemId.key()); EcoItem item = EcoItems.INSTANCE.getByID(itemId.key());
if (item == null) throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key()); if (item == null) throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key());
return itemStack.get(item).clone(); return itemStack.get(item).clone();
} }
@NotNull
@Override @Override
public Identifier[] getBlockTypes() { public Identifier[] getBlockTypes() {
return new Identifier[0]; return new Identifier[0];
} }
@NotNull
@Override @Override
public Identifier[] getItemTypes() { public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -66,7 +71,7 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
} }
@Override @Override
public boolean isValidProvider(Identifier id, boolean isItem) { public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
return id.namespace().equalsIgnoreCase("ecoitems") && isItem; return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
} }
} }

View File

@@ -6,6 +6,7 @@ import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.Optional; import java.util.Optional;
@@ -20,23 +21,27 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
Iris.info("Setting up ExecutableItems Link..."); Iris.info("Setting up ExecutableItems Link...");
} }
@NotNull
@Override @Override
public BlockData getBlockData(Identifier blockId, 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()); throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
} }
@NotNull
@Override @Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException { public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
return ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemId.key()) return ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemId.key())
.map(item -> item.buildItem(1, Optional.empty())) .map(item -> item.buildItem(1, Optional.empty()))
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key())); .orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
} }
@NotNull
@Override @Override
public Identifier[] getBlockTypes() { public Identifier[] getBlockTypes() {
return new Identifier[0]; return new Identifier[0];
} }
@NotNull
@Override @Override
public Identifier[] getItemTypes() { public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -53,7 +58,7 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
} }
@Override @Override
public boolean isValidProvider(Identifier key, boolean isItem) { public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
return key.namespace().equalsIgnoreCase("executable_items") && isItem; return key.namespace().equalsIgnoreCase("executable_items") && isItem;
} }
} }

View File

@@ -2,22 +2,28 @@ package com.volmit.iris.core.link;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.IrisBlockData;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.MissingResourceException; import java.util.MissingResourceException;
@Getter
@RequiredArgsConstructor @RequiredArgsConstructor
public abstract class ExternalDataProvider { public abstract class ExternalDataProvider {
@Getter @NonNull
private final String pluginId; private final String pluginId;
@Nullable
public Plugin getPlugin() { public Plugin getPlugin() {
return Bukkit.getPluginManager().getPlugin(pluginId); return Bukkit.getPluginManager().getPlugin(pluginId);
} }
@@ -28,23 +34,60 @@ public abstract class ExternalDataProvider {
public abstract void init(); public abstract void init();
public BlockData getBlockData(Identifier blockId) throws MissingResourceException { /**
* @see ExternalDataProvider#getBlockData(Identifier, KMap)
*/
@NotNull
public BlockData getBlockData(@NotNull Identifier blockId) throws MissingResourceException {
return getBlockData(blockId, new KMap<>()); return getBlockData(blockId, new KMap<>());
} }
public abstract BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException; /**
* This method returns a {@link BlockData} corresponding to the blockID
* it is used in any place Iris accepts {@link BlockData}
*
* @param blockId The id of the block to get
* @param state The state of the block to get
* @return Corresponding {@link BlockData} to the blockId
* may return {@link IrisBlockData} for blocks that need a world for placement
* @throws MissingResourceException when the blockId is invalid
*/
@NotNull
public abstract BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException;
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException { /**
* @see ExternalDataProvider#getItemStack(Identifier)
*/
@NotNull
public ItemStack getItemStack(@NotNull Identifier itemId) throws MissingResourceException {
return getItemStack(itemId, new KMap<>()); return getItemStack(itemId, new KMap<>());
} }
public abstract ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException; /**
* This method returns a {@link ItemStack} corresponding to the itemID
* it is used in loot tables
*
* @param itemId The id of the item to get
* @param customNbt Custom nbt to apply to the item
* @return Corresponding {@link ItemStack} to the itemId
* @throws MissingResourceException when the itemId is invalid
*/
@NotNull
public abstract ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException;
public void processUpdate(Engine engine, Block block, Identifier blockId) {} /**
* This method is used for placing blocks that need to use the plugins api
* it will only be called when the {@link ExternalDataProvider#getBlockData(Identifier, KMap)} returned a {@link IrisBlockData}
*
* @param engine The engine of the world the block is being placed in
* @param block The block where the block should be placed
* @param blockId The blockId to place
*/
public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {}
public abstract Identifier[] getBlockTypes(); public abstract @NotNull Identifier[] getBlockTypes();
public abstract Identifier[] getItemTypes(); public abstract @NotNull Identifier[] getItemTypes();
public abstract boolean isValidProvider(Identifier id, boolean isItem); public abstract boolean isValidProvider(@NotNull Identifier id, boolean isItem);
} }

View File

@@ -16,6 +16,7 @@ import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Leaves; import org.bukkit.block.data.type.Leaves;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Map; import java.util.Map;
import java.util.MissingResourceException; import java.util.MissingResourceException;
@@ -51,8 +52,9 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
} }
} }
@NotNull
@Override @Override
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException { public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
Object o = blockDataMap.get(blockId.key()); Object o = blockDataMap.get(blockId.key());
if (o == null) if (o == null)
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()); throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
@@ -65,15 +67,16 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
return new IrisBlockData(blockData, ExternalDataSVC.buildState(blockId, state)); return new IrisBlockData(blockData, ExternalDataSVC.buildState(blockId, state));
} }
@NotNull
@Override @Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException { public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
if (!itemDataField.containsKey(itemId.key())) if (!itemDataField.containsKey(itemId.key()))
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()); throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
return itemDataField.get(itemId.key()).get(); return itemDataField.get(itemId.key()).get();
} }
@Override @Override
public void processUpdate(Engine engine, Block block, Identifier blockId) { public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
var pair = ExternalDataSVC.parseState(blockId); var pair = ExternalDataSVC.parseState(blockId);
blockId = pair.getA(); blockId = pair.getA();
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false}); Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false});
@@ -86,6 +89,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
} }
} }
@NotNull
@Override @Override
public Identifier[] getBlockTypes() { public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -101,6 +105,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
return names.toArray(new Identifier[0]); return names.toArray(new Identifier[0]);
} }
@NotNull
@Override @Override
public Identifier[] getItemTypes() { public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -117,7 +122,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
} }
@Override @Override
public boolean isValidProvider(Identifier id, boolean isItem) { public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key()); return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
} }

View File

@@ -7,6 +7,7 @@ import dev.lone.itemsadder.api.CustomBlock;
import dev.lone.itemsadder.api.CustomStack; import dev.lone.itemsadder.api.CustomStack;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException; import java.util.MissingResourceException;
@@ -32,13 +33,15 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
} }
} }
@NotNull
@Override @Override
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException { public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
return CustomBlock.getBaseBlockData(blockId.toString()); return CustomBlock.getBaseBlockData(blockId.toString());
} }
@NotNull
@Override @Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException { public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
CustomStack stack = CustomStack.getInstance(itemId.toString()); CustomStack stack = CustomStack.getInstance(itemId.toString());
if (stack == null) { if (stack == null) {
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()); throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
@@ -46,6 +49,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
return stack.getItemStack(); return stack.getItemStack();
} }
@NotNull
@Override @Override
public Identifier[] getBlockTypes() { public Identifier[] getBlockTypes() {
KList<Identifier> keys = new KList<>(); KList<Identifier> keys = new KList<>();
@@ -55,6 +59,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
return keys.toArray(new Identifier[0]); return keys.toArray(new Identifier[0]);
} }
@NotNull
@Override @Override
public Identifier[] getItemTypes() { public Identifier[] getItemTypes() {
KList<Identifier> keys = new KList<>(); KList<Identifier> keys = new KList<>();
@@ -65,7 +70,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
} }
@Override @Override
public boolean isValidProvider(Identifier id, boolean isItem) { public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace()); return isItem ? this.itemNamespaces.contains(id.namespace()) : this.blockNamespaces.contains(id.namespace());
} }
} }

View File

@@ -11,6 +11,7 @@ import net.Indyuce.mmoitems.api.block.CustomBlock;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -27,8 +28,9 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
Iris.info("Setting up MMOItems Link..."); Iris.info("Setting up MMOItems Link...");
} }
@NotNull
@Override @Override
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException { public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
int id = -1; int id = -1;
try { try {
id = Integer.parseInt(blockId.key()); id = Integer.parseInt(blockId.key());
@@ -38,8 +40,9 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
return block.getState().getBlockData(); return block.getState().getBlockData();
} }
@NotNull
@Override @Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException { public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
String[] parts = itemId.namespace().split("_", 2); String[] parts = itemId.namespace().split("_", 2);
if (parts.length != 2) if (parts.length != 2)
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()); throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
@@ -82,6 +85,7 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
return item; return item;
} }
@NotNull
@Override @Override
public Identifier[] getBlockTypes() { public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -96,6 +100,7 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
return names.toArray(new Identifier[0]); return names.toArray(new Identifier[0]);
} }
@NotNull
@Override @Override
public Identifier[] getItemTypes() { public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -124,7 +129,7 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
} }
@Override @Override
public boolean isValidProvider(Identifier id, boolean isItem) { public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems"); return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
} }

View File

@@ -40,6 +40,7 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.Optional; import java.util.Optional;
@@ -62,8 +63,9 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
} }
} }
@NotNull
@Override @Override
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException { public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key()) CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key())
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key())); .orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()));
CustomBlockItemContext blockItemContext = crucibleItem.getBlockData(); CustomBlockItemContext blockItemContext = crucibleItem.getBlockData();
@@ -76,8 +78,9 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()); throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
} }
@NotNull
@Override @Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException { public ItemStack getItemStack(@NotNull Identifier itemId, @NotNull KMap<String, Object> customNbt) throws MissingResourceException {
Optional<CrucibleItem> opt = this.itemManager.getItem(itemId.key()); Optional<CrucibleItem> opt = this.itemManager.getItem(itemId.key());
return BukkitAdapter.adapt(opt.orElseThrow(() -> return BukkitAdapter.adapt(opt.orElseThrow(() ->
new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key())) new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()))
@@ -85,6 +88,7 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
.generateItemStack(1)); .generateItemStack(1));
} }
@NotNull
@Override @Override
public Identifier[] getBlockTypes() { public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -101,6 +105,7 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
return names.toArray(new Identifier[0]); return names.toArray(new Identifier[0]);
} }
@NotNull
@Override @Override
public Identifier[] getItemTypes() { public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>(); KList<Identifier> names = new KList<>();
@@ -117,7 +122,7 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
} }
@Override @Override
public void processUpdate(Engine engine, Block block, Identifier blockId) { public void processUpdate(@NotNull Engine engine, @NotNull Block block, @NotNull Identifier blockId) {
var pair = ExternalDataSVC.parseState(blockId); var pair = ExternalDataSVC.parseState(blockId);
var state = pair.getB(); var state = pair.getB();
blockId = pair.getA(); blockId = pair.getA();
@@ -160,7 +165,7 @@ public class MythicCrucibleDataProvider extends ExternalDataProvider {
} }
@Override @Override
public boolean isValidProvider(Identifier key, boolean isItem) { public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
return key.namespace().equalsIgnoreCase("crucible"); return key.namespace().equalsIgnoreCase("crucible");
} }
} }

View File

@@ -0,0 +1,164 @@
package com.volmit.iris.core.link;
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.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.IrisBlockData;
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.PotionMeta;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.MissingResourceException;
import java.util.concurrent.atomic.AtomicBoolean;
public class NexoDataProvider extends ExternalDataProvider {
private final AtomicBoolean failed = new AtomicBoolean(false);
public NexoDataProvider() {
super("Nexo");
}
@Override
public void init() {
}
@NotNull
@Override
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
if (!NexoItems.exists(blockId.key())) {
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
}
Identifier blockState = ExternalDataSVC.buildState(blockId, state);
if (NexoBlocks.isCustomBlock(blockId.key())) {
BlockData data = NexoBlocks.blockData(blockId.key());
if (data == null)
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
return new IrisBlockData(data, blockState);
} else if (NexoFurniture.isFurniture(blockId.key())) {
return new IrisBlockData(B.getAir(), blockState);
}
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 {
ItemBuilder builder = NexoItems.itemFromId(itemId.key());
if (builder == null) {
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
}
return builder.build();
}
@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();
if (NexoBlocks.isCustomBlock(blockId.key())) {
NexoBlocks.place(blockId.key(), block.getLocation());
return;
}
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);
if (display == null) return;
ItemStack itemStack = display.getItemStack();
if (itemStack == null) return;
BiomeColor type = null;
try {
type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
} catch (NullPointerException | IllegalArgumentException ignored) {}
if (type != null) {
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);
}
}
display.setItemStack(itemStack);
}
@NotNull
@Override
public Identifier[] getBlockTypes() {
return Arrays.stream(NexoItems.itemNames())
.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 Arrays.stream(NexoItems.itemNames())
.map(i -> new Identifier("nexo", i))
.filter(i -> {
try {
return getItemStack(i) != null;
} catch (MissingResourceException e) {
return false;
}
})
.toArray(Identifier[]::new);
}
@Override
public boolean isValidProvider(@NotNull Identifier id, boolean isItem) {
return "nexo".equalsIgnoreCase(id.namespace());
}
@Override
public boolean isReady() {
return super.isReady() && !failed.get();
}
}

View File

@@ -1,213 +0,0 @@
/*
* 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;
import com.volmit.iris.Iris;
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.IrisBlockData;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.reflect.WrappedField;
import io.th0rgal.oraxen.api.OraxenItems;
import io.th0rgal.oraxen.items.ItemBuilder;
import io.th0rgal.oraxen.mechanics.Mechanic;
import io.th0rgal.oraxen.mechanics.MechanicFactory;
import io.th0rgal.oraxen.mechanics.MechanicsManager;
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanic;
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanicFactory;
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureFactory;
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureMechanic;
import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanicFactory;
import io.th0rgal.oraxen.mechanics.provided.gameplay.stringblock.StringBlockMechanicFactory;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.entity.ItemFrame;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Optional;
import java.util.function.Consumer;
public class OraxenDataProvider extends ExternalDataProvider {
private static final String FIELD_FACTORIES_MAP = "FACTORIES_BY_MECHANIC_ID";
private WrappedField<MechanicsManager, Map<String, MechanicFactory>> factories;
public OraxenDataProvider() {
super("Oraxen");
}
@Override
public void init() {
Iris.info("Setting up Oraxen Link...");
this.factories = new WrappedField<>(MechanicsManager.class, FIELD_FACTORIES_MAP);
if (this.factories.hasFailed()) {
Iris.error("Failed to set up Oraxen Link: Unable to fetch MechanicFactoriesMap!");
}
}
@Override
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
MechanicFactory factory = getFactory(blockId);
if (factory instanceof NoteBlockMechanicFactory f)
return f.createNoteBlockData(blockId.key());
else if (factory instanceof BlockMechanicFactory f) {
MultipleFacing newBlockData = (MultipleFacing) Bukkit.createBlockData(Material.MUSHROOM_STEM);
BlockMechanic.setBlockFacing(newBlockData, ((BlockMechanic) f.getMechanic(blockId.key())).getCustomVariation());
return newBlockData;
} else if (factory instanceof StringBlockMechanicFactory f) {
return f.createTripwireData(blockId.key());
} else if (factory instanceof FurnitureFactory) {
return new IrisBlockData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
} else
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
}
@Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
Optional<ItemBuilder> opt = OraxenItems.getOptionalItemById(itemId.key());
return opt.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key())).build();
}
@Override
public void processUpdate(Engine engine, Block block, Identifier blockId) {
var pair = ExternalDataSVC.parseState(blockId);
var state = pair.getB();
blockId = pair.getA();
Mechanic mechanic = getFactory(blockId).getMechanic(blockId.key());
if (mechanic instanceof FurnitureMechanic f) {
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;
}
ItemStack itemStack = OraxenItems.getItemById(f.getItemID()).build();
Entity entity = f.place(block.getLocation(), itemStack, yaw, face, false);
Consumer<ItemStack> setter = null;
if (entity instanceof ItemFrame frame) {
itemStack = frame.getItem();
setter = frame::setItem;
} else if (entity instanceof ItemDisplay display) {
itemStack = display.getItemStack();
setter = display::setItemStack;
}
if (setter == null || itemStack == null) return;
BiomeColor type = null;
try {
type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
} catch (NullPointerException | IllegalArgumentException ignored) {}
if (type != null) {
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);
}
}
setter.accept(itemStack);
}
}
@Override
public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>();
for (String name : OraxenItems.getItemNames()) {
try {
Identifier key = new Identifier("oraxen", name);
if (getBlockData(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
return names.toArray(new Identifier[0]);
}
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
for (String name : OraxenItems.getItemNames()) {
try {
Identifier key = new Identifier("oraxen", name);
if (getItemStack(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
return names.toArray(new Identifier[0]);
}
@Override
public boolean isReady() {
if (super.isReady()) {
if (factories == null) {
this.factories = new WrappedField<>(MechanicsManager.class, FIELD_FACTORIES_MAP);
}
return super.isReady() && !factories.hasFailed();
}
return false;
}
@Override
public boolean isValidProvider(Identifier key, boolean isItem) {
return key.namespace().equalsIgnoreCase("oraxen");
}
private MechanicFactory getFactory(Identifier key) throws MissingResourceException {
return factories.get().values().stream()
.filter(i -> i.getItems().contains(key.key()))
.findFirst()
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", key.namespace(), key.key()));
}
}

View File

@@ -36,6 +36,7 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.reflect.OldEnum;
import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import lombok.Data; import lombok.Data;
@@ -337,6 +338,15 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
this.imageLoader = registerLoader(IrisImage.class); this.imageLoader = registerLoader(IrisImage.class);
this.scriptLoader = registerLoader(IrisScript.class); this.scriptLoader = registerLoader(IrisScript.class);
this.matterObjectLoader = registerLoader(IrisMatterObject.class); this.matterObjectLoader = registerLoader(IrisMatterObject.class);
if (OldEnum.exists()) {
builder.registerTypeAdapterFactory(new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return (TypeAdapter<T>) OldEnum.create(type.getRawType());
}
});
}
gson = builder.create(); gson = builder.create();
} }
@@ -434,6 +444,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
return adapter.read(reader); return adapter.read(reader);
} catch (Throwable e) { } catch (Throwable e) {
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least."); Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
Iris.reportError(e);
try { try {
return (T) typeToken.getRawType().getConstructor().newInstance(); return (T) typeToken.getRawType().getConstructor().newInstance();
} catch (Throwable ignored) { } catch (Throwable ignored) {

View File

@@ -1,15 +0,0 @@
package com.volmit.iris.core.nms;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.event.Listener;
import org.bukkit.generator.ChunkGenerator;
public interface IMemoryWorld extends Listener, AutoCloseable {
World getBukkit();
Chunk getChunk(int x, int z);
ChunkGenerator.ChunkData getChunkData(int x, int z);
}

View File

@@ -30,7 +30,9 @@ public class INMS {
"1.20.5", "v1_20_R4", "1.20.5", "v1_20_R4",
"1.20.6", "v1_20_R4", "1.20.6", "v1_20_R4",
"1.21", "v1_21_R1", "1.21", "v1_21_R1",
"1.21.1", "v1_21_R1" "1.21.1", "v1_21_R1",
"1.21.2", "v1_21_R2",
"1.21.3", "v1_21_R2"
); );
//@done //@done
private static final INMSBinding binding = bind(); private static final INMSBinding binding = bind();

View File

@@ -18,7 +18,6 @@
package com.volmit.iris.core.nms; package com.volmit.iris.core.nms;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.container.BiomeColor; import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion; import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
@@ -31,7 +30,6 @@ import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
import com.volmit.iris.util.nbt.tag.CompoundTag; import com.volmit.iris.util.nbt.tag.CompoundTag;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Dolphin; import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@@ -42,7 +40,6 @@ import org.bukkit.inventory.ItemStack;
import java.awt.*; import java.awt.*;
import java.awt.Color; import java.awt.Color;
import java.io.IOException;
public interface INMSBinding { public interface INMSBinding {
boolean hasTile(Material material); boolean hasTile(Material material);
@@ -99,10 +96,6 @@ public interface INMSBinding {
int countCustomBiomes(); int countCustomBiomes();
default boolean setBlock(World world, int x, int y, int z, BlockData data, int flag, int updateDepth) {
throw new UnsupportedOperationException();
}
void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk); void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk);
default boolean supportsDataPacks() { default boolean supportsDataPacks() {
@@ -132,20 +125,4 @@ public interface INMSBinding {
} }
KList<String> getStructureKeys(); KList<String> getStructureKeys();
default BlockData getBlockData(CompoundTag tag) {
Iris.error("Unsupported version!");
return null;
};
default IMemoryWorld createMemoryWorld(WorldCreator creator) throws IOException {
return createMemoryWorld(switch (creator.environment()) {
case NORMAL -> NamespacedKey.minecraft("overworld");
case NETHER -> NamespacedKey.minecraft("the_nether");
case THE_END -> NamespacedKey.minecraft("the_end");
default -> throw new IllegalArgumentException("Illegal dimension (" + creator.environment() + ")");
}, creator);
}
IMemoryWorld createMemoryWorld(NamespacedKey levelType, WorldCreator creator) throws IOException;
} }

View File

@@ -3,6 +3,7 @@ package com.volmit.iris.core.nms.datapack;
import com.volmit.iris.core.nms.INMS; import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192; import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192;
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206; import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
import com.volmit.iris.core.nms.datapack.v1213.DataFixerV1213;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@@ -13,7 +14,8 @@ import java.util.function.Supplier;
@Getter @Getter
public enum DataVersion { public enum DataVersion {
V1192("1.19.2", 10, DataFixerV1192::new), V1192("1.19.2", 10, DataFixerV1192::new),
V1205("1.20.6", 41, DataFixerV1206::new); V1205("1.20.6", 41, DataFixerV1206::new),
V1213("1.21.3", 57, DataFixerV1213::new);
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>(); private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
private final Supplier<IDataFixer> constructor; private final Supplier<IDataFixer> constructor;

View File

@@ -16,6 +16,8 @@ public class DataFixerV1206 implements IDataFixer {
int spawnRarity = biome.getSpawnRarity(); int spawnRarity = biome.getSpawnRarity();
if (spawnRarity > 0) { if (spawnRarity > 0) {
json.put("creature_spawn_probability", Math.min(spawnRarity/20d, 0.9999999)); json.put("creature_spawn_probability", Math.min(spawnRarity/20d, 0.9999999));
} else {
json.remove("creature_spawn_probability");
} }
var spawns = biome.getSpawns(); var spawns = biome.getSpawns();
@@ -26,10 +28,10 @@ public class DataFixerV1206 implements IDataFixer {
for (IrisBiomeCustomSpawn i : spawns) { for (IrisBiomeCustomSpawn i : spawns) {
JSONArray g = groups.computeIfAbsent(i.getGroup(), (k) -> new JSONArray()); JSONArray g = groups.computeIfAbsent(i.getGroup(), (k) -> new JSONArray());
JSONObject o = new JSONObject(); JSONObject o = new JSONObject();
o.put("type", "minecraft:" + i.getType().name().toLowerCase()); o.put("type", i.getType().getKey());
o.put("weight", i.getWeight()); o.put("weight", i.getWeight());
o.put("minCount", Math.min(i.getMinCount()/20d, 0)); o.put("minCount", i.getMinCount());
o.put("maxCount", Math.min(i.getMaxCount()/20d, 0.9999999)); o.put("maxCount", i.getMaxCount());
g.put(o); g.put(o);
} }

View File

@@ -0,0 +1,16 @@
package com.volmit.iris.core.nms.datapack.v1213;
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.json.JSONArray;
import com.volmit.iris.util.json.JSONObject;
public class DataFixerV1213 extends DataFixerV1206 {
@Override
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
json = super.fixCustomBiome(biome, json);
json.put("carvers", new JSONArray());
return json;
}
}

View File

@@ -19,10 +19,8 @@
package com.volmit.iris.core.nms.v1X; package com.volmit.iris.core.nms.v1X;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.core.nms.INMSBinding; import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.core.nms.container.BiomeColor; import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
@@ -33,8 +31,6 @@ import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
import com.volmit.iris.util.nbt.tag.CompoundTag; import com.volmit.iris.util.nbt.tag.CompoundTag;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
@@ -42,9 +38,8 @@ import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.structure.Structure; import org.bukkit.generator.structure.Structure;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.awt.*;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.util.stream.StreamSupport;
public class NMSBinding1X implements INMSBinding { public class NMSBinding1X implements INMSBinding {
private static final boolean supportsCustomHeight = testCustomHeight(); private static final boolean supportsCustomHeight = testCustomHeight();
@@ -116,18 +111,13 @@ public class NMSBinding1X implements INMSBinding {
@Override @Override
public KList<String> getStructureKeys() { public KList<String> getStructureKeys() {
var list = Registry.STRUCTURE.stream() var list = StreamSupport.stream(Registry.STRUCTURE.spliterator(), false)
.map(Structure::getKey) .map(Structure::getKey)
.map(NamespacedKey::toString) .map(NamespacedKey::toString)
.toList(); .toList();
return new KList<>(list); return new KList<>(list);
} }
@Override
public IMemoryWorld createMemoryWorld(NamespacedKey levelType, WorldCreator creator) throws IOException {
throw new IOException("Unsupported version!");
}
@Override @Override
public CompoundTag serializeEntity(Entity location) { public CompoundTag serializeEntity(Entity location) {
return null; return null;

View File

@@ -236,7 +236,8 @@ public class ChunkUpdater {
try { try {
c = PaperLib.getChunkAtAsync(world, xx, zz, false, true) c = PaperLib.getChunkAtAsync(world, xx, zz, false, true)
.thenApply(chunk -> { .thenApply(chunk -> {
chunk.addPluginChunkTicket(Iris.instance); if (chunk != null)
chunk.addPluginChunkTicket(Iris.instance);
return chunk; return chunk;
}).get(); }).get();
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException | ExecutionException e) {
@@ -244,12 +245,17 @@ public class ChunkUpdater {
return; return;
} }
if (c == null) {
generated.set(false);
return;
}
if (!c.isLoaded()) { if (!c.isLoaded()) {
var future = J.sfut(() -> c.load(false)); var future = J.sfut(() -> c.load(false));
if (future != null) future.join(); if (future != null) future.join();
} }
if (!c.isGenerated()) if (!PaperLib.isChunkGenerated(c.getWorld(), xx, zz))
generated.set(false); generated.set(false);
var pair = lastUse.computeIfAbsent(Cache.key(c), k -> new Pair<>(0L, new AtomicInteger(-1))); var pair = lastUse.computeIfAbsent(Cache.key(c), k -> new Pair<>(0L, new AtomicInteger(-1)));

View File

@@ -0,0 +1,274 @@
package com.volmit.iris.core.pregenerator;
import com.google.gson.Gson;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import lombok.Data;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
public class DeepSearchPregenerator extends Thread implements Listener {
@Getter
private static DeepSearchPregenerator instance;
private final DeepSearchJob job;
private final File destination;
private final int maxPosition;
private World world;
private final ChronoLatch latch;
private static AtomicInteger foundChunks;
private final AtomicInteger foundLast;
private final AtomicInteger foundTotalChunks;
private final AtomicLong startTime;
private final RollingSequence chunksPerSecond;
private final RollingSequence chunksPerMinute;
private final AtomicInteger chunkCachePos;
private final AtomicInteger chunkCacheSize;
private int pos;
private final AtomicInteger foundCacheLast;
private final AtomicInteger foundCache;
private LinkedHashMap<Integer, Position2> chunkCache;
private KList<Position2> chunkQueue;
private final ReentrantLock cacheLock;
private static final Map<String, DeepSearchJob> jobs = new HashMap<>();
public DeepSearchPregenerator(DeepSearchJob job, File destination) {
this.job = job;
this.chunkCacheSize = new AtomicInteger(); // todo
this.chunkCachePos = new AtomicInteger(1000);
this.foundCacheLast = new AtomicInteger();
this.foundCache = new AtomicInteger();
this.cacheLock = new ReentrantLock();
this.destination = destination;
this.chunkCache = new LinkedHashMap<>();
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
}).count();
this.world = Bukkit.getWorld(job.getWorld().getUID());
this.chunkQueue = new KList<>();
this.latch = new ChronoLatch(3000);
this.startTime = new AtomicLong(M.ms());
this.chunksPerSecond = new RollingSequence(10);
this.chunksPerMinute = new RollingSequence(10);
foundChunks = new AtomicInteger(0);
this.foundLast = new AtomicInteger(0);
this.foundTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
this.pos = 0;
jobs.put(job.getWorld().getName(), job);
DeepSearchPregenerator.instance = this;
}
@EventHandler
public void on(WorldUnloadEvent e) {
if (e.getWorld().equals(world)) {
interrupt();
}
}
public void run() {
while (!interrupted()) {
tick();
}
try {
saveNow();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void tick() {
DeepSearchJob job = jobs.get(world.getName());
// chunkCache(); //todo finish this
if (latch.flip() && !job.paused) {
if (cacheLock.isLocked()) {
Iris.info("DeepFinder: Caching: " + chunkCachePos.get() + " Of " + chunkCacheSize.get());
} else {
long eta = computeETA();
save();
int secondGenerated = foundChunks.get() - foundLast.get();
foundLast.set(foundChunks.get());
secondGenerated = secondGenerated / 3;
chunksPerSecond.put(secondGenerated);
chunksPerMinute.put(secondGenerated * 60);
Iris.info("DeepFinder: " + C.IRIS + world.getName() + C.RESET + " Searching: " + Form.f(foundChunks.get()) + " of " + Form.f(foundTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
}
}
if (foundChunks.get() >= foundTotalChunks.get()) {
Iris.info("Completed DeepSearch!");
interrupt();
}
}
private long computeETA() {
return (long) ((foundTotalChunks.get() - foundChunks.get()) / chunksPerSecond.getAverage()) * 1000;
// todo broken
}
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
private void queueSystem(Position2 chunk) {
if (chunkQueue.isEmpty()) {
for (int limit = 512; limit != 0; limit--) {
pos = job.getPosition() + 1;
chunkQueue.add(getChunk(pos));
}
} else {
//MCAUtil.read();
}
}
private void findInChunk(World world, int x, int z) throws IOException {
int xx = x * 16;
int zz = z * 16;
Engine engine = IrisToolbelt.access(world).getEngine();
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
int height = engine.getHeight(xx + i, zz + j);
if (height > 300) {
File found = new File("plugins" + "iris" + "found.txt");
FileWriter writer = new FileWriter(found);
if (!found.exists()) {
found.createNewFile();
}
IrisBiome biome = engine.getBiome(xx, engine.getHeight(), zz);
Iris.info("Found at! " + xx + ", " + zz + "Biome ID: " + biome.getName() + ", ");
writer.write("Biome at: X: " + xx + " Z: " + zz + "Biome ID: " + biome.getName() + ", ");
return;
}
}
}
}
public Position2 getChunk(int position) {
int p = -1;
AtomicInteger xx = new AtomicInteger();
AtomicInteger zz = new AtomicInteger();
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
xx.set(x);
zz.set(z);
});
while (s.hasNext() && p++ < position) {
s.next();
}
return new Position2(xx.get(), zz.get());
}
public void save() {
J.a(() -> {
try {
saveNow();
} catch (Throwable e) {
e.printStackTrace();
}
});
}
public static void setPausedDeep(World world) {
DeepSearchJob job = jobs.get(world.getName());
if (isPausedDeep(world)){
job.paused = false;
} else {
job.paused = true;
}
if ( job.paused) {
Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Paused");
} else {
Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
}
}
public static boolean isPausedDeep(World world) {
DeepSearchJob job = jobs.get(world.getName());
return job != null && job.isPaused();
}
public void shutdownInstance(World world) throws IOException {
Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
DeepSearchJob job = jobs.get(world.getName());
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File deepFile = new File(worldDirectory, "DeepSearch.json");
if (job == null) {
Iris.error("No DeepSearch job found for world: " + world.getName());
return;
}
try {
if (!job.isPaused()) {
job.setPaused(true);
}
save();
jobs.remove(world.getName());
new BukkitRunnable() {
@Override
public void run() {
while (deepFile.exists()){
deepFile.delete();
J.sleep(1000);
}
Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
}
}.runTaskLater(Iris.instance, 20L);
} catch (Exception e) {
Iris.error("Failed to shutdown DeepSearch for " + world.getName());
e.printStackTrace();
} finally {
saveNow();
interrupt();
}
}
public void saveNow() throws IOException {
IO.writeAll(this.destination, new Gson().toJson(job));
}
@Data
@lombok.Builder
public static class DeepSearchJob {
private World world;
@lombok.Builder.Default
private int radiusBlocks = 5000;
@lombok.Builder.Default
private int position = 0;
@lombok.Builder.Default
boolean paused = false;
}
}

View File

@@ -12,7 +12,6 @@ import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -264,22 +263,22 @@ public class LazyPregenerator extends Thread implements Listener {
} }
@Data @Data
@Builder @lombok.Builder
public static class LazyPregenJob { public static class LazyPregenJob {
private String world; private String world;
@Builder.Default @lombok.Builder.Default
private int healingPosition = 0; private int healingPosition = 0;
@Builder.Default @lombok.Builder.Default
private boolean healing = false; private boolean healing = false;
@Builder.Default @lombok.Builder.Default
private int chunksPerMinute = 32; private int chunksPerMinute = 32;
@Builder.Default @lombok.Builder.Default
private int radiusBlocks = 5000; private int radiusBlocks = 5000;
@Builder.Default @lombok.Builder.Default
private int position = 0; private int position = 0;
@Builder.Default @lombok.Builder.Default
boolean silent = false; boolean silent = false;
@Builder.Default @lombok.Builder.Default
boolean paused = false; boolean paused = false;
} }
} }

View File

@@ -0,0 +1,341 @@
package com.volmit.iris.core.pregenerator;
import com.google.gson.Gson;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.HyperLock;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import io.papermc.lib.PaperLib;
import lombok.Data;
import lombok.Getter;
import org.apache.logging.log4j.core.util.ExecutorServices;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.checkerframework.checker.units.qual.N;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;
public class TurboPregenerator extends Thread implements Listener {
@Getter
private static TurboPregenerator instance;
private final TurboPregenJob job;
private final File destination;
private final int maxPosition;
private World world;
private final ChronoLatch latch;
private static AtomicInteger turboGeneratedChunks;
private final AtomicInteger generatedLast;
private final AtomicLong cachedLast;
private final RollingSequence cachePerSecond;
private final AtomicInteger turboTotalChunks;
private final AtomicLong startTime;
private final RollingSequence chunksPerSecond;
private final RollingSequence chunksPerMinute;
private KList<Position2> queue;
private ConcurrentHashMap<Integer, Position2> cache;
private AtomicInteger maxWaiting;
private ReentrantLock cachinglock;
private AtomicBoolean caching;
private final HyperLock hyperLock;
private MultiBurst burst;
private static final Map<String, TurboPregenJob> jobs = new HashMap<>();
public TurboPregenerator(TurboPregenJob job, File destination) {
this.job = job;
queue = new KList<>(512);
this.maxWaiting = new AtomicInteger(128);
this.destination = destination;
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
}).count();
this.world = Bukkit.getWorld(job.getWorld());
this.latch = new ChronoLatch(3000);
this.burst = MultiBurst.burst;
this.hyperLock = new HyperLock();
this.startTime = new AtomicLong(M.ms());
this.cachePerSecond = new RollingSequence(10);
this.chunksPerSecond = new RollingSequence(10);
this.chunksPerMinute = new RollingSequence(10);
turboGeneratedChunks = new AtomicInteger(0);
this.generatedLast = new AtomicInteger(0);
this.cachedLast = new AtomicLong(0);
this.caching = new AtomicBoolean(false);
this.turboTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
cache = new ConcurrentHashMap<>(turboTotalChunks.get());
this.cachinglock = new ReentrantLock();
jobs.put(job.getWorld(), job);
TurboPregenerator.instance = this;
}
public TurboPregenerator(File file) throws IOException {
this(new Gson().fromJson(IO.readAll(file), TurboPregenerator.TurboPregenJob.class), file);
}
public static void loadTurboGenerator(String i) {
World x = Bukkit.getWorld(i);
File turbogen = new File(x.getWorldFolder(), "turbogen.json");
if (turbogen.exists()) {
try {
TurboPregenerator p = new TurboPregenerator(turbogen);
p.start();
Iris.info("Started Turbo Pregenerator: " + p.job);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@EventHandler
public void on(WorldUnloadEvent e) {
if (e.getWorld().equals(world)) {
interrupt();
}
}
public void run() {
while (!interrupted()) {
tick();
}
try {
saveNow();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void tick() {
TurboPregenJob job = jobs.get(world.getName());
if (!cachinglock.isLocked() && cache.isEmpty() && !caching.get()) {
ExecutorService cache = Executors.newFixedThreadPool(1);
cache.submit(this::cache);
}
if (latch.flip() && caching.get()) {
long secondCached = cache.mappingCount() - cachedLast.get();
cachedLast.set(cache.mappingCount());
secondCached = secondCached / 3;
cachePerSecond.put(secondCached);
Iris.info("TurboGen: " + C.IRIS + world.getName() + C.RESET + C.BLUE + " Caching: " + Form.f(cache.mappingCount()) + " of " + Form.f(turboTotalChunks.get()) + " " + Form.f((int) cachePerSecond.getAverage()) + "/s");
}
if (latch.flip() && !job.paused && !cachinglock.isLocked()) {
long eta = computeETA();
save();
int secondGenerated = turboGeneratedChunks.get() - generatedLast.get();
generatedLast.set(turboGeneratedChunks.get());
secondGenerated = secondGenerated / 3;
chunksPerSecond.put(secondGenerated);
chunksPerMinute.put(secondGenerated * 60);
Iris.info("TurboGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(turboGeneratedChunks.get()) + " of " + Form.f(turboTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
}
if (turboGeneratedChunks.get() >= turboTotalChunks.get()) {
Iris.info("Completed Turbo Gen!");
interrupt();
} else {
if (!cachinglock.isLocked()) {
int pos = job.getPosition() + 1;
job.setPosition(pos);
if (!job.paused) {
if (queue.size() < maxWaiting.get()) {
Position2 chunk = cache.get(pos);
queue.add(chunk);
}
waitForChunksPartial();
}
}
}
}
private void cache() {
if (!cachinglock.isLocked()) {
cachinglock.lock();
caching.set(true);
PrecisionStopwatch p = PrecisionStopwatch.start();
BurstExecutor b = MultiBurst.burst.burst(turboTotalChunks.get());
b.setMulticore(true);
int[] list = IntStream.rangeClosed(0, turboTotalChunks.get()).toArray();
AtomicInteger order = new AtomicInteger(turboTotalChunks.get());
int threads = Runtime.getRuntime().availableProcessors();
if (threads > 1) threads--;
ExecutorService process = Executors.newFixedThreadPool(threads);
for (int id : list) {
b.queue(() -> {
cache.put(id, getChunk(id));
order.addAndGet(-1);
});
}
b.complete();
if (order.get() < 0) {
cachinglock.unlock();
caching.set(false);
Iris.info("Completed Caching in: " + Form.duration(p.getMilliseconds(), 2));
}
} else {
Iris.error("TurboCache is locked!");
}
}
private void waitForChunksPartial() {
while (!queue.isEmpty() && maxWaiting.get() > queue.size()) {
try {
for (Position2 c : new KList<>(queue)) {
tickGenerate(c);
queue.remove(c);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private long computeETA() {
return (long) ((turboTotalChunks.get() - turboGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
// todo broken
}
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
private void tickGenerate(Position2 chunk) {
executorService.submit(() -> {
CountDownLatch latch = new CountDownLatch(1);
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
.thenAccept((i) -> {
latch.countDown();
});
try {
latch.await();
} catch (InterruptedException ignored) {
}
turboGeneratedChunks.addAndGet(1);
});
}
public Position2 getChunk(int position) {
int p = -1;
AtomicInteger xx = new AtomicInteger();
AtomicInteger zz = new AtomicInteger();
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
xx.set(x);
zz.set(z);
});
while (s.hasNext() && p++ < position) {
s.next();
}
return new Position2(xx.get(), zz.get());
}
public void save() {
J.a(() -> {
try {
saveNow();
} catch (Throwable e) {
e.printStackTrace();
}
});
}
public static void setPausedTurbo(World world) {
TurboPregenJob job = jobs.get(world.getName());
if (isPausedTurbo(world)) {
job.paused = false;
} else {
job.paused = true;
}
if (job.paused) {
Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Paused");
} else {
Iris.info(C.BLUE + "TurboGen: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
}
}
public static boolean isPausedTurbo(World world) {
TurboPregenJob job = jobs.get(world.getName());
return job != null && job.isPaused();
}
public void shutdownInstance(World world) throws IOException {
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
TurboPregenJob job = jobs.get(world.getName());
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File turboFile = new File(worldDirectory, "turbogen.json");
if (job == null) {
Iris.error("No turbogen job found for world: " + world.getName());
return;
}
try {
if (!job.isPaused()) {
job.setPaused(true);
}
save();
jobs.remove(world.getName());
new BukkitRunnable() {
@Override
public void run() {
while (turboFile.exists()) {
turboFile.delete();
J.sleep(1000);
}
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
}
}.runTaskLater(Iris.instance, 20L);
} catch (Exception e) {
Iris.error("Failed to shutdown turbogen for " + world.getName());
e.printStackTrace();
} finally {
saveNow();
interrupt();
}
}
public void saveNow() throws IOException {
IO.writeAll(this.destination, new Gson().toJson(job));
}
@Data
@lombok.Builder
public static class TurboPregenJob {
private String world;
@lombok.Builder.Default
private int radiusBlocks = 5000;
@lombok.Builder.Default
private int position = 0;
@lombok.Builder.Default
boolean paused = false;
}
}

View File

@@ -22,7 +22,6 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.PregenListener; import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregeneratorMethod; import com.volmit.iris.core.pregenerator.PregeneratorMethod;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.M;
@@ -34,12 +33,12 @@ import org.bukkit.World;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Future; import java.util.concurrent.Semaphore;
public class AsyncPregenMethod implements PregeneratorMethod { public class AsyncPregenMethod implements PregeneratorMethod {
private final World world; private final World world;
private final MultiBurst burst; private final MultiBurst burst;
private final KList<Future<?>> future; private final Semaphore semaphore;
private final Map<Chunk, Long> lastUse; private final Map<Chunk, Long> lastUse;
public AsyncPregenMethod(World world, int threads) { public AsyncPregenMethod(World world, int threads) {
@@ -49,7 +48,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
this.world = world; this.world = world;
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY); burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
future = new KList<>(256); semaphore = new Semaphore(256);
this.lastUse = new KMap<>(); this.lastUse = new KMap<>();
} }
@@ -63,7 +62,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
for (Chunk i : new ArrayList<>(lastUse.keySet())) { for (Chunk i : new ArrayList<>(lastUse.keySet())) {
Long lastUseTime = lastUse.get(i); Long lastUseTime = lastUse.get(i);
if (lastUseTime != null && M.ms() - lastUseTime >= 10000) { if (!i.isLoaded() || (lastUseTime != null && M.ms() - lastUseTime >= 10000)) {
i.unload(); i.unload();
lastUse.remove(i); lastUse.remove(i);
} }
@@ -85,37 +84,8 @@ public class AsyncPregenMethod implements PregeneratorMethod {
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
} semaphore.release();
private void waitForChunksPartial(int maxWaiting) {
while (future.size() > maxWaiting) {
try {
Future<?> i = future.remove(0);
if (i == null) {
continue;
}
i.get();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
private void waitForChunks() {
for (Future<?> i : future.copy()) {
if (i == null) {
continue;
}
try {
i.get();
future.remove(i);
} catch (Throwable e) {
e.printStackTrace();
}
} }
} }
@@ -131,14 +101,13 @@ public class AsyncPregenMethod implements PregeneratorMethod {
@Override @Override
public void close() { public void close() {
waitForChunks(); semaphore.acquireUninterruptibly(256);
unloadAndSaveAllChunks(); unloadAndSaveAllChunks();
burst.close(); burst.close();
} }
@Override @Override
public void save() { public void save() {
waitForChunksPartial(256);
unloadAndSaveAllChunks(); unloadAndSaveAllChunks();
} }
@@ -155,10 +124,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
@Override @Override
public void generateChunk(int x, int z, PregenListener listener) { public void generateChunk(int x, int z, PregenListener listener) {
listener.onChunkGenerating(x, z); listener.onChunkGenerating(x, z);
if (future.size() > 256) { try {
waitForChunksPartial(256); semaphore.acquire();
} catch (InterruptedException e) {
return;
} }
future.add(burst.complete(() -> completeChunk(x, z, listener))); burst.complete(() -> completeChunk(x, z, listener));
} }
@Override @Override

View File

@@ -22,21 +22,23 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant; import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.loader.ResourceLoader; import com.volmit.iris.core.loader.ResourceLoader;
import com.volmit.iris.engine.framework.ListFunction;
import com.volmit.iris.engine.object.annotations.*; import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.B;
import com.volmit.iris.util.json.JSONArray; import com.volmit.iris.util.json.JSONArray;
import com.volmit.iris.util.json.JSONObject; import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.reflect.OldEnum;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import java.awt.*; import java.awt.*;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SchemaBuilder { public class SchemaBuilder {
@@ -44,7 +46,6 @@ public class SchemaBuilder {
private static final String SYMBOL_TYPE__N = ""; private static final String SYMBOL_TYPE__N = "";
private static final JSONArray POTION_TYPES = getPotionTypes(); private static final JSONArray POTION_TYPES = getPotionTypes();
private static final JSONArray ENCHANT_TYPES = getEnchantTypes(); private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
private static final JSONArray ITEM_TYPES = new JSONArray(B.getItemTypes());
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()); private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
private final KMap<String, JSONObject> definitions; private final KMap<String, JSONObject> definitions;
private final Class<?> root; private final Class<?> root;
@@ -262,7 +263,7 @@ public class SchemaBuilder {
if (!definitions.containsKey(key)) { if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject(); JSONObject j = new JSONObject();
j.put("enum", ITEM_TYPES); j.put("enum", B.getItemTypes());
definitions.put(key, j); definitions.put(key, j);
} }
@@ -342,38 +343,9 @@ public class SchemaBuilder {
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)"); description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
} else if (k.getType().isEnum()) { } else if (k.getType().isEnum()) {
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", ""); fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
JSONArray a = new JSONArray(); } else if (OldEnum.isOldEnum(k.getType())) {
boolean advanced = k.getType().isAnnotationPresent(Desc.class); fancyType = addEnum(k.getType(), prop, description, OldEnum.values(k.getType()), OldEnum::name);
for (Object gg : k.getType().getEnumConstants()) {
if (advanced) {
try {
JSONObject j = new JSONObject();
String name = ((Enum<?>) gg).name();
j.put("const", name);
Desc dd = k.getType().getField(name).getAnnotation(Desc.class);
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
a.put(j);
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
} else {
a.put(((Enum<?>) gg).name());
}
}
String key = (advanced ? "oneof-" : "") + "enum-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put(advanced ? "oneOf" : "enum", a);
definitions.put(key, j);
}
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid " + k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
} }
} }
case "object" -> { case "object" -> {
@@ -397,10 +369,6 @@ public class SchemaBuilder {
description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries."); description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries.");
} }
} }
if (t.max() > 0) {
prop.put("maxItems", t.max());
description.add(SYMBOL_LIMIT__N + " Maximum allowed entries are " + t.max() + ".");
}
String arrayType = getType(t.type()); String arrayType = getType(t.type());
@@ -472,7 +440,7 @@ public class SchemaBuilder {
if (!definitions.containsKey(key)) { if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject(); JSONObject j = new JSONObject();
j.put("enum", ITEM_TYPES); j.put("enum", B.getItemTypes());
definitions.put(key, j); definitions.put(key, j);
} }
@@ -523,39 +491,9 @@ public class SchemaBuilder {
prop.put("items", items); prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)"); description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
} else if (t.type().isEnum()) { } else if (t.type().isEnum()) {
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s"; fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
JSONArray a = new JSONArray(); } else if (OldEnum.isOldEnum(t.type())) {
boolean advanced = t.type().isAnnotationPresent(Desc.class); fancyType = addEnumList(prop, description, t, OldEnum.values(t.type()), OldEnum::name);
for (Object gg : t.type().getEnumConstants()) {
if (advanced) {
try {
JSONObject j = new JSONObject();
String name = ((Enum<?>) gg).name();
j.put("const", name);
Desc dd = t.type().getField(name).getAnnotation(Desc.class);
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
a.put(j);
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
} else {
a.put(((Enum<?>) gg).name());
}
}
String key = (advanced ? "oneof-" : "") + "enum-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put(advanced ? "oneOf" : "enum", a);
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
} }
} }
} }
@@ -588,7 +526,7 @@ public class SchemaBuilder {
if (value instanceof List) { if (value instanceof List) {
d.add(" "); d.add(" ");
d.add("* Default Value is an empty list"); d.add("* Default Value is an empty list");
} else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum())) { } else if (!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()) && !OldEnum.isOldEnum(cl)) {
d.add(" "); d.add(" ");
d.add("* Default Value is a default object (create this object to see default properties)"); d.add("* Default Value is a default object (create this object to see default properties)");
} else { } else {
@@ -634,6 +572,50 @@ public class SchemaBuilder {
return prop; return prop;
} }
@NotNull
private String addEnumList(JSONObject prop, KList<String> description, ArrayType t, Object[] values, Function<Object, String> function) {
JSONObject items = new JSONObject();
var s = addEnum(t.type(), items, description, values, function);
prop.put("items", items);
return "List of " + s + "s";
}
@NotNull
private String addEnum(Class<?> type, JSONObject prop, KList<String> description, Object[] values, Function<Object, String> function) {
JSONArray a = new JSONArray();
boolean advanced = type.isAnnotationPresent(Desc.class);
for (Object gg : values) {
if (advanced) {
try {
JSONObject j = new JSONObject();
String name = function.apply(gg);
j.put("const", name);
Desc dd = type.getField(name).getAnnotation(Desc.class);
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
a.put(j);
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
} else {
a.put(function.apply(gg));
}
}
String key = (advanced ? "oneof-" : "") + "enum-" + type.getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put(advanced ? "oneOf" : "enum", a);
definitions.put(key, j);
}
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid " + type.getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
return type.getSimpleName().replaceAll("\\QIris\\E", "");
}
private String getType(Class<?> c) { private String getType(Class<?> c) {
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) { if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
return "integer"; return "integer";
@@ -647,7 +629,7 @@ public class SchemaBuilder {
return "boolean"; return "boolean";
} }
if (c.equals(String.class) || c.isEnum() || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) { if (c.equals(String.class) || c.isEnum() || OldEnum.isOldEnum(c) || c.equals(Enchantment.class) || c.equals(PotionEffectType.class)) {
return "string"; return "string";
} }

View File

@@ -20,12 +20,11 @@ import java.util.Map;
import java.util.StringJoiner; import java.util.StringJoiner;
import static com.volmit.iris.Iris.getJavaVersion; import static com.volmit.iris.Iris.getJavaVersion;
import static com.volmit.iris.Iris.instance;
import static com.volmit.iris.core.safeguard.IrisSafeguard.*; import static com.volmit.iris.core.safeguard.IrisSafeguard.*;
public class ServerBootSFG { public class ServerBootSFG {
public static final Map<String, Boolean> incompatibilities = new HashMap<>(); public static final Map<String, Boolean> incompatibilities = new HashMap<>();
public static boolean isJDK17 = true; public static boolean isCorrectJDK = true;
public static boolean hasEnoughDiskSpace = true; public static boolean hasEnoughDiskSpace = true;
public static boolean isJRE = false; public static boolean isJRE = false;
public static boolean hasPrivileges = true; public static boolean hasPrivileges = true;
@@ -87,8 +86,8 @@ public class ServerBootSFG {
severityHigh++; severityHigh++;
} }
if (!List.of(17, 21).contains(getJavaVersion())) { if (!List.of(21).contains(getJavaVersion())) {
isJDK17 = false; isCorrectJDK = false;
joiner.add("Unsupported Java version"); joiner.add("Unsupported Java version");
severityMedium++; severityMedium++;
} }

View File

@@ -37,7 +37,7 @@ public class UtilsSFG {
} }
if (ServerBootSFG.unsuportedversion) { if (ServerBootSFG.unsuportedversion) {
Iris.safeguard(C.RED + "Server Version"); Iris.safeguard(C.RED + "Server Version");
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.21.1"); Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.21.3");
} }
if (!ServerBootSFG.passedserversoftware) { if (!ServerBootSFG.passedserversoftware) {
Iris.safeguard(C.YELLOW + "Unsupported Server Software"); Iris.safeguard(C.YELLOW + "Unsupported Server Software");
@@ -51,13 +51,13 @@ public class UtilsSFG {
Iris.safeguard(C.YELLOW + "Insufficient Disk Space"); Iris.safeguard(C.YELLOW + "Insufficient Disk Space");
Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+."); Iris.safeguard(C.YELLOW + "- The server has insufficient Free DiskSpace to run iris required 3GB+.");
} }
if (!ServerBootSFG.isJDK17) { if (!ServerBootSFG.isCorrectJDK) {
Iris.safeguard(C.YELLOW + "Unsupported java version"); Iris.safeguard(C.YELLOW + "Unsupported java version");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JDK " + Iris.getJavaVersion()); Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JDK " + Iris.getJavaVersion());
} }
if (ServerBootSFG.isJRE) { if (ServerBootSFG.isJRE) {
Iris.safeguard(C.YELLOW + "Unsupported Server JDK"); Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JRE " + Iris.getJavaVersion()); Iris.safeguard(C.YELLOW + "- Please consider using JDK 21 Instead of JRE " + Iris.getJavaVersion());
} }
} }
} }

View File

@@ -40,6 +40,7 @@ import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class BoardSVC implements IrisService, BoardProvider { public class BoardSVC implements IrisService, BoardProvider {
private final KMap<Player, PlayerBoard> boards = new KMap<>(); private final KMap<Player, PlayerBoard> boards = new KMap<>();
@@ -104,11 +105,11 @@ public class BoardSVC implements IrisService, BoardProvider {
@Data @Data
public static class PlayerBoard { public static class PlayerBoard {
private final Player player; private final Player player;
private final KList<String> lines; private final CopyOnWriteArrayList<String> lines;
public PlayerBoard(Player player) { public PlayerBoard(Player player) {
this.player = player; this.player = player;
this.lines = new KList<>(); this.lines = new CopyOnWriteArrayList<>();
update(); update();
} }
@@ -125,19 +126,32 @@ public class BoardSVC implements IrisService, BoardProvider {
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight(); int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
int z = player.getLocation().getBlockZ(); int z = player.getLocation().getBlockZ();
if(IrisSettings.get().getGeneral().debug){
lines.add("&7&m "); lines.add("&7&m ");
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0)); lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize())); lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount()); lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
lines.add("&7&m "); lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName()); lines.add("&7&m ");
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName()); lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z))); lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2)); lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond())); lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
lines.add("&7&m "); lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
lines.add("&7&m ");
} else {
lines.add("&7&m ");
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
lines.add("&7&m ");
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
lines.add("&7&m ");
}
} }
} }
} }

View File

@@ -20,12 +20,9 @@ package com.volmit.iris.core.service;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.Consumer2; import com.volmit.iris.util.function.Consumer2;
import com.volmit.iris.util.io.Converter; import com.volmit.iris.util.io.Converter;
@@ -40,16 +37,13 @@ import com.volmit.iris.util.nbt.tag.ListTag;
import com.volmit.iris.util.plugin.IrisService; import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import org.apache.commons.io.FileUtils;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Jigsaw; import org.bukkit.block.data.type.Jigsaw;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class ConversionSVC implements IrisService { public class ConversionSVC implements IrisService {
private KList<Converter> converters; private KList<Converter> converters;
@@ -128,7 +122,7 @@ public class ConversionSVC implements IrisService {
@SuppressWarnings("unchecked") ListTag<CompoundTag> paletteList = (ListTag<CompoundTag>) compound.getListTag("palette"); @SuppressWarnings("unchecked") ListTag<CompoundTag> paletteList = (ListTag<CompoundTag>) compound.getListTag("palette");
for (int i = 0; i < paletteList.size(); i++) { for (int i = 0; i < paletteList.size(); i++) {
CompoundTag cp = paletteList.get(i); CompoundTag cp = paletteList.get(i);
palette.add(INMS.get().getBlockData(cp)); palette.add(NBTWorld.getBlockData(cp));
} }
IrisJigsawPiece piece = new IrisJigsawPiece(); IrisJigsawPiece piece = new IrisJigsawPiece();
IrisObject object = new IrisObject(w, h, d); IrisObject object = new IrisObject(w, h, d);
@@ -141,37 +135,20 @@ public class ConversionSVC implements IrisService {
int z = pos.get(2).asInt(); int z = pos.get(2).asInt();
BlockData bd = palette.get(cp.getInt("state")).clone(); BlockData bd = palette.get(cp.getInt("state")).clone();
piece.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
if (bd.getMaterial().equals(Material.JIGSAW) && cp.containsKey("nbt")) { if (bd.getMaterial().equals(Material.JIGSAW) && cp.containsKey("nbt")) {
//.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]); piece.setObject(in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
IrisPosition spos = new IrisPosition(object.getSigned(x, y, z)); IrisPosition spos = new IrisPosition(object.getSigned(x, y, z));
CompoundTag nbt = cp.getCompoundTag("nbt"); CompoundTag nbt = cp.getCompoundTag("nbt");
CompoundTag finalState = new CompoundTag(); CompoundTag finalState = new CompoundTag();
finalState.putString("Name", nbt.getString("final_state")); finalState.putString("Name", nbt.getString("final_state"));
BlockData jd = bd.clone(); BlockData jd = bd.clone();
bd = INMS.get().getBlockData(finalState); bd = NBTWorld.getBlockData(finalState);
String joint = nbt.getString("joint"); String joint = nbt.getString("joint");
String pool = nbt.getString("pool"); String pool = nbt.getString("pool");
String poolId = toPoolName(pool); String poolId = toPoolName(pool);
String name = nbt.getString("name"); String name = nbt.getString("name");
String target = nbt.getString("target"); String target = nbt.getString("target");
pools.computeIfAbsent(poolId, (k) -> { pools.computeIfAbsent(poolId, (k) -> new IrisJigsawPool());
IrisJigsawPool irisPool = new IrisJigsawPool();
String basePath = in.toURI().relativize(folder.toURI()).getPath();
File baseFolder = new File(in.toURI().relativize(folder.toURI()).toString());
String[] paths = FileUtils.listFiles(folder, null, true)
.stream()
.map(path -> path.getPath().replaceAll("\\.nbt$", "")).toArray(String[]::new);
KList<String> poolList = new KList<>();
for (int ii = 0; ii < Objects.requireNonNull(paths).length; ii++) {
String lastSegment = paths[ii].substring(paths[ii].lastIndexOf("\\") + 1);
poolList.add(basePath + lastSegment);
}
irisPool.setPieces(poolList);
return irisPool;
});
IrisJigsawPieceConnector connector = new IrisJigsawPieceConnector(); IrisJigsawPieceConnector connector = new IrisJigsawPieceConnector();
connector.setName(name); connector.setName(name);
connector.setTargetName(target); connector.setTargetName(target);
@@ -192,14 +169,10 @@ public class ConversionSVC implements IrisService {
} }
} }
if (piece.getObject().isBlank() || piece.getObject().isEmpty()) {
Iris.info(C.RED + "Failed Setting object with path: " + in.toURI().relativize(folder.toURI()).getPath() + file.getName().split("\\Q.\\E")[0]);
}
jpool.getPieces().addIfMissing(id); jpool.getPieces().addIfMissing(id);
object.write(new File(destObjects, file.getName().split("\\Q.\\E")[0] + ".iob")); object.write(new File(destObjects, file.getName().split("\\Q.\\E")[0] + ".iob"));
IO.writeAll(new File(destPieces, file.getName().split("\\Q.\\E")[0] + ".json"), new JSONObject(new Gson().toJson(piece)).toString(4)); IO.writeAll(new File(destPieces, file.getName().split("\\Q.\\E")[0] + ".json"), new JSONObject(new Gson().toJson(piece)).toString(4));
Iris.info("[Jigsaw]: (" + Form.pc((double) at.get() / (double) total.get(), 0).replace("%", "%%") + ") Exported Piece: " + id); Iris.info("[Jigsaw]: (" + Form.pc((double) at.get() / (double) total.get(), 0) + ") Exported Piece: " + id);
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();

View File

@@ -26,6 +26,7 @@ import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.plugin.IrisService; import com.volmit.iris.util.plugin.IrisService;
import lombok.Data; import lombok.Data;
import lombok.NonNull;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@@ -46,9 +47,9 @@ public class ExternalDataSVC implements IrisService {
Iris.info("Loading ExternalDataProvider..."); Iris.info("Loading ExternalDataProvider...");
Bukkit.getPluginManager().registerEvents(this, Iris.instance); Bukkit.getPluginManager().registerEvents(this, Iris.instance);
providers.add(new OraxenDataProvider()); providers.add(new NexoDataProvider());
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) { if (Bukkit.getPluginManager().getPlugin("Nexo") != null) {
Iris.info("Oraxen found, loading OraxenDataProvider..."); Iris.info("Nexo found, loading NexoDataProvider...");
} }
providers.add(new MythicCrucibleDataProvider()); providers.add(new MythicCrucibleDataProvider());
if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) { if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
@@ -99,6 +100,18 @@ public class ExternalDataSVC implements IrisService {
} }
} }
public void registerProvider(@NonNull ExternalDataProvider provider) {
String plugin = provider.getPluginId();
if (providers.stream().map(ExternalDataProvider::getPluginId).anyMatch(plugin::equals))
throw new IllegalArgumentException("A provider with the same plugin id already exists.");
providers.add(provider);
if (provider.isReady()) {
activeProviders.add(provider);
provider.init();
}
}
public Optional<BlockData> getBlockData(final Identifier key) { public Optional<BlockData> getBlockData(final Identifier key) {
var pair = parseState(key); var pair = parseState(key);
Identifier mod = pair.getA(); Identifier mod = pair.getA();

View File

@@ -63,7 +63,12 @@ public class StudioSVC implements IrisService {
if (!f.exists()) { if (!f.exists()) {
Iris.info("Downloading Default Pack " + pack); Iris.info("Downloading Default Pack " + pack);
downloadSearch(Iris.getSender(), pack, false); if (pack.equals("overworld")) {
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + Iris.OVERWORLD_TAG + "/overworld.zip";
Iris.service(StudioSVC.class).downloadRelease(Iris.getSender(), url, false, false);
} else {
downloadSearch(Iris.getSender(), pack, false);
}
} }
}); });
} }

View File

@@ -76,7 +76,7 @@ public class WandSVC implements IrisService {
* @param p The wand player * @param p The wand player
* @return The new object * @return The new object
*/ */
public static IrisObject createSchematic(Player p) { public static IrisObject createSchematic(Player p, boolean legacy) {
if (!isHoldingWand(p)) { if (!isHoldingWand(p)) {
return null; return null;
} }
@@ -132,7 +132,7 @@ public class WandSVC implements IrisService {
continue; continue;
BlockVector bv = b.getLocation().subtract(c.getLowerNE().toVector()).toVector().toBlockVector(); BlockVector bv = b.getLocation().subtract(c.getLowerNE().toVector()).toVector().toBlockVector();
s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b); s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b, legacy);
} finally { } finally {
i++; i++;
} }

View File

@@ -2,12 +2,8 @@ package com.volmit.iris.core.tools;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.Consumer2;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.nbt.io.NBTUtil; import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.io.NamedTag; import com.volmit.iris.util.nbt.io.NamedTag;
import com.volmit.iris.util.nbt.tag.*; import com.volmit.iris.util.nbt.tag.*;
@@ -34,10 +30,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class IrisConverter { public class IrisConverter {
/**
* Converts all schematics in the convert folder
* @param sender
*/
public static void convertSchematics(VolmitSender sender) { public static void convertSchematics(VolmitSender sender) {
File folder = Iris.instance.getDataFolder("convert"); File folder = Iris.instance.getDataFolder("convert");
@@ -140,62 +132,6 @@ public class IrisConverter {
}); });
} }
// /**
// *
// * @param sender
// */
// public static void convertJigsawStructure(File in, File out, VolmitSender sender) {
// File dataFolder = Iris.instance.getDataFolder("convert");
// try {
// KMap<String, IrisJigsawPool> pools = new KMap<>();
// KList<File> roots = new KList<>();
// AtomicInteger total = new AtomicInteger(0);
// AtomicInteger at = new AtomicInteger(0);
// File destPools = new File(out.getAbsolutePath() + "/jigsaw-pools");
// destPools.mkdirs();
// findAllNBT(in, (folder, file) -> {
// total.getAndIncrement();
// if (roots.addIfMissing(folder)) {
// String b = in.toURI().relativize(folder.toURI()).getPath();
// if (b.startsWith("/")) {
// b = b.substring(1);
// }
//
// if (b.endsWith("/")) {
// b = b.substring(0, b.length() - 1);
// }
//
// pools.put(b, new IrisJigsawPool());
// }
// });
//
// } catch (Exception e) {
// Iris.error(C.RED + "Failed to convert: " + in.getPath());
// e.printStackTrace();
// }
//
//
//
// }
private static void findAllNBT(File path, Consumer2<File, File> inFile) {
if (path == null) {
return;
}
if (path.isFile() && path.getName().endsWith(".nbt")) {
inFile.accept(path.getParentFile(), path);
return;
}
for (File i : path.listFiles()) {
if (i.isDirectory()) {
findAllNBT(i, inFile);
} else if (i.isFile() && i.getName().endsWith(".nbt")) {
inFile.accept(path, i);
}
}
}
} }

View File

@@ -24,10 +24,8 @@ import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator; import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.pregenerator.PregenTask; import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension; import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.platform.PlatformChunkGenerator; import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.core.safeguard.UtilsSFG;
import com.volmit.iris.util.exceptions.IrisException; import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
@@ -46,7 +44,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier; import java.util.function.Supplier;
import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode;
/** /**
* Makes it a lot easier to setup an engine, world, studio or whatever * Makes it a lot easier to setup an engine, world, studio or whatever
@@ -126,14 +123,11 @@ public class IrisCreator {
if (sender == null) if (sender == null)
sender = Iris.getSender(); sender = Iris.getSender();
if (!studio()) { if (!studio() || benchmark) {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
}
if (benchmark) {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name())); Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
} }
PlatformChunkGenerator access = null; PlatformChunkGenerator access;
AtomicReference<World> world = new AtomicReference<>(); AtomicReference<World> world = new AtomicReference<>();
AtomicDouble pp = new AtomicDouble(0); AtomicDouble pp = new AtomicDouble(0);
O<Boolean> done = new O<>(); O<Boolean> done = new O<>();

View File

@@ -9,8 +9,6 @@ import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.exceptions.IrisException; import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Getter; import lombok.Getter;
@@ -27,44 +25,44 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.time.Clock; import java.time.Clock;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.*;
public class IrisPackBenchmarking { public class IrisPackBenchmarking {
@Getter @Getter
public static IrisPackBenchmarking instance; public static IrisPackBenchmarking instance;
public static boolean benchmarkInProgress = false; public static boolean benchmarkInProgress = false;
private IrisDimension IrisDimension; private final PrecisionStopwatch stopwatch = new PrecisionStopwatch();
private int radius; private final IrisDimension dimension;
private boolean finished = false; private final int radius;
PrecisionStopwatch stopwatch; private final boolean gui;
public IrisPackBenchmarking(IrisDimension dimension, int r) { public IrisPackBenchmarking(IrisDimension dimension, int radius, boolean gui) {
instance = this; instance = this;
this.IrisDimension = dimension; this.dimension = dimension;
this.radius = r; this.radius = radius;
this.gui = gui;
runBenchmark(); runBenchmark();
} }
private void runBenchmark() { private void runBenchmark() {
this.stopwatch = new PrecisionStopwatch(); Thread.ofVirtual()
ExecutorService service = Executors.newSingleThreadExecutor(); .name("PackBenchmarking")
service.submit(() -> { .start(() -> {
Iris.info("Setting up benchmark environment "); Iris.info("Setting up benchmark environment ");
benchmarkInProgress = true; benchmarkInProgress = true;
File file = new File("benchmark"); File file = new File("benchmark");
if (file.exists()) { if (file.exists()) {
deleteDirectory(file.toPath()); deleteDirectory(file.toPath());
} }
createBenchmark(); createBenchmark();
while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) { while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
J.sleep(1000); J.sleep(1000);
Iris.debug("Iris PackBenchmark: Waiting..."); Iris.debug("Iris PackBenchmark: Waiting...");
} }
Iris.info("Starting Benchmark!"); Iris.info("Starting Benchmark!");
stopwatch.begin(); stopwatch.begin();
startBenchmark(); startBenchmark();
}); });
} }
@@ -88,14 +86,14 @@ public class IrisPackBenchmarking {
File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks"); File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks");
profilers.mkdir(); profilers.mkdir();
File results = new File("plugins " + File.separator + "Iris", IrisDimension.getName() + LocalDateTime.now(Clock.systemDefaultZone()) + ".txt"); File results = new File(profilers, dimension.getName() + " " + LocalDateTime.now(Clock.systemDefaultZone()).toString().replace(':', '-') + ".txt");
results.createNewFile(); results.getParentFile().mkdirs();
KMap<String, Double> metrics = engine.getMetrics().pull(); KMap<String, Double> metrics = engine.getMetrics().pull();
try (FileWriter writer = new FileWriter(results)) { try (FileWriter writer = new FileWriter(results)) {
writer.write("-----------------\n"); writer.write("-----------------\n");
writer.write("Results:\n"); writer.write("Results:\n");
writer.write("Dimension: " + IrisDimension.getName() + "\n"); writer.write("Dimension: " + dimension.getName() + "\n");
writer.write("- Date of Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n"); writer.write("- Date of Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n");
writer.write("\n"); writer.write("\n");
writer.write("Metrics"); writer.write("Metrics");
for (String m : metrics.k()) { for (String m : metrics.k()) {
@@ -103,7 +101,7 @@ public class IrisPackBenchmarking {
writer.write("- " + m + ": " + i); writer.write("- " + m + ": " + i);
} }
writer.write("- " + metrics); writer.write("- " + metrics);
writer.write("Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n"); writer.write("Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n");
writer.write("- Total time: " + time + "\n"); writer.write("- Total time: " + time + "\n");
writer.write("- Average CPS: " + calculateAverage(cps) + "\n"); writer.write("- Average CPS: " + calculateAverage(cps) + "\n");
writer.write(" - Median CPS: " + calculateMedian(cps) + "\n"); writer.write(" - Median CPS: " + calculateMedian(cps) + "\n");
@@ -116,17 +114,24 @@ public class IrisPackBenchmarking {
e.printStackTrace(); e.printStackTrace();
} }
Bukkit.getServer().unloadWorld("benchmark", true); J.s(() -> {
var world = Bukkit.getWorld("benchmark");
if (world == null) return;
IrisToolbelt.evacuate(world);
Bukkit.unloadWorld(world, true);
});
stopwatch.end(); stopwatch.end();
} catch (Exception e) { } catch (Exception e) {
Iris.error("Something has gone wrong!"); Iris.error("Something has gone wrong!");
e.printStackTrace(); e.printStackTrace();
} }
} }
private void createBenchmark(){
private void createBenchmark() {
try { try {
IrisToolbelt.createWorld() IrisToolbelt.createWorld()
.dimension(IrisDimension.getName()) .dimension(dimension.getLoadKey())
.name("benchmark") .name("benchmark")
.seed(1337) .seed(1337)
.studio(false) .studio(false)
@@ -137,17 +142,14 @@ public class IrisPackBenchmarking {
} }
} }
private void startBenchmark(){ private void startBenchmark() {
int x = 0; IrisToolbelt.pregenerate(PregenTask
int z = 0; .builder()
IrisToolbelt.pregenerate(PregenTask .gui(gui)
.builder() .width(radius)
.gui(false) .height(radius)
.center(new Position2(x, z)) .build(), Bukkit.getWorld("benchmark")
.width(5) );
.height(5)
.build(), Bukkit.getWorld("benchmark")
);
} }
private double calculateAverage(KList<Integer> list) { private double calculateAverage(KList<Integer> list) {
@@ -179,7 +181,7 @@ public class IrisPackBenchmarking {
private boolean deleteDirectory(Path dir) { private boolean deleteDirectory(Path dir) {
try { try {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { Files.walkFileTree(dir, new SimpleFileVisitor<>() {
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file); Files.delete(file);

View File

@@ -1,111 +0,0 @@
package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.Looper;
import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
public class IrisWorldAnalytics {
private final ChronoLatch latch;
private final String world;
private final AtomicInteger totalChunks;
private final AtomicInteger processed;
private final RollingSequence chunksPerSecond;
private final AtomicLong startTime;
private final Looper ticker;
public IrisWorldAnalytics(String world) {
this.world = world;
totalChunks = new AtomicInteger();
processed = new AtomicInteger(0);
latch = new ChronoLatch(3000);
chunksPerSecond = new RollingSequence(3000);
startTime = new AtomicLong(M.ms());
index();
ticker = new Looper() {
@Override
protected long loop() {
return 1000;
}
};
}
public void execute() {
Iris.info("Starting world analyser..");
long startTime = System.currentTimeMillis();
}
private long computeETA() {
return (long) (totalChunks.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() - processed.get()) * ((double) (M.ms() - startTime.get()) / (double) processed.get())) :
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
((totalChunks.get() - processed.get()) / chunksPerSecond.getAverage()) * 1000
);
}
private void index() {
try {
AtomicInteger chunks = new AtomicInteger();
AtomicInteger pr = new AtomicInteger();
AtomicInteger pl = new AtomicInteger(0);
RollingSequence rps = new RollingSequence(5);
ChronoLatch cl = new ChronoLatch(3000);
File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca"));
Supplier<Long> eta = () -> (long) ((McaFiles.length - pr.get()) / rps.getAverage()) * 1000;
ScheduledFuture<?> sc = Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
int sp = pr.get() - pl.get();
pl.set(pr.get());
rps.put(sp);
if (cl.flip()) {
double pc = ((double) pr.get() / (double) McaFiles.length) * 100;
Iris.info("Indexing: " + Form.f(pr.get()) + " of " + Form.f(McaFiles.length) + " (%.0f%%) " + Form.f((int) rps.getAverage()) + "/s ETA: " + Form.duration(eta.get(), 2), pc);
}
}, 3,1, TimeUnit.SECONDS);
BurstExecutor b = MultiBurst.burst.burst(McaFiles.length);
for (File mca : McaFiles) {
b.queue(() -> {
try {
MCAFile region = MCAUtil.read(mca, 0);
var array = region.getChunks();
for (int i = 0; i < array.length(); i++) {
if (array.get(i) != null) {
chunks.incrementAndGet();
}
}
pr.incrementAndGet();
} catch (Exception e) {
e.printStackTrace();
}
});
}
b.complete();
sc.cancel(true);
totalChunks.set(chunks.get());
Iris.info("Indexing completed!");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,73 +0,0 @@
package com.volmit.iris.core.tools;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.Spiraler;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
public class IrisWorldMerger {
private Engine engine;
private World world;
private World selectedWorld;
/**
* @param world > The selected world to get the caves from
* @param engine > The engine of the iris world
*/
public IrisWorldMerger(Engine engine, World world) {
this.engine = engine;
this.world = this.engine.getWorld().realWorld();
this.selectedWorld = world;
}
/**
* Merges caves from a selected chunk into the corresponding chunk in the outcome world.
*
* @param selectedChunk The chunk from the selected world.
* @param targetChunk The corresponding chunk in the outcome world.
*/
private void mergeCavesInChunk(Chunk selectedChunk, Chunk targetChunk) {
int baseX = selectedChunk.getX() << 4;
int baseZ = selectedChunk.getZ() << 4;
for (int x = 0; x < 16; x++) {
int worldX = baseX + x;
for (int z = 0; z < 16; z++) {
int worldZ = baseZ + z;
int surfaceY = engine.getHeight(worldX, worldZ);
for (int y = 0; y <= surfaceY; y++) {
Block selectedBlock = selectedChunk.getBlock(x, y, z);
if (selectedBlock.getType() == Material.AIR) {
Block targetBlock = targetChunk.getBlock(x, y, z);
targetBlock.setType(Material.AIR);
}
}
}
}
}
/**
* Irritates (merges) caves in a spiral pattern around the specified center chunk coordinates.
*
* @param centerX The X coordinate of the center chunk.
* @param centerZ The Z coordinate of the center chunk.
* @param radius The radius (in chunks) to merge caves around.
*/
public void irritateSpiral(int centerX, int centerZ, int radius) {
Spiraler spiraler = new Spiraler(radius * 2, radius * 2, (x, z) -> {
int chunkX = centerX + x;
int chunkZ = centerZ + z;
Chunk selectedChunk = selectedWorld.getChunkAt(chunkX, chunkZ);
Chunk targetChunk = world.getChunkAt(chunkX, chunkZ);
mergeCavesInChunk(selectedChunk, targetChunk);
});
// Execute the spiral iteration
while (spiraler.hasNext()) {
spiraler.next(); // The spiraler itself runs the callback defined in its constructor
}
}
}

View File

@@ -29,6 +29,7 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.IrisContext; import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.data.DataProvider; import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.interpolation.IrisInterpolation.NoiseKey;
import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.noise.CNG; import com.volmit.iris.util.noise.CNG;
@@ -292,9 +293,11 @@ public class IrisComplex implements DataProvider {
return 0; return 0;
} }
KMap<NoiseKey, IrisBiome> cache = new KMap<>();
double hi = interpolator.interpolate(x, z, (xx, zz) -> { double hi = interpolator.interpolate(x, z, (xx, zz) -> {
try { try {
IrisBiome bx = baseBiomeStream.get(xx, zz); IrisBiome bx = baseBiomeStream.get(xx, zz);
cache.put(new NoiseKey(xx, zz), bx);
double b = 0; double b = 0;
for (IrisGenerator gen : generators) { for (IrisGenerator gen : generators) {
@@ -313,7 +316,11 @@ public class IrisComplex implements DataProvider {
double lo = interpolator.interpolate(x, z, (xx, zz) -> { double lo = interpolator.interpolate(x, z, (xx, zz) -> {
try { try {
IrisBiome bx = baseBiomeStream.get(xx, zz); IrisBiome bx = cache.get(new NoiseKey(xx, zz));
if (bx == null) {
bx = baseBiomeStream.get(xx, zz);
cache.put(new NoiseKey(xx, zz), bx);
}
double b = 0; double b = 0;
for (IrisGenerator gen : generators) { for (IrisGenerator gen : generators) {

View File

@@ -21,11 +21,10 @@ package com.volmit.iris.engine;
import com.google.common.util.concurrent.AtomicDouble; import com.google.common.util.concurrent.AtomicDouble;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator; import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.events.IrisEngineHotloadEvent; import com.volmit.iris.core.events.IrisEngineHotloadEvent;
import com.volmit.iris.core.gui.PregeneratorJob; import com.volmit.iris.core.gui.PregeneratorJob;
import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.container.BlockPos; import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.core.project.IrisProject; import com.volmit.iris.core.project.IrisProject;
@@ -54,24 +53,21 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import org.apache.commons.lang3.function.Failable; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.WorldCreator;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Data @Data
@EqualsAndHashCode(exclude = "context") @EqualsAndHashCode(exclude = "context")
@@ -100,8 +96,6 @@ public class IrisEngine implements Engine {
private EngineEffects effects; private EngineEffects effects;
private EngineExecutionEnvironment execution; private EngineExecutionEnvironment execution;
private EngineWorldManager worldManager; private EngineWorldManager worldManager;
private IMemoryWorld memoryWorld;
private IrisMerger merger;
private volatile int parallelism; private volatile int parallelism;
private volatile int minHeight; private volatile int minHeight;
private boolean failing; private boolean failing;
@@ -133,9 +127,6 @@ public class IrisEngine implements Engine {
context = new IrisContext(this); context = new IrisContext(this);
cleaning = new AtomicBoolean(false); cleaning = new AtomicBoolean(false);
context.touch(); context.touch();
merger = getDimension().getMerger();
merger.loadWorld(this);
updateMemoryWorld();
getData().setEngine(this); getData().setEngine(this);
getData().loadPrefetch(this); getData().loadPrefetch(this);
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getDimension().getDimensionHeight() + " height) Seed: " + getSeedManager().getSeed()); Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getDimension().getDimensionHeight() + " height) Seed: " + getSeedManager().getSeed());
@@ -201,34 +192,6 @@ public class IrisEngine implements Engine {
mode = getDimension().getMode().getType().create(this); mode = getDimension().getMode().getType().create(this);
} }
private void updateMemoryWorld() {
try {
if(!merger.isUseMemoryWorld() || merger.getGenerator().isEmpty())
return;
merger = getDimension().getMerger();
if (!getDimension().isEnableExperimentalMerger()) return;
if (getMerger().getGenerator().isBlank()) return;
NamespacedKey dk = NamespacedKey.minecraft("memory_current_creator");
PersistentDataContainer per;
if (memoryWorld != null) {
per = memoryWorld.getBukkit().getPersistentDataContainer();
if (Objects.equals(per.get(dk, PersistentDataType.STRING), getMerger().getGenerator()))
return;
if (memoryWorld != null)
memoryWorld.close();
}
memoryWorld = getMerger().isDatapackMode() ? Failable.get(() ->
getMerger().getGenerator() == null ?
INMS.get().createMemoryWorld(new WorldCreator("memoryworld").seed(getSeedManager().getSeed())) :
INMS.get().createMemoryWorld(NamespacedKey.minecraft(getMerger().getGenerator()), new WorldCreator("memoryworld").seed(getSeedManager().getSeed()))
) : null; // todo: experimental
per = memoryWorld.getBukkit().getPersistentDataContainer();
per.set(dk, PersistentDataType.STRING, getMerger().getGenerator());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override @Override
public void generateMatter(int x, int z, boolean multicore, ChunkContext context) { public void generateMatter(int x, int z, boolean multicore, ChunkContext context) {
getMantle().generateMatter(x, z, multicore, context); getMantle().generateMatter(x, z, multicore, context);
@@ -278,7 +241,6 @@ public class IrisEngine implements Engine {
getData().clearLists(); getData().clearLists();
getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey())); getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey()));
prehotload(); prehotload();
updateMemoryWorld();
setupEngine(); setupEngine();
J.a(() -> { J.a(() -> {
synchronized (ServerConfigurator.class) { synchronized (ServerConfigurator.class) {

View File

@@ -18,32 +18,21 @@
package com.volmit.iris.engine; package com.volmit.iris.engine;
import com.volmit.iris.Iris; import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.mantle.MantleComponent; import com.volmit.iris.engine.mantle.MantleComponent;
import com.volmit.iris.engine.mantle.components.MantleCarvingComponent; import com.volmit.iris.engine.mantle.components.*;
import com.volmit.iris.engine.mantle.components.MantleFluidBodyComponent;
import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.parallel.BurstExecutor; import lombok.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.bukkit.util.BlockVector;
import java.io.File; import java.io.File;
import java.io.IOException; import java.util.stream.Collectors;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
@Data @Data
@EqualsAndHashCode(exclude = "engine") @EqualsAndHashCode(exclude = "engine")
@@ -51,8 +40,9 @@ import java.util.concurrent.atomic.AtomicInteger;
public class IrisEngineMantle implements EngineMantle { public class IrisEngineMantle implements EngineMantle {
private final Engine engine; private final Engine engine;
private final Mantle mantle; private final Mantle mantle;
private final KList<MantleComponent> components; @Getter(AccessLevel.NONE)
private final int radius; private final KMap<Integer, KList<MantleComponent>> components;
private final AtomicCache<KList<Pair<KList<MantleComponent>, Integer>>> componentsCache = new AtomicCache<>();
private final AtomicCache<Integer> radCache = new AtomicCache<>(); private final AtomicCache<Integer> radCache = new AtomicCache<>();
private final MantleObjectComponent object; private final MantleObjectComponent object;
private final MantleJigsawComponent jigsaw; private final MantleJigsawComponent jigsaw;
@@ -60,19 +50,59 @@ public class IrisEngineMantle implements EngineMantle {
public IrisEngineMantle(Engine engine) { public IrisEngineMantle(Engine engine) {
this.engine = engine; this.engine = engine;
this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight()); this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight());
radius = radCache.aquire(this::computeParallaxSize); components = new KMap<>();
components = new KList<>();
registerComponent(new MantleCarvingComponent(this)); registerComponent(new MantleCarvingComponent(this));
registerComponent(new MantleFluidBodyComponent(this)); registerComponent(new MantleFluidBodyComponent(this));
jigsaw = new MantleJigsawComponent(this); jigsaw = new MantleJigsawComponent(this);
registerComponent(jigsaw); registerComponent(jigsaw);
object = new MantleObjectComponent(this); object = new MantleObjectComponent(this);
registerComponent(object); registerComponent(object);
registerComponent(new MantleStaticComponent(this));
}
@Override
public int getRadius() {
if (components.isEmpty()) return 0;
return getComponents().getFirst().getB();
}
@Override
public int getRealRadius() {
if (components.isEmpty()) return 0;
return getComponents().getLast().getB();
}
@Override
public KList<Pair<KList<MantleComponent>, Integer>> getComponents() {
return componentsCache.aquire(() -> {
var list = components.keySet()
.stream()
.sorted()
.map(components::get)
.map(components -> {
int radius = components.stream()
.mapToInt(MantleComponent::getRadius)
.max()
.orElse(0);
return new Pair<>(components, radius);
})
.collect(Collectors.toCollection(KList::new));
int radius = 0;
for (var pair : list.reversed()) {
radius += pair.getB();
pair.setB(Math.ceilDiv(radius, 16));
}
return list;
});
} }
@Override @Override
public void registerComponent(MantleComponent c) { public void registerComponent(MantleComponent c) {
components.add(c); components.computeIfAbsent(c.getPriority(), k -> new KList<>()).add(c);
componentsCache.reset();
} }
@Override @Override
@@ -84,243 +114,4 @@ public class IrisEngineMantle implements EngineMantle {
public MantleObjectComponent getObjectComponent() { public MantleObjectComponent getObjectComponent() {
return object; return object;
} }
private KList<IrisRegion> getAllRegions() {
KList<IrisRegion> r = new KList<>();
for (String i : getEngine().getDimension().getRegions()) {
r.add(getEngine().getData().getRegionLoader().load(i));
}
return r;
}
private KList<IrisBiome> getAllBiomes() {
KList<IrisBiome> r = new KList<>();
for (IrisRegion i : getAllRegions()) {
r.addAll(i.getAllBiomes(getEngine()));
}
return r;
}
private void warn(String ob, BlockVector bv) {
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
Iris.warn("Object " + ob + " has a large size (" + bv + ") and may increase memory usage!");
}
}
private void warnScaled(String ob, BlockVector bv, double ms) {
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
Iris.warn("Object " + ob + " has a large size (" + bv + ") and may increase memory usage! (Object scaled up to " + Form.pc(ms, 2) + ")");
}
}
private int computeParallaxSize() {
Iris.verbose("Calculating the Parallax Size in Parallel");
AtomicInteger xg = new AtomicInteger(0);
AtomicInteger zg = new AtomicInteger();
xg.set(0);
zg.set(0);
int jig = 0;
KSet<String> objects = new KSet<>();
KMap<IrisObjectScale, KList<String>> scalars = new KMap<>();
int x = xg.get();
int z = zg.get();
if (getEngine().getDimension().isUseMantle()) {
KList<IrisRegion> r = getAllRegions();
KList<IrisBiome> b = getAllBiomes();
for (IrisBiome i : b) {
for (IrisObjectPlacement j : i.getObjects()) {
if (j.getScale().canScaleBeyond()) {
scalars.put(j.getScale(), j.getPlace());
} else {
objects.addAll(j.getPlace());
}
}
for (IrisJigsawStructurePlacement j : i.getJigsawStructures()) {
jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension());
}
}
for (IrisRegion i : r) {
for (IrisObjectPlacement j : i.getObjects()) {
if (j.getScale().canScaleBeyond()) {
scalars.put(j.getScale(), j.getPlace());
} else {
objects.addAll(j.getPlace());
}
}
for (IrisJigsawStructurePlacement j : i.getJigsawStructures()) {
jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension());
}
}
for (IrisJigsawStructurePlacement j : getEngine().getDimension().getJigsawStructures()) {
jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension());
}
if (getEngine().getDimension().getStronghold() != null) {
try {
jig = Math.max(jig, getData().getJigsawStructureLoader().load(getEngine().getDimension().getStronghold()).getMaxDimension());
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
}
Iris.verbose("Checking sizes for " + Form.f(objects.size()) + " referenced objects.");
BurstExecutor e = getEngine().getTarget().getBurster().burst(objects.size());
KMap<String, BlockVector> sizeCache = new KMap<>();
for (String i : objects) {
e.queue(() -> {
try {
BlockVector bv = sizeCache.computeIfAbsent(i, (k) -> {
try {
return IrisObject.sampleSize(getData().getObjectLoader().findFile(i));
} catch (IOException ex) {
Iris.reportError(ex);
ex.printStackTrace();
}
return null;
});
if (bv == null) {
throw new RuntimeException();
}
warn(i, bv);
synchronized (xg) {
xg.getAndSet(Math.max(bv.getBlockX(), xg.get()));
}
synchronized (zg) {
zg.getAndSet(Math.max(bv.getBlockZ(), zg.get()));
}
} catch (Throwable ed) {
Iris.reportError(ed);
}
});
}
for (Map.Entry<IrisObjectScale, KList<String>> entry : scalars.entrySet()) {
double ms = entry.getKey().getMaximumScale();
for (String j : entry.getValue()) {
e.queue(() -> {
try {
BlockVector bv = sizeCache.computeIfAbsent(j, (k) -> {
try {
return IrisObject.sampleSize(getData().getObjectLoader().findFile(j));
} catch (IOException ioException) {
Iris.reportError(ioException);
ioException.printStackTrace();
}
return null;
});
if (bv == null) {
throw new RuntimeException();
}
warnScaled(j, bv, ms);
synchronized (xg) {
xg.getAndSet((int) Math.max(Math.ceil(bv.getBlockX() * ms), xg.get()));
}
synchronized (zg) {
zg.getAndSet((int) Math.max(Math.ceil(bv.getBlockZ() * ms), zg.get()));
}
} catch (Throwable ee) {
Iris.reportError(ee);
}
});
}
}
e.complete();
x = xg.get();
z = zg.get();
for (IrisDepositGenerator i : getEngine().getDimension().getDeposits()) {
int max = i.getMaxDimension();
x = Math.max(max, x);
z = Math.max(max, z);
}
for (IrisRegion v : r) {
for (IrisDepositGenerator i : v.getDeposits()) {
int max = i.getMaxDimension();
x = Math.max(max, x);
z = Math.max(max, z);
}
}
for (IrisBiome v : b) {
for (IrisDepositGenerator i : v.getDeposits()) {
int max = i.getMaxDimension();
x = Math.max(max, x);
z = Math.max(max, z);
}
}
} else {
return 0;
}
x = Math.max(z, x);
int u = x;
int c = Math.max(computeCarvingRange(), computeBodyRange());
x = Math.max(jig, x);
x = Math.max(x, c);
x = (Math.max(x, 16) + 16) >> 4;
x = x % 2 == 0 ? x + 1 : x;
Iris.info("Mantle Size: " + x + " Chunks");
Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")");
Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")");
Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")");
return x;
}
private int computeBodyRange() {
int m = 0;
m = Math.max(m, getDimension().getFluidBodies().getMaxRange(getData()));
for (IrisRegion i : getDimension().getAllRegions(getEngine())) {
m = Math.max(m, i.getFluidBodies().getMaxRange(getData()));
}
for (IrisBiome i : getDimension().getAllBiomes(getEngine())) {
m = Math.max(m, i.getFluidBodies().getMaxRange(getData()));
}
return m;
}
private int computeCarvingRange() {
int m = 0;
m = Math.max(m, getDimension().getCarving().getMaxRange(getData()));
for (IrisRegion i : getDimension().getAllRegions(getEngine())) {
m = Math.max(m, i.getCarving().getMaxRange(getData()));
}
for (IrisBiome i : getDimension().getAllBiomes(getEngine())) {
m = Math.max(m, i.getCarving().getMaxRange(getData()));
}
return m;
}
} }

View File

@@ -459,7 +459,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
IrisEngineData ed = getEngine().getEngineData(); IrisEngineData ed = getEngine().getEngineData();
IrisEngineSpawnerCooldown cd = null; IrisEngineSpawnerCooldown cd = null;
for (IrisEngineSpawnerCooldown j : ed.getSpawnerCooldowns()) { for (IrisEngineSpawnerCooldown j : ed.getSpawnerCooldowns().copy()) {
if (j.getSpawner().equals(i.getLoadKey())) { if (j.getSpawner().equals(i.getLoadKey())) {
cd = j; cd = j;
} }

View File

@@ -18,7 +18,6 @@
package com.volmit.iris.engine.actuator; package com.volmit.iris.engine.actuator;
import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedActuator; import com.volmit.iris.engine.framework.EngineAssignedActuator;
import com.volmit.iris.engine.object.IrisBiome; import com.volmit.iris.engine.object.IrisBiome;
@@ -30,18 +29,15 @@ import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Getter; import lombok.Getter;
import org.bukkit.*; import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData> { public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData> {
private static final BlockData AIR = Material.AIR.createBlockData(); private static final BlockData AIR = Material.AIR.createBlockData();
private static final BlockData BEDROCK = Material.BEDROCK.createBlockData(); private static final BlockData BEDROCK = Material.BEDROCK.createBlockData();
private static final BlockData DEEPSLATE = Material.DEEPSLATE.createBlockData();
private static final BlockData LAVA = Material.LAVA.createBlockData(); private static final BlockData LAVA = Material.LAVA.createBlockData();
private static final BlockData GLASS = Material.GLASS.createBlockData(); private static final BlockData GLASS = Material.GLASS.createBlockData();
private static final BlockData CAVE_AIR = Material.CAVE_AIR.createBlockData(); private static final BlockData CAVE_AIR = Material.CAVE_AIR.createBlockData();
private static final BlockData FILLER = Material.STONE.createBlockData();
private IMemoryWorld memoryWorld;
@Getter @Getter
private final RNG rng; private final RNG rng;
@Getter @Getter
@@ -55,20 +51,14 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
@BlockCoordinates @BlockCoordinates
@Override @Override
public void onActuate(int x, int z, Hunk<BlockData> h, boolean multicore, ChunkContext context) { public void onActuate(int x, int z, Hunk<BlockData> h, boolean multicore, ChunkContext context) {
try { PrecisionStopwatch p = PrecisionStopwatch.start();
PrecisionStopwatch p = PrecisionStopwatch.start();
for (int xf = 0; xf < h.getWidth(); xf++) { for (int xf = 0; xf < h.getWidth(); xf++) {
terrainSliver(x, z, xf, h, context); terrainSliver(x, z, xf, h, context);
}
getEngine().getMetrics().getTerrain().put(p.getMilliseconds());
} catch (Exception e) {
e.printStackTrace();
//Iris.error("Fatal Error!", e);
} }
}
getEngine().getMetrics().getTerrain().put(p.getMilliseconds());
}
private int fluidOrHeight(int height) { private int fluidOrHeight(int height) {
return Math.max(getDimension().getFluidHeight(), height); return Math.max(getDimension().getFluidHeight(), height);
@@ -148,11 +138,6 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
continue; continue;
} }
if (getDimension().isEnableExperimentalMerger()) {
h.set(xf, i, zf, FILLER);
continue;
}
BlockData ore = biome.generateOres(realX, i, realZ, rng, getData()); BlockData ore = biome.generateOres(realX, i, realZ, rng, getData());
ore = ore == null ? region.generateOres(realX, i, realZ, rng, getData()) : ore; ore = ore == null ? region.generateOres(realX, i, realZ, rng, getData()) : ore;
ore = ore == null ? getDimension().generateOres(realX, i, realZ, rng, getData()) : ore; ore = ore == null ? getDimension().generateOres(realX, i, realZ, rng, getData()) : ore;
@@ -160,11 +145,7 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
if (ore != null) { if (ore != null) {
h.set(xf, i, zf, ore); h.set(xf, i, zf, ore);
} else { } else {
if (getDimension().isDeepslateLayer() && i < 64) { h.set(xf, i, zf, context.getRock().get(xf, zf));
h.set(xf, i, zf, DEEPSLATE);
} else {
h.set(xf, i, zf, context.getRock().get(xf, zf));
}
} }
} }
} }

View File

@@ -43,15 +43,7 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
IrisDecorator decorator = getDecorator(biome, realX, realZ); IrisDecorator decorator = getDecorator(biome, realX, realZ);
if (decorator != null) { if (decorator != null) {
if (!decorator.isStacking()) { if (!decorator.isStacking()) {
if (height >= 0 || height < getEngine().getHeight()) { data.set(x, height, z, fixFaces(decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()), realX, height, realZ));
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
height--;
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
} else {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
}
}
} else { } else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData()); int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
if (decorator.isScaleStack()) { if (decorator.isScaleStack()) {

View File

@@ -44,15 +44,7 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
return; return;
} }
if (height >= 0 || height < getEngine().getHeight()) { if (height >= 0 || height < getEngine().getHeight()) {
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) { data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
if (height == getDimension().getFluidHeight() - 1) {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
height++;
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
}
} else {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
}
} }
} else { } else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData()); int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());

View File

@@ -40,13 +40,7 @@ public class IrisSeaSurfaceDecorator extends IrisEngineDecorator {
if (decorator != null) { if (decorator != null) {
if (!decorator.isStacking()) { if (!decorator.isStacking()) {
if (height >= 0 || height < getEngine().getHeight()) { if (height >= 0 || height < getEngine().getHeight()) {
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) { data.set(x, height + 1, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
height++;
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
} else {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
}
} }
} else { } else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData()); int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());

View File

@@ -51,13 +51,7 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
} }
if (!decorator.isStacking()) { if (!decorator.isStacking()) {
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) { data.set(x, height + 1, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
height++;
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
} else {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
}
} else { } else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData()); int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
if (decorator.isScaleStack()) { if (decorator.isScaleStack()) {

View File

@@ -20,12 +20,12 @@ package com.volmit.iris.engine.framework;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.events.IrisLootEvent;
import com.volmit.iris.core.gui.components.RenderType; import com.volmit.iris.core.gui.components.RenderType;
import com.volmit.iris.core.gui.components.Renderer; import com.volmit.iris.core.gui.components.Renderer;
import com.volmit.iris.core.link.Identifier; import com.volmit.iris.core.link.Identifier;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant; import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.core.nms.container.BlockPos; import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.core.pregenerator.ChunkUpdater; import com.volmit.iris.core.pregenerator.ChunkUpdater;
@@ -76,7 +76,6 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.awt.*;
import java.awt.Color; import java.awt.Color;
import java.util.Arrays; import java.util.Arrays;
import java.util.Set; import java.util.Set;
@@ -112,10 +111,6 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
EngineExecutionEnvironment getExecution(); EngineExecutionEnvironment getExecution();
IMemoryWorld getMemoryWorld();
IrisMerger getMerger();
double getMaxBiomeObjectDensity(); double getMaxBiomeObjectDensity();
double getMaxBiomeDecoratorDensity(); double getMaxBiomeDecoratorDensity();
@@ -473,7 +468,10 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
} }
@Override @Override
default void injectTables(KList<IrisLootTable> list, IrisLootReference r) { default void injectTables(KList<IrisLootTable> list, IrisLootReference r, boolean fallback) {
if (r.getMode().equals(IrisLootMode.FALLBACK) && !fallback)
return;
if (r.getMode().equals(IrisLootMode.CLEAR) || r.getMode().equals(IrisLootMode.REPLACE)) { if (r.getMode().equals(IrisLootMode.CLEAR) || r.getMode().equals(IrisLootMode.REPLACE)) {
list.clear(); list.clear();
} }
@@ -508,10 +506,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
IrisBiome biomeUnder = ry < he ? getComplex().getCaveBiomeStream().get(rx, rz) : biomeSurface; IrisBiome biomeUnder = ry < he ? getComplex().getCaveBiomeStream().get(rx, rz) : biomeSurface;
double multiplier = 1D * getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier(); double multiplier = 1D * getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier();
injectTables(tables, getDimension().getLoot()); boolean fallback = tables.isEmpty();
injectTables(tables, region.getLoot()); injectTables(tables, getDimension().getLoot(), fallback);
injectTables(tables, biomeSurface.getLoot()); injectTables(tables, region.getLoot(), fallback);
injectTables(tables, biomeUnder.getLoot()); injectTables(tables, biomeSurface.getLoot(), fallback);
injectTables(tables, biomeUnder.getLoot(), fallback);
if (tables.isNotEmpty()) { if (tables.isNotEmpty()) {
int target = (int) Math.round(tables.size() * multiplier); int target = (int) Math.round(tables.size() * multiplier);
@@ -532,15 +531,15 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
default void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, World world, int x, int y, int z, int mgf) { default void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, World world, int x, int y, int z, int mgf) {
KList<ItemStack> items = new KList<>(); KList<ItemStack> items = new KList<>();
int b = 4;
for (IrisLootTable i : tables) { for (IrisLootTable i : tables) {
if (i == null) if (i == null)
continue; continue;
b++;
items.addAll(i.getLoot(debug, rng, slot, world, x, y, z)); items.addAll(i.getLoot(debug, rng, slot, world, x, y, z));
} }
if (IrisLootEvent.callLootEvent(items, inv, world, x, y, z))
return;
if (PaperLib.isPaper() && getWorld().hasRealWorld()) { if (PaperLib.isPaper() && getWorld().hasRealWorld()) {
PaperLib.getChunkAtAsync(getWorld().realWorld(), x >> 4, z >> 4).thenAccept((c) -> { PaperLib.getChunkAtAsync(getWorld().realWorld(), x >> 4, z >> 4).thenAccept((c) -> {
Runnable r = () -> { Runnable r = () -> {
for (ItemStack i : items) { for (ItemStack i : items) {
@@ -827,6 +826,13 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
return new PlacedObject(piece.getPlacementOptions(), getData().getObjectLoader().load(object), id, x, z); return new PlacedObject(piece.getPlacementOptions(), getData().getObjectLoader().load(object), id, x, z);
} }
for (var staticPlacement : getDimension().getStaticPlacements().getObjects()) {
IrisObjectPlacement i = staticPlacement.placement();
if (i.getPlace().contains(object)) {
return new PlacedObject(i, getData().getObjectLoader().load(object), id, x, z);
}
}
IrisRegion region = getRegion(x, z); IrisRegion region = getRegion(x, z);
for (IrisObjectPlacement i : region.getObjects()) { for (IrisObjectPlacement i : region.getObjects()) {

View File

@@ -1,8 +1,10 @@
package com.volmit.iris.engine.framework; package com.volmit.iris.engine.framework;
import com.volmit.iris.core.loader.IrisData;
import java.util.function.Function; import java.util.function.Function;
public interface ListFunction<T, R> extends Function<T, R> { public interface ListFunction<R> extends Function<IrisData, R> {
String key(); String key();
String fancyName(); String fancyName();
} }

View File

@@ -30,7 +30,7 @@ import org.bukkit.inventory.Inventory;
public interface LootProvider { public interface LootProvider {
void scramble(Inventory inventory, RNG rng); void scramble(Inventory inventory, RNG rng);
void injectTables(KList<IrisLootTable> list, IrisLootReference r); void injectTables(KList<IrisLootTable> list, IrisLootReference r, boolean fallback);
KList<IrisLootTable> getLootTables(RNG rng, Block b); KList<IrisLootTable> getLootTables(RNG rng, Block b);

View File

@@ -5,7 +5,7 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisLootEvent; import com.volmit.iris.core.events.IrisLootEvent;
import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.object.IObjectPlacer; import com.volmit.iris.engine.object.IObjectPlacer;
import com.volmit.iris.engine.object.InventorySlotType; import com.volmit.iris.engine.object.InventorySlotType;
@@ -20,10 +20,7 @@ import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
@Getter @Getter
@@ -65,8 +62,6 @@ public class WorldObjectPlacer implements IObjectPlacer {
RNG rx = new RNG(Cache.key(x, z)); RNG rx = new RNG(Cache.key(x, z));
KList<IrisLootTable> tables = engine.getLootTables(rx, block); KList<IrisLootTable> tables = engine.getLootTables(rx, block);
Inventory inventory = null;
try { try {
Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables)); Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables));

View File

@@ -30,7 +30,6 @@ import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer; import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
import com.volmit.iris.util.matter.slices.container.JigsawStructureContainer;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer; import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import lombok.Data; import lombok.Data;
@@ -62,7 +61,7 @@ public class PlannedStructure {
this.structure = structure; this.structure = structure;
this.position = position; this.position = position;
this.rng = rng; this.rng = rng;
this.forcePlace = forcePlace; this.forcePlace = forcePlace || structure.isForcePlace();
this.data = structure.getLoader(); this.data = structure.getLoader();
generateStartPiece(); generateStartPiece();
@@ -152,12 +151,10 @@ public class PlannedStructure {
int id = rng.i(0, Integer.MAX_VALUE); int id = rng.i(0, Integer.MAX_VALUE);
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece()); JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
JigsawStructureContainer structureContainer = JigsawStructureContainer.toContainer(structure);
i.setRealPositions(xx, height, zz, placer); i.setRealPositions(xx, height, zz, placer);
return v.place(xx, height, zz, placer, options, rng, (b, data) -> { return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id); e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
e.set(b.getX(), b.getY(), b.getZ(), container); e.set(b.getX(), b.getY(), b.getZ(), container);
e.set(b.getX(), b.getY(), b.getZ(), structureContainer);
if (data instanceof IrisBlockData d) { if (data instanceof IrisBlockData d) {
e.set(b.getX(), b.getY(), b.getZ(), d.getCustom()); e.set(b.getX(), b.getY(), b.getZ(), d.getCustom());
} }

View File

@@ -20,10 +20,10 @@ package com.volmit.iris.engine.mantle;
import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.engine.IrisComplex; import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget; import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.framework.SeedManager;
import com.volmit.iris.engine.mantle.components.MantleJigsawComponent; import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
import com.volmit.iris.engine.mantle.components.MantleObjectComponent; import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
import com.volmit.iris.engine.object.IObjectPlacer; import com.volmit.iris.engine.object.IObjectPlacer;
@@ -44,7 +44,6 @@ import com.volmit.iris.util.matter.*;
import com.volmit.iris.util.matter.slices.UpdateMatter; import com.volmit.iris.util.matter.slices.UpdateMatter;
import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -59,7 +58,9 @@ public interface EngineMantle extends IObjectPlacer {
int getRadius(); int getRadius();
KList<MantleComponent> getComponents(); int getRealRadius();
KList<Pair<KList<MantleComponent>, Integer>> getComponents();
void registerComponent(MantleComponent c); void registerComponent(MantleComponent c);
@@ -187,39 +188,37 @@ public interface EngineMantle extends IObjectPlacer {
return getEngine().burst(); return getEngine().burst();
} }
default int getRealRadius() {
return (int) Math.ceil(getRadius() / 2D);
}
@ChunkCoordinates @ChunkCoordinates
default void generateMatter(int x, int z, boolean multicore, ChunkContext context) { default void generateMatter(int x, int z, boolean multicore, ChunkContext context) {
synchronized (this) { if (!getEngine().getDimension().isUseMantle()) {
if (!getEngine().getDimension().isUseMantle()) { return;
return; }
}
int s = getRealRadius(); try (MantleWriter writer = getMantle().write(this, x, z, getRadius() * 2)) {
BurstExecutor burst = burst().burst(multicore); var iterator = getComponents().iterator();
MantleWriter writer = getMantle().write(this, x, z, s * 2); while (iterator.hasNext()) {
for (int i = -s; i <= s; i++) { var pair = iterator.next();
for (int j = -s; j <= s; j++) { int radius = pair.getB();
int xx = i + x; boolean last = !iterator.hasNext();
int zz = j + z; BurstExecutor burst = burst().burst(radius * 2 + 1);
burst.queue(() -> { burst.setMulticore(multicore);
IrisContext.touch(getEngine().getContext());
getMantle().raiseFlag(xx, zz, MantleFlag.PLANNED, () -> {
MantleChunk mc = getMantle().getChunk(xx, zz);
for (MantleComponent k : getComponents()) { for (int i = -radius; i <= radius; i++) {
generateMantleComponent(writer, xx, zz, k, mc, context); for (int j = -radius; j <= radius; j++) {
} int xx = x + i;
int zz = z + j;
MantleChunk mc = getMantle().getChunk(xx, zz);
burst.queue(() -> {
IrisContext.touch(getEngine().getContext());
pair.getA().forEach(k -> generateMantleComponent(writer, xx, zz, k, mc, context));
if (last) mc.flag(MantleFlag.PLANNED, true);
}); });
}); }
} }
}
burst.complete(); burst.complete();
}
} }
} }

View File

@@ -29,4 +29,5 @@ import lombok.ToString;
public abstract class IrisMantleComponent implements MantleComponent { public abstract class IrisMantleComponent implements MantleComponent {
private final EngineMantle engineMantle; private final EngineMantle engineMantle;
private final MantleFlag flag; private final MantleFlag flag;
private final int priority;
} }

View File

@@ -26,11 +26,12 @@ import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.BurstExecutor;
import org.jetbrains.annotations.NotNull;
public interface MantleComponent { public interface MantleComponent extends Comparable<MantleComponent> {
default int getRadius() { int getPriority();
return getEngineMantle().getRealRadius();
} int getRadius();
default IrisData getData() { default IrisData getData() {
return getEngineMantle().getData(); return getEngineMantle().getData();
@@ -62,4 +63,9 @@ public interface MantleComponent {
@ChunkCoordinates @ChunkCoordinates
void generateLayer(MantleWriter writer, int x, int z, ChunkContext context); void generateLayer(MantleWriter writer, int x, int z, ChunkContext context);
@Override
default int compareTo(@NotNull MantleComponent o) {
return Integer.compare(getPriority(), o.getPriority());
}
} }

View File

@@ -35,7 +35,6 @@ import com.volmit.iris.util.mantle.MantleChunk;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.Matter;
import lombok.Data; import lombok.Data;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@@ -44,7 +43,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
@Data @Data
public class MantleWriter implements IObjectPlacer { public class MantleWriter implements IObjectPlacer, AutoCloseable {
private final EngineMantle engineMantle; private final EngineMantle engineMantle;
private final Mantle mantle; private final Mantle mantle;
private final KMap<Long, MantleChunk> cachedChunks; private final KMap<Long, MantleChunk> cachedChunks;
@@ -62,7 +61,7 @@ public class MantleWriter implements IObjectPlacer {
for (int i = -radius; i <= radius; i++) { for (int i = -radius; i <= radius; i++) {
for (int j = -radius; j <= radius; j++) { for (int j = -radius; j <= radius; j++) {
cachedChunks.put(Cache.key(i + x, j + z), mantle.getChunk(i + x, j + z)); cachedChunks.put(Cache.key(i + x, j + z), mantle.getChunk(i + x, j + z).use());
} }
} }
} }
@@ -633,4 +632,12 @@ public class MantleWriter implements IObjectPlacer {
return cx >= this.x - radius && cx <= this.x + radius return cx >= this.x - radius && cx <= this.x + radius
&& cz >= this.z - radius && cz <= this.z + radius; && cz >= this.z - radius && cz <= this.z + radius;
} }
@Override
public void close() {
cachedChunks.values().removeIf(c -> {
c.release();
return true;
});
}
} }

View File

@@ -29,10 +29,14 @@ import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import lombok.Getter;
@Getter
public class MantleCarvingComponent extends IrisMantleComponent { public class MantleCarvingComponent extends IrisMantleComponent {
private final int radius = computeRadius();
public MantleCarvingComponent(EngineMantle engineMantle) { public MantleCarvingComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.CARVED); super(engineMantle, MantleFlag.CARVED, 0);
} }
@Override @Override
@@ -56,4 +60,21 @@ public class MantleCarvingComponent extends IrisMantleComponent {
private void carve(IrisCarving carving, MantleWriter writer, RNG rng, int cx, int cz) { private void carve(IrisCarving carving, MantleWriter writer, RNG rng, int cx, int cz) {
carving.doCarving(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4); carving.doCarving(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4);
} }
private int computeRadius() {
var dimension = getDimension();
int max = 0;
max = Math.max(max, dimension.getCarving().getMaxRange(getData()));
for (var i : dimension.getAllRegions(this::getData)) {
max = Math.max(max, i.getCarving().getMaxRange(getData()));
}
for (var i : dimension.getAllBiomes(this::getData)) {
max = Math.max(max, i.getCarving().getMaxRange(getData()));
}
return max;
}
} }

View File

@@ -29,10 +29,14 @@ import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import lombok.Getter;
@Getter
public class MantleFluidBodyComponent extends IrisMantleComponent { public class MantleFluidBodyComponent extends IrisMantleComponent {
private final int radius = computeRadius();
public MantleFluidBodyComponent(EngineMantle engineMantle) { public MantleFluidBodyComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.FLUID_BODIES); super(engineMantle, MantleFlag.FLUID_BODIES, 0);
} }
@Override @Override
@@ -56,4 +60,20 @@ public class MantleFluidBodyComponent extends IrisMantleComponent {
private void generate(IrisFluidBodies bodies, MantleWriter writer, RNG rng, int cx, int cz) { private void generate(IrisFluidBodies bodies, MantleWriter writer, RNG rng, int cx, int cz) {
bodies.generate(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4); bodies.generate(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4);
} }
private int computeRadius() {
int max = 0;
max = Math.max(max, getDimension().getFluidBodies().getMaxRange(getData()));
for (IrisRegion i : getDimension().getAllRegions(this::getData)) {
max = Math.max(max, i.getFluidBodies().getMaxRange(getData()));
}
for (IrisBiome i : getDimension().getAllBiomes(this::getData)) {
max = Math.max(max, i.getFluidBodies().getMaxRange(getData()));
}
return max;
}
} }

View File

@@ -34,15 +34,18 @@ import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer; import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.noise.CNG; import com.volmit.iris.util.noise.CNG;
import lombok.Getter;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
public class MantleJigsawComponent extends IrisMantleComponent { public class MantleJigsawComponent extends IrisMantleComponent {
@Getter
private final int radius = computeRadius();
private final CNG cng; private final CNG cng;
public MantleJigsawComponent(EngineMantle engineMantle) { public MantleJigsawComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.JIGSAW); super(engineMantle, MantleFlag.JIGSAW, 1);
cng = NoiseStyle.STATIC.create(new RNG(jigsaw())); cng = NoiseStyle.STATIC.create(new RNG(jigsaw()));
} }
@@ -168,4 +171,29 @@ public class MantleJigsawComponent extends IrisMantleComponent {
private long jigsaw() { private long jigsaw() {
return getEngineMantle().getEngine().getSeedManager().getJigsaw(); return getEngineMantle().getEngine().getSeedManager().getJigsaw();
} }
private int computeRadius() {
var dimension = getDimension();
KSet<String> structures = new KSet<>();
for (var placement : dimension.getJigsawStructures()) {
structures.add(placement.getStructure());
}
for (var region : dimension.getAllRegions(this::getData)) {
for (var placement : region.getJigsawStructures()) {
structures.add(placement.getStructure());
}
}
for (var biome : dimension.getAllBiomes(this::getData)) {
for (var placement : biome.getJigsawStructures()) {
structures.add(placement.getStructure());
}
}
int max = 0;
for (var structure : structures) {
max = Math.max(max, getData().getJigsawStructureLoader().load(structure).getMaxDimension());
}
return max;
}
} }

View File

@@ -19,28 +19,43 @@
package com.volmit.iris.engine.mantle.components; package com.volmit.iris.engine.mantle.components;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.mantle.IrisMantleComponent; import com.volmit.iris.engine.mantle.IrisMantleComponent;
import com.volmit.iris.engine.mantle.MantleWriter; import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisBlockData; import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.documentation.BlockCoordinates; import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.MatterStructurePOI; import com.volmit.iris.util.matter.MatterStructurePOI;
import com.volmit.iris.util.noise.CNG; import com.volmit.iris.util.noise.CNG;
import com.volmit.iris.util.noise.NoiseType; import com.volmit.iris.util.noise.NoiseType;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import lombok.Getter;
import org.bukkit.util.BlockVector;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@Getter
public class MantleObjectComponent extends IrisMantleComponent { public class MantleObjectComponent extends IrisMantleComponent {
private final int radius = computeRadius();
public MantleObjectComponent(EngineMantle engineMantle) { public MantleObjectComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.OBJECT); super(engineMantle, MantleFlag.OBJECT, 1);
} }
@Override @Override
@@ -146,4 +161,94 @@ public class MantleObjectComponent extends IrisMantleComponent {
return v; return v;
} }
private int computeRadius() {
var dimension = getDimension();
KSet<String> objects = new KSet<>();
KMap<IrisObjectScale, KList<String>> scalars = new KMap<>();
for (var region : dimension.getAllRegions(this::getData)) {
for (var placement : region.getObjects()) {
if (placement.getScale().canScaleBeyond()) {
scalars.put(placement.getScale(), placement.getPlace());
} else {
objects.addAll(placement.getPlace());
}
}
for (var biome : region.getAllBiomes(this::getData)) {
for (var placement : biome.getObjects()) {
if (placement.getScale().canScaleBeyond()) {
scalars.put(placement.getScale(), placement.getPlace());
} else {
objects.addAll(placement.getPlace());
}
}
}
}
return computeObjectRadius(objects, scalars, getEngineMantle().getTarget().getBurster(), getData());
}
static int computeObjectRadius(KSet<String> objects, KMap<IrisObjectScale, KList<String>> scalars, MultiBurst burst, IrisData data) {
AtomicInteger x = new AtomicInteger();
AtomicInteger z = new AtomicInteger();
BurstExecutor e = burst.burst(objects.size());
KMap<String, BlockVector> sizeCache = new KMap<>();
for (String loadKey : objects) {
e.queue(() -> {
try {
BlockVector bv = sampleSize(sizeCache, data, loadKey);
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
Iris.warn("Object " + loadKey + " has a large size (" + bv + ") and may increase memory usage!");
}
x.getAndUpdate(i -> Math.max(bv.getBlockX(), i));
z.getAndUpdate(i -> Math.max(bv.getBlockZ(), i));
} catch (Throwable ed) {
Iris.reportError(ed);
}
});
}
for (Map.Entry<IrisObjectScale, KList<String>> entry : scalars.entrySet()) {
double ms = entry.getKey().getMaximumScale();
for (String loadKey : entry.getValue()) {
e.queue(() -> {
try {
BlockVector bv = sampleSize(sizeCache, data, loadKey);
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
Iris.warn("Object " + loadKey + " has a large size (" + bv + ") and may increase memory usage! (Object scaled up to " + Form.pc(ms, 2) + ")");
}
x.getAndUpdate(i -> (int) Math.max(Math.ceil(bv.getBlockX() * ms), i));
x.getAndUpdate(i -> (int) Math.max(Math.ceil(bv.getBlockZ() * ms), i));
} catch (Throwable ee) {
Iris.reportError(ee);
}
});
}
}
e.complete();
return Math.max(x.get(), z.get());
}
private static BlockVector sampleSize(KMap<String, BlockVector> sizeCache, IrisData data, String loadKey) {
BlockVector bv = sizeCache.computeIfAbsent(loadKey, (k) -> {
try {
return IrisObject.sampleSize(data.getObjectLoader().findFile(loadKey));
} catch (IOException ioException) {
Iris.reportError(ioException);
ioException.printStackTrace();
}
return null;
});
return Objects.requireNonNull(bv, "sampleSize returned a null block vector");
}
} }

View File

@@ -0,0 +1,59 @@
package com.volmit.iris.engine.mantle.components;
import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.mantle.IrisMantleComponent;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.IrisObjectScale;
import com.volmit.iris.engine.object.IrisStaticPlacement;
import com.volmit.iris.engine.object.NoiseStyle;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.noise.CNG;
import lombok.Getter;
public class MantleStaticComponent extends IrisMantleComponent {
private final CNG cng;
@Getter
private final int radius = computeRadius();
public MantleStaticComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.STATIC, 1);
cng = NoiseStyle.STATIC.create(new RNG(seed()));
}
@Override
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
RNG rng = new RNG(cng.fit(Integer.MIN_VALUE, Integer.MAX_VALUE, x, z));
for (IrisStaticPlacement placement : getDimension().getStaticPlacements().getAll(x, z)) {
placement.place(writer, rng, getData());
}
}
private int computeRadius() {
var placements = getDimension().getStaticPlacements();
KSet<String> objects = new KSet<>();
KMap<IrisObjectScale, KList<String>> scalars = new KMap<>();
for (var staticPlacement : placements.getObjects()) {
var placement = staticPlacement.placement();
if (placement.getScale().canScaleBeyond()) {
scalars.put(placement.getScale(), placement.getPlace());
} else {
objects.addAll(placement.getPlace());
}
}
int jigsaw = placements.getStructures()
.stream()
.mapToInt(staticPlacement -> staticPlacement.maxDimension(getData()))
.max()
.orElse(0);
int object = MantleObjectComponent.computeObjectRadius(objects, scalars, getEngineMantle().getTarget().getBurster(), getData());
return Math.max(jigsaw, object);
}
}

View File

@@ -20,10 +20,7 @@ package com.volmit.iris.engine.modifier;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier; import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.object.IrisBiome; import com.volmit.iris.engine.object.*;
import com.volmit.iris.engine.object.IrisDepositGenerator;
import com.volmit.iris.engine.object.IrisObject;
import com.volmit.iris.engine.object.IrisRegion;
import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.HeightMap; import com.volmit.iris.util.data.HeightMap;
@@ -45,30 +42,26 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
@Override @Override
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore, ChunkContext context) { public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore, ChunkContext context) {
PrecisionStopwatch p = PrecisionStopwatch.start(); PrecisionStopwatch p = PrecisionStopwatch.start();
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16), multicore, context); generateDeposits(output, Math.floorDiv(x, 16), Math.floorDiv(z, 16), multicore, context);
getEngine().getMetrics().getDeposit().put(p.getMilliseconds()); getEngine().getMetrics().getDeposit().put(p.getMilliseconds());
} }
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z, boolean multicore, ChunkContext context) { public void generateDeposits(Hunk<BlockData> terrain, int x, int z, boolean multicore, ChunkContext context) {
RNG ro = rx.nextParallelRNG(x * x).nextParallelRNG(z * z);
IrisRegion region = context.getRegion().get(7, 7); IrisRegion region = context.getRegion().get(7, 7);
IrisBiome biome = context.getBiome().get(7, 7); IrisBiome biome = context.getBiome().get(7, 7);
BurstExecutor burst = burst().burst(multicore); BurstExecutor burst = burst().burst(multicore);
long seed = x * 341873128712L + z * 132897987541L;
for (IrisDepositGenerator k : getDimension().getDeposits()) { for (IrisDepositGenerator k : getDimension().getDeposits()) {
burst.queue(() -> generate(k, terrain, ro, x, z, false, context)); burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(seed), x, z, false, context));
} }
for (IrisDepositGenerator k : region.getDeposits()) { for (IrisDepositGenerator k : region.getDeposits()) {
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) { burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(seed), x, z, false, context));
burst.queue(() -> generate(k, terrain, ro, x, z, false, context));
}
} }
for (IrisDepositGenerator k : biome.getDeposits()) { for (IrisDepositGenerator k : biome.getDeposits()) {
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) { burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(seed), x, z, false, context));
burst.queue(() -> generate(k, terrain, ro, x, z, false, context));
}
} }
burst.complete(); burst.complete();
} }
@@ -78,45 +71,48 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
} }
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, HeightMap he, ChunkContext context) { public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, HeightMap he, ChunkContext context) {
for (int l = 0; l < rng.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) { if (k.getSpawnChance() < rng.d())
return;
for (int l = 0; l < rng.i(k.getMinPerChunk(), k.getMaxPerChunk() + 1); l++) {
if (k.getPerClumpSpawnChance() < rng.d())
continue;
IrisObject clump = k.getClump(rng, getData()); IrisObject clump = k.getClump(rng, getData());
int af = (int) Math.floor(clump.getW() / 2D); int dim = clump.getW();
int bf = (int) Math.floor(16D - (clump.getW() / 2D)); int min = dim / 2;
int max = (int) (16D - dim / 2D);
if (af > bf || af < 0 || bf > 15) { if (min > max || min < 0 || max > 15) {
af = 6; min = 6;
bf = 9; max = 9;
} }
af = Math.max(af - 1, 0); int x = rng.i(min, max + 1);
int x = rng.i(af, bf); int z = rng.i(min, max + 1);
int z = rng.i(af, bf);
int height = (he != null ? he.getHeight((cx << 4) + x, (cz << 4) + z) : (int) (Math.round( int height = (he != null ? he.getHeight((cx << 4) + x, (cz << 4) + z) : (int) (Math.round(
context.getHeight().get(x, z) context.getHeight().get(x, z)
))) - 7; ))) - 7;
if (height <= 0) { if (height <= 0)
return; continue;
}
int i = Math.max(0, k.getMinHeight()); int minY = Math.max(0, k.getMinHeight());
// TODO: WARNING HEIGHT // TODO: WARNING HEIGHT
int a = Math.min(height, Math.min(getEngine().getHeight(), k.getMaxHeight())); int maxY = Math.min(height, Math.min(getEngine().getHeight(), k.getMaxHeight()));
if (i >= a) { if (minY >= maxY)
return; continue;
}
int h = rng.i(i, a); int y = rng.i(minY, maxY + 1);
if (h > k.getMaxHeight() || h < k.getMinHeight() || h > height - 2) { if (y > k.getMaxHeight() || y < k.getMinHeight() || y > height - 2)
return; continue;
}
for (BlockVector j : clump.getBlocks().keySet()) { for (BlockVector j : clump.getBlocks().keySet()) {
int nx = j.getBlockX() + x; int nx = j.getBlockX() + x;
int ny = j.getBlockY() + h; int ny = j.getBlockY() + y;
int nz = j.getBlockZ() + z; int nz = j.getBlockZ() + z;
if (ny > height || nx > 15 || nx < 0 || ny > getEngine().getHeight() || ny < 0 || nz < 0 || nz > 15) { if (ny > height || nx > 15 || nx < 0 || ny > getEngine().getHeight() || ny < 0 || nz < 0 || nz > 15) {

View File

@@ -0,0 +1,13 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.util.collection.KList;
import org.bukkit.block.data.BlockData;
public interface IObjectLoot {
KList<IrisBlockData> getFilter();
KList<BlockData> getFilter(IrisData manager);
boolean isExact();
String getName();
int getWeight();
}

View File

@@ -37,12 +37,10 @@ public class IrisBiomeCustomSpawn {
private EntityType type = EntityType.COW; private EntityType type = EntityType.COW;
@MinNumber(1) @MinNumber(1)
@MaxNumber(20)
@Desc("The min to spawn") @Desc("The min to spawn")
private int minCount = 2; private int minCount = 2;
@MinNumber(1) @MinNumber(1)
@MaxNumber(20)
@Desc("The max to spawn") @Desc("The max to spawn")
private int maxCount = 5; private int maxCount = 5;

View File

@@ -67,10 +67,6 @@ public class IrisCarving {
@BlockCoordinates @BlockCoordinates
public void doCarving(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int waterHint) { public void doCarving(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, int waterHint) {
if (!engine.getDimension().isDoCaves()) {
return;
}
if (caves.isNotEmpty()) { if (caves.isNotEmpty()) {
for (IrisCavePlacer i : caves) { for (IrisCavePlacer i : caves) {
i.generateCave(writer, rng, engine, x, y, z, waterHint); i.generateCave(writer, rng, engine, x, y, z, waterHint);

View File

@@ -22,13 +22,14 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*; import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.math.BlockPosition;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.util.BlockVector;
@Snippet("deposit") @Snippet("deposit")
@Accessors(chain = true) @Accessors(chain = true)
@@ -69,6 +70,14 @@ public class IrisDepositGenerator {
@MaxNumber(2048) @MaxNumber(2048)
@Desc("The minimum amount of clumps per chunk") @Desc("The minimum amount of clumps per chunk")
private int minPerChunk = 0; private int minPerChunk = 0;
@MinNumber(0)
@MaxNumber(1)
@Desc("The change of the deposit spawning in a chunk")
private double spawnChance = 1;
@MinNumber(0)
@MaxNumber(1)
@Desc("The change of the a clump spawning in a chunk")
private double perClumpSpawnChance = 1;
@Required @Required
@ArrayType(min = 1, type = IrisBlockData.class) @ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The palette of blocks to be used in this deposit generator") @Desc("The palette of blocks to be used in this deposit generator")
@@ -90,35 +99,62 @@ public class IrisDepositGenerator {
return objectsf; return objectsf;
}); });
return objects.get(rng.i(0, objects.size() - 1)); return objects.get(rng.i(0, objects.size()));
} }
public int getMaxDimension() { public int getMaxDimension() {
return Math.min(11, (int) Math.round(Math.pow(maxSize, 1D / 3D))); return Math.min(11, (int) Math.ceil(Math.cbrt(maxSize)));
} }
private IrisObject generateClumpObject(RNG rngv, IrisData rdata) { private IrisObject generateClumpObject(RNG rngv, IrisData rdata) {
int s = rngv.i(minSize, maxSize); int s = rngv.i(minSize, maxSize + 1);
int dim = Math.min(11, (int) Math.round(Math.pow(maxSize, 1D / 3D))); if (s == 1) {
int w = dim / 2; IrisObject o = new IrisObject(1, 1, 1);
o.getBlocks().put(o.getCenter(), nextBlock(rngv, rdata));
return o;
}
int dim = Math.min(11, (int) Math.ceil(Math.cbrt(s)));
IrisObject o = new IrisObject(dim, dim, dim); IrisObject o = new IrisObject(dim, dim, dim);
if (s == 1) { int volume = dim * dim * dim;
o.getBlocks().put(o.getCenter(), nextBlock(rngv, rdata)); if (s >= volume) {
} else { int x = 0, y = 0, z = 0;
while (s > 0) {
s--; while (z < dim) {
BlockVector ang = new BlockVector(rngv.i(-w, w), rngv.i(-w, w), rngv.i(-w, w)); o.setUnsigned(x++, y, z, nextBlock(rngv, rdata));
BlockVector pos = o.getCenter().clone().add(ang).toBlockVector();
o.getBlocks().put(pos, nextBlock(rngv, rdata)); if (x == dim) {
x = 0;
y++;
}
if (y == dim) {
y = 0;
z++;
}
} }
return o;
}
KSet<BlockPosition> set = new KSet<>();
while (s > 0) {
BlockPosition ang = new BlockPosition(
rngv.i(0, dim),
rngv.i(0, dim),
rngv.i(0, dim)
);
if (!set.add(ang)) continue;
s--;
o.setUnsigned(ang.getX(), ang.getY(), ang.getZ(), nextBlock(rngv, rdata));
} }
return o; return o;
} }
private BlockData nextBlock(RNG rngv, IrisData rdata) { private BlockData nextBlock(RNG rngv, IrisData rdata) {
return getBlockData(rdata).get(rngv.i(0, getBlockData(rdata).size() - 1)); return getBlockData(rdata).get(rngv.i(0, getBlockData(rdata).size()));
} }
public KList<BlockData> getBlockData(IrisData rdata) { public KList<BlockData> getBlockData(IrisData rdata) {

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.engine.object;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant; import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.IDataFixer; import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*; import com.volmit.iris.engine.object.annotations.*;
@@ -144,10 +145,6 @@ public class IrisDimension extends IrisRegistrant {
@RegistryListResource(IrisJigsawStructure.class) @RegistryListResource(IrisJigsawStructure.class)
@Desc("If defined, Iris will place the given jigsaw structure where minecraft should place the overworld stronghold.") @Desc("If defined, Iris will place the given jigsaw structure where minecraft should place the overworld stronghold.")
private String stronghold; private String stronghold;
@Desc("Iris merger [Experimental] ( Deprecated for v3 )")
private IrisMerger merger = new IrisMerger();
@Desc("Cheap temp solution till v4 arrives [ Enables the experimental merger ] Requires studio restart to take effect!")
private boolean EnableExperimentalMerger = false;
@Desc("If set to true, Iris will remove chunks to allow visualizing cross sections of chunks easily") @Desc("If set to true, Iris will remove chunks to allow visualizing cross sections of chunks easily")
private boolean debugChunkCrossSections = false; private boolean debugChunkCrossSections = false;
@Desc("Vertically split up the biome palettes with 3 air blocks in between to visualize them") @Desc("Vertically split up the biome palettes with 3 air blocks in between to visualize them")
@@ -182,10 +179,6 @@ public class IrisDimension extends IrisRegistrant {
private KList<IrisBlockDrops> blockDrops = new KList<>(); private KList<IrisBlockDrops> blockDrops = new KList<>();
@Desc("Should bedrock be generated or not.") @Desc("Should bedrock be generated or not.")
private boolean bedrock = true; private boolean bedrock = true;
@Desc("If under 0 deepslate will be placed instead of the rockPalette")
private boolean deepslateLayer = true;
@Desc("If true caves get made")
private boolean doCaves = true;
@MinNumber(0) @MinNumber(0)
@MaxNumber(1) @MaxNumber(1)
@Desc("The land chance. Up to 1.0 for total land or 0.0 for total sea") @Desc("The land chance. Up to 1.0 for total land or 0.0 for total sea")
@@ -317,6 +310,8 @@ public class IrisDimension extends IrisRegistrant {
@MaxNumber(318) @MaxNumber(318)
@Desc("The Subterrain Fluid Layer Height") @Desc("The Subterrain Fluid Layer Height")
private int caveLavaHeight = 8; private int caveLavaHeight = 8;
@Desc("Static Placements for objects and structures")
private IrisStaticPlacements staticPlacements = new IrisStaticPlacements();
public int getMaxHeight() { public int getMaxHeight() {
return (int) getDimensionHeight().getMax(); return (int) getDimensionHeight().getMax();
@@ -495,10 +490,10 @@ public class IrisDimension extends IrisRegistrant {
{ {
"pack": { "pack": {
"description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.", "description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.",
"pack_format": 10 "pack_format": {}
} }
} }
"""); """.replace("{}", INMS.get().getDataVersion().getPackFormat() + ""));
} catch (IOException e) { } catch (IOException e) {
Iris.reportError(e); Iris.reportError(e);
e.printStackTrace(); e.printStackTrace();

View File

@@ -74,6 +74,9 @@ public class IrisJigsawStructure extends IrisRegistrant {
@Desc("The minecraft key to use when creating treasure maps") @Desc("The minecraft key to use when creating treasure maps")
private String structureKey = null; private String structureKey = null;
@Desc("Force Place the whole structure")
private boolean forcePlace = false;
private transient AtomicCache<Integer> maxDimension = new AtomicCache<>(); private transient AtomicCache<Integer> maxDimension = new AtomicCache<>();
private void loadPool(String p, KList<String> pools, KList<String> pieces) { private void loadPool(String p, KList<String> pools, KList<String> pieces) {
@@ -142,7 +145,7 @@ public class IrisJigsawStructure extends IrisRegistrant {
avg += getLoader().getJigsawPieceLoader().load(i).getMax2dDimension(); avg += getLoader().getJigsawPieceLoader().load(i).getMax2dDimension();
} }
return (avg / (pieces.size() > 0 ? pieces.size() : 1)) * (((getMaxDepth() + 1) * 2) + 1); return (avg / (!pieces.isEmpty() ? pieces.size() : 1)) * (((getMaxDepth() + 1) * 2) + 1);
} }
}); });
} }

View File

@@ -27,5 +27,7 @@ public enum IrisLootMode {
@Desc("Clear all loot tables then add this table") @Desc("Clear all loot tables then add this table")
CLEAR, CLEAR,
@Desc("Replace all loot tables with this table (same as clear)") @Desc("Replace all loot tables with this table (same as clear)")
REPLACE REPLACE,
@Desc("Only use when there was no loot table defined by an object")
FALLBACK
} }

View File

@@ -1,13 +0,0 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.Desc;
@Desc("Modes for generator merging")
public enum IrisMergeStrategies {
@Desc("Splits the world in height. Use the split settings to customize this option")
SPLIT,
@Desc("Merge from of the engine height")
SPLIT_ENGINE_HEIGHT,
}

View File

@@ -1,391 +0,0 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IMemoryWorld;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.util.context.ChunkedDataCache;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.generator.ChunkGenerator;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function;
@AllArgsConstructor
@NoArgsConstructor
@Desc("Dimension Merging only supports 1 for now.")
@Data
public class IrisMerger {
private transient RollingSequence mergeDuration = new RollingSequence(20);
private transient World worldsave;
private transient ReentrantLock lock = new ReentrantLock();
private transient ChunkGenerator chunkGenerator;
private static final BlockData FILLER = Material.STONE.createBlockData();
@Desc("Selected Generator")
private String generator;
@Desc("Use Generator")
private boolean useMemoryWorld = false;
@Desc("Allows to gen chunks on the mergers world")
private boolean allowGenChunks = true;
@Desc("Uses a world instead of a generator")
private String world;
@Desc("Uses the generator as a datapack key")
private boolean datapackMode;
@Desc("How deep till it should use vanilla terrain")
private int depth = 30;
@Desc("Gets the terrain x,z height as the limit")
private IrisMergeStrategies mode = null;
@Desc("If it should put the selected generator above or under the split")
private boolean splitUnder = true;
@Desc("Splits in the engine height")
private int split = 0;
@Desc("If it should translate iris deposits/ores to their deepslate variant")
private boolean deepslateTranslator = true;
private final Map<Chunk, Long> lastUse = new ConcurrentHashMap<>();
/**
* Merges underground from a selected chunk into the corresponding chunk in the outcome world.
*/
@Deprecated
public void generateVanillaUnderground(int cx, int cz, Chunk ichunk, Engine engine) {
if (engine.getMemoryWorld() == null && useMemoryWorld)
throw new IllegalStateException("MemoryWorld is null. Ensure that it has been initialized.");
if (engine.getWorld().realWorld() == null)
return;
if (world == null) {
Iris.error("World merger is null! cant generate chunks FALLBACK!");
return;
}
try {
PrecisionStopwatch p = PrecisionStopwatch.start();
IMemoryWorld memoryWorld;
World bukkit;
if (world.isBlank()) {
memoryWorld = engine.getMemoryWorld();
bukkit = memoryWorld.getBukkit();
} else {
bukkit = Bukkit.getWorld(world);
if (bukkit == null) {
Iris.info("World " + world + " not loaded yet, cannot generate chunk at (" + cx + ", " + cz + ")");
return;
}
}
Chunk chunk;
if (allowGenChunks) {
chunk = bukkit.getChunkAt(cx, cz, true);
} else {
chunk = bukkit.getChunkAt(cx, cz, false);
if (!chunk.isGenerated()) {
throw new IllegalStateException("Chunk " + cx + ", " + cz + " not found. OUT OF BOUNDS");
}
}
// Chunk ichunk = engine.getWorld().realWorld().getChunkAt(cx, cz);
if (!chunk.isLoaded())
J.s(chunk::load);
int totalHeight = bukkit.getMaxHeight() - bukkit.getMinHeight();
int minHeight = Math.abs(bukkit.getMinHeight());
var world = engine.getWorld().realWorld();
int wX = cx << 4;
int wZ = cz << 4;
BurstExecutor b = MultiBurst.burst.burst();
var cache = new ChunkedDataCache<>(b, engine.getComplex().getHeightStream(), wX, wZ);
b.complete();
Set<Biome> caveBiomes = new HashSet<>(Arrays.asList(
Biome.DRIPSTONE_CAVES,
Biome.LUSH_CAVES,
Biome.DEEP_DARK
));
var nms = INMS.get();
var flag = new Flags(false, false, true, false, false).value();
for (int xx = 0; xx < 16; xx += 4) {
for (int zz = 0; zz < 16; zz += 4) {
int maxHeightInSection = 0;
for (int x = 0; x < 4; x++) {
for (int z = 0; z < 4; z++) {
int globalX = xx + x;
int globalZ = zz + z;
int height = (int) Math.ceil(cache.get(globalX, globalZ) - depth);
if (height > maxHeightInSection) {
maxHeightInSection = height;
}
}
}
Hunk<BlockData> vh = getHunkSlice(chunk, xx, zz, maxHeightInSection);
Hunk<BlockData> ih = getHunkSlice(ichunk, xx, zz, maxHeightInSection);
for (int x = 0; x < 4; x++) {
for (int z = 0; z < 4; z++) {
int globalX = xx + x;
int globalZ = zz + z;
int height = (int) Math.ceil(cache.get(globalX, globalZ) - depth);
for (int y = 0; y < totalHeight; y++) {
if (shouldSkip(y, height))
continue;
BlockData blockData = vh.get(x, y, z);
if (!blockData.getMaterial().isAir() && deepslateTranslator) {
if (ih.get(x, y, z).getMaterial() != FILLER.getMaterial() && blockData.getMaterial().isOccluding()) {
try {
BlockData newBlockData = ih.get(x, y, z);
if (hasAround(vh, x, y, z, Material.DEEPSLATE)) {
String id = newBlockData.getMaterial().getItemTranslationKey().replaceFirst("^block\\.[^.]+\\.", "").toUpperCase();
id = "DEEPSLATE_" + id;
Material dps = Material.getMaterial(id);
if (dps != null)
blockData = dps.createBlockData();
}
} catch (Exception e) {
// no Handle exception
}
}
}
nms.setBlock(
world,
wX + globalX,
y - minHeight,
wZ + globalZ,
blockData,
flag,
0
);
if (nms.hasTile(blockData.getMaterial())) {
var tile = nms.serializeTile(new Location(bukkit, wX + globalX, y - minHeight, wZ + globalZ));
if (tile != null) {
nms.deserializeTile(tile, new Location(world, wX + globalX, y - minHeight, wZ + globalZ));
}
}
if (globalX % 4 == 0 && globalZ % 4 == 0 && y % 4 == 0) {
Biome biome;
biome = bukkit.getBiome(wX + globalX, y, wZ + globalZ);
if (caveBiomes.contains(biome)) {
world.setBiome(wX + globalX, y - minHeight, wZ + globalZ, biome);
}
}
}
}
}
}
}
lastUse.put(chunk, System.currentTimeMillis());
mergeDuration.put(p.getMilliseconds());
Iris.info("Vanilla merge average in: " + Form.duration(mergeDuration.getAverage(), 8));
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean shouldSkip(int y, int ht) {
int threshold;
switch (mode) {
case SPLIT_ENGINE_HEIGHT:
threshold = ht;
break;
case SPLIT:
threshold = split;
break;
default:
return false;
}
return splitUnder ? y > threshold : y < threshold;
}
public record Flags(boolean listener, boolean flag, boolean client, boolean update, boolean physics) {
public static Flags fromValue(int value) {
return new Flags(
(value & 1024) != 0,
(value & 64) != 0,
(value & 2) != 0,
(value & 1) != 0,
(value & 16) == 0
);
}
public int value() {
int value = 0;
if (!listener) value |= 1024;
if (flag) value |= 64;
if (client) value |= 2;
if (update) value |= 1;
if (!physics) value |= 16;
return value;
}
}
/**
* Retrieves a 4x4 hunk slice starting at (sx, sz) up to the specified height.
*
* @param chunk The Bukkit chunk
* @param sx Chunk Slice X (must be multiple of 4)
* @param sz Chunk Slice Z (must be multiple of 4)
* @param height The maximum height to process
* @return A hunk of size 4x(totalHeight)x4
*/
private Hunk<BlockData> getHunkSlice(Chunk chunk, int sx, int sz, int height) {
if (!chunk.isGenerated())
throw new IllegalStateException("Chunk is not generated!");
int minHeight = chunk.getWorld().getMinHeight();
int maxHeight = chunk.getWorld().getMaxHeight();
int totalHeight = Math.abs(minHeight) + maxHeight;
Hunk<BlockData> h = Hunk.newHunk(4, totalHeight, 4);
for (int x = 0; x < 4; x++) {
for (int z = 0; z < 4; z++) {
for (int y = 0; y < totalHeight; y++) {
if (shouldSkip(y, height))
continue;
BlockData data = chunk.getBlock(sx + x, y + minHeight, sz + z).getBlockData();
h.set(x, y, z, data);
}
}
}
return h;
}
private boolean hasAround(Hunk<BlockData> hunk, int x, int y, int z, Material material) {
int[] d = {-1, 0, 1};
for (int dx : d) {
for (int dy : d) {
for (int dz : d) {
if (dx == 0 && dy == 0 && dz == 0) continue;
int nx = x + dx;
int ny = y + dy;
int nz = z + dz;
if (nx >= 0 && nx < hunk.getWidth() && nz >= 0 && nz < hunk.getDepth() && ny >= 0 && ny < hunk.getHeight()) {
BlockData neighborBlock = hunk.get(nx, ny, nz);
if (neighborBlock.getMaterial() == material) {
return true;
}
}
}
}
}
return false;
}
public static <T> Hunk<T> copyHunkParallel(Hunk<T> original, Function<T, T> elementCopier) {
Hunk<T> copy = Hunk.newHunk(original.getWidth(), original.getHeight(), original.getDepth());
original.compute3D((ox, oy, oz, section) -> {
Hunk<T> copySection = copy.croppedView(ox, oy, oz, ox + section.getWidth(), oy + section.getHeight(), oz + section.getDepth());
section.iterate((x, y, z, value) -> {
T copiedValue = value != null ? elementCopier.apply(value) : null;
copySection.set(x, y, z, copiedValue);
});
});
return copy;
}
public void loadWorld(Engine engine) {
if (!engine.getDimension().isEnableExperimentalMerger())
return;
World bukkitWorld = Bukkit.getWorld(world);
if (!new File(Bukkit.getWorldContainer(), world).exists())
Iris.warn("World does not exist disabled merger generation for: " + engine.getWorld().name());
//throw new IllegalStateException("World does not exist!");
if (bukkitWorld == null) {
Iris.info("World " + world + " is not loaded yet, creating it.");
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
if (event.getWorld().getName().equals(world)) {
worldsave = event.getWorld();
Iris.info("World " + world + " has been loaded.");
}
}
}, Iris.instance);
WorldCreator worldCreator = new WorldCreator(world);
Bukkit.createWorld(worldCreator);
} else {
worldsave = bukkitWorld;
}
init();
}
public void init() {
Bukkit.getScheduler().runTaskTimer(Iris.instance, this::unloadAndSaveAllChunks, 200L, 20L); // Runs every 10 seconds
}
private void unloadAndSaveAllChunks() {
try {
if (worldsave == null) {
Iris.warn("World was null somehow...");
return;
}
for (Chunk chunk : new ArrayList<>(lastUse.keySet())) {
Long lastUsed = lastUse.get(chunk);
if (lastUsed != null && System.currentTimeMillis() - lastUsed >= 10000) { // 10 seconds
if (chunk.isLoaded()) {
chunk.unload();
}
lastUse.remove(chunk);
}
}
worldsave.save();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -562,7 +562,7 @@ public class IrisObject extends IrisRegistrant {
} }
} }
public void setUnsigned(int x, int y, int z, Block block) { public void setUnsigned(int x, int y, int z, Block block, boolean legacy) {
BlockVector v = getSigned(x, y, z); BlockVector v = getSigned(x, y, z);
if (block == null) { if (block == null) {
@@ -571,7 +571,7 @@ public class IrisObject extends IrisRegistrant {
} else { } else {
BlockData data = block.getBlockData(); BlockData data = block.getBlockData();
getBlocks().put(v, data); getBlocks().put(v, data);
TileData state = TileData.getTileState(block); TileData state = TileData.getTileState(block, legacy);
if (state != null) { if (state != null) {
Iris.debug("Saved State " + v); Iris.debug("Saved State " + v);
getStates().put(v, state); getStates().put(v, state);
@@ -663,7 +663,18 @@ public class IrisObject extends IrisRegistrant {
yrand = yrand > 0 ? rng.i(0, yrand) : yrand < 0 ? rng.i(yrand, 0) : yrand; yrand = yrand > 0 ? rng.i(0, yrand) : yrand < 0 ? rng.i(yrand, 0) : yrand;
boolean bail = false; boolean bail = false;
if (yv < 0) { if (config.isFromBottom()) {
// todo Convert this to a mode and make it compatible with jigsaw
y = (getH() + 1) + rty;
if (!config.isForcePlace()) {
if (placer.isCarved(x, y, z) ||
placer.isCarved(x, y - 1, z) ||
placer.isCarved(x, y - 2, z) ||
placer.isCarved(x, y - 3, z)) {
bail = true;
}
}
} else if (yv < 0) {
if (config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT) || config.getMode() == ObjectPlaceMode.CENTER_STILT) { if (config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT) || config.getMode() == ObjectPlaceMode.CENTER_STILT) {
y = (c != null ? c.getSurface() : placer.getHighest(x, z, getLoader(), config.isUnderwater())) + rty; y = (c != null ? c.getSurface() : placer.getHighest(x, z, getLoader(), config.isUnderwater())) + rty;
if (!config.isForcePlace()) { if (!config.isForcePlace()) {

View File

@@ -34,7 +34,7 @@ import org.bukkit.block.data.BlockData;
@AllArgsConstructor @AllArgsConstructor
@Desc("Represents loot within this object or jigsaw piece") @Desc("Represents loot within this object or jigsaw piece")
@Data @Data
public class IrisObjectLoot { public class IrisObjectLoot implements IObjectLoot {
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>(); private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
@ArrayType(min = 1, type = IrisBlockData.class) @ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The list of blocks this loot table should apply to") @Desc("The list of blocks this loot table should apply to")

View File

@@ -39,9 +39,9 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.TreeType; import org.bukkit.TreeType;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.loot.LootTable;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
@Snippet("object-placer") @Snippet("object-placer")
@@ -109,6 +109,8 @@ public class IrisObjectPlacement {
private boolean onwater = false; private boolean onwater = false;
@Desc("If set to true, this object will only place parts of itself where blocks already exist. Warning: Melding is very performance intensive!") @Desc("If set to true, this object will only place parts of itself where blocks already exist. Warning: Melding is very performance intensive!")
private boolean meld = false; private boolean meld = false;
@Desc("If set to true, this object will get placed from the bottom of the world up")
private boolean fromBottom;
@Desc("If set to true, this object will place from the ground up instead of height checks when not y locked to the surface. This is not compatable with X and Z axis rotations (it may look off)") @Desc("If set to true, this object will place from the ground up instead of height checks when not y locked to the surface. This is not compatable with X and Z axis rotations (it may look off)")
private boolean bottom = false; private boolean bottom = false;
@Desc("If set to true, air will be placed before the schematic places.") @Desc("If set to true, air will be placed before the schematic places.")
@@ -147,8 +149,7 @@ public class IrisObjectPlacement {
private KList<String> forbiddenCollisions = new KList<>(); private KList<String> forbiddenCollisions = new KList<>();
@Desc("Ignore any placement restrictions for this object") @Desc("Ignore any placement restrictions for this object")
private boolean forcePlace = false; private boolean forcePlace = false;
private transient AtomicCache<TableCache<IrisLootTable>> cache = new AtomicCache<>(); private transient AtomicCache<TableCache> cache = new AtomicCache<>();
private transient AtomicCache<TableCache<IrisVanillaLootTable>> vanillaCache = new AtomicCache<>();
public IrisObjectPlacement toPlacement(String... place) { public IrisObjectPlacement toPlacement(String... place) {
IrisObjectPlacement p = new IrisObjectPlacement(); IrisObjectPlacement p = new IrisObjectPlacement();
@@ -219,21 +220,24 @@ public class IrisObjectPlacement {
return (int) Math.round(densityStyle.get(rng, x, z, data)); return (int) Math.round(densityStyle.get(rng, x, z, data));
} }
private TableCache<IrisLootTable> getCache(IrisData manager) { private TableCache getCache(IrisData manager) {
return cache.aquire(() -> getCache(manager, manager.getLootLoader()::load)); return cache.aquire(() -> {
TableCache cache = new TableCache();
cache.merge(getCache(manager, getVanillaLoot(), IrisObjectPlacement::getVanillaTable));
cache.merge(getCache(manager, getLoot(), manager.getLootLoader()::load));
return cache;
});
} }
private TableCache<IrisVanillaLootTable> getVanillaCache(IrisData manager) { private TableCache getCache(IrisData manager, KList<? extends IObjectLoot> list, Function<String, IrisLootTable> loader) {
return vanillaCache.aquire(() -> getCache(manager, IrisObjectPlacement::getVanillaTable)); TableCache tc = new TableCache();
}
private <T> TableCache<T> getCache(IrisData manager, Function<String, T> loader) { for (IObjectLoot loot : list) {
TableCache<T> tc = new TableCache<>();
for (IrisObjectLoot loot : getLoot()) {
if (loot == null) if (loot == null)
continue; continue;
T table = loader.apply(loot.getName()); IrisLootTable table = loader.apply(loot.getName());
if (table == null) { if (table == null) {
Iris.warn("Couldn't find loot table " + loot.getName()); Iris.warn("Couldn't find loot table " + loot.getName());
continue; continue;
@@ -271,10 +275,10 @@ public class IrisObjectPlacement {
@Nullable @Nullable
private static IrisVanillaLootTable getVanillaTable(String name) { private static IrisVanillaLootTable getVanillaTable(String name) {
NamespacedKey key = NamespacedKey.fromString(name); return Optional.ofNullable(NamespacedKey.fromString(name))
if (key == null) .map(Bukkit::getLootTable)
return null; .map(IrisVanillaLootTable::new)
return new IrisVanillaLootTable(Bukkit.getLootTable(key)); .orElse(null);
} }
/** /**
@@ -285,16 +289,9 @@ public class IrisObjectPlacement {
* @return The loot table it should use. * @return The loot table it should use.
*/ */
public IrisLootTable getTable(BlockData data, IrisData dataManager) { public IrisLootTable getTable(BlockData data, IrisData dataManager) {
IrisLootTable table = pickTable(data, getVanillaCache(dataManager)); TableCache cache = getCache(dataManager);
if (table == null) {
table = pickTable(data, getCache(dataManager));
}
return table;
}
private <T> T pickTable(BlockData data, TableCache<T> cache) {
if (B.isStorageChest(data)) { if (B.isStorageChest(data)) {
T picked = null; IrisLootTable picked = null;
if (cache.exact.containsKey(data.getMaterial()) && cache.exact.get(data.getMaterial()).containsKey(data)) { if (cache.exact.containsKey(data.getMaterial()) && cache.exact.get(data.getMaterial()).containsKey(data)) {
picked = cache.exact.get(data.getMaterial()).get(data).pullRandom(); picked = cache.exact.get(data.getMaterial()).get(data).pullRandom();
} else if (cache.basic.containsKey(data.getMaterial())) { } else if (cache.basic.containsKey(data.getMaterial())) {
@@ -309,9 +306,15 @@ public class IrisObjectPlacement {
return null; return null;
} }
private static class TableCache<T> { private static class TableCache {
final transient WeightedRandom<T> global = new WeightedRandom<>(); final transient WeightedRandom<IrisLootTable> global = new WeightedRandom<>();
final transient KMap<Material, WeightedRandom<T>> basic = new KMap<>(); final transient KMap<Material, WeightedRandom<IrisLootTable>> basic = new KMap<>();
final transient KMap<Material, KMap<BlockData, WeightedRandom<T>>> exact = new KMap<>(); final transient KMap<Material, KMap<BlockData, WeightedRandom<IrisLootTable>>> exact = new KMap<>();
private void merge(TableCache other) {
global.merge(other.global);
basic.merge(other.basic, WeightedRandom::merge);
exact.merge(other.exact, (a, b) -> a.merge(b, WeightedRandom::merge));
}
} }
} }

View File

@@ -17,16 +17,16 @@ import org.bukkit.block.data.BlockData;
@AllArgsConstructor @AllArgsConstructor
@Desc("Represents vanilla loot within this object or jigsaw piece") @Desc("Represents vanilla loot within this object or jigsaw piece")
@Data @Data
public class IrisObjectVanillaLoot { public class IrisObjectVanillaLoot implements IObjectLoot {
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>(); private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
@ArrayType(min = 1, type = IrisBlockData.class) @ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The list of blocks this loot table should apply to") @Desc("The list of blocks this loot table should apply to")
private KList<IrisBlockData> filter = new KList<>(); private KList<IrisBlockData> filter = new KList<>();
@Desc("Exactly match the block data or not") @Desc("Exactly match the block data or not")
private boolean exact = false; private boolean exact = false;
@RegistryListFunction(LootTableKeyFunction.class)
@Desc("The vanilla loot table key") @Desc("The vanilla loot table key")
@Required @Required
@RegistryListFunction(LootTableKeyFunction.class)
private String name; private String name;
@Desc("The weight of this loot table being chosen") @Desc("The weight of this loot table being chosen")
private int weight = 1; private int weight = 1;

View File

@@ -0,0 +1,52 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.MatterStructurePOI;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Desc("Static Object Placement")
@Accessors(chain = true, fluent = true)
@NoArgsConstructor
@AllArgsConstructor
public class IrisStaticObjectPlacement implements IrisStaticPlacement {
@Required
@Desc("The X coordinate to spawn the object at")
private int x = 0;
@Required
@Desc("The Y coordinate to spawn the object at\nuse a value <0 to allow the placement modes to function")
private int y = 0;
@Required
@Desc("The Z coordinate to spawn the object at")
private int z = 0;
@Required
@Desc("The object placement to use")
private IrisObjectPlacement placement;
@Override
public void place(MantleWriter writer, RNG rng, IrisData irisData) {
IrisObject v = placement.getScale().get(rng, placement.getObject(() -> irisData, rng));
if (v == null) return;
v.place(x, y, z, writer, placement, rng, irisData);
int id = rng.i(0, Integer.MAX_VALUE);
v.place(x, y, z, writer, placement, rng, (b, data) -> {
writer.setData(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
if (placement.isDolphinTarget() && placement.isUnderwater() && B.isStorageChest(data)) {
writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE);
}
if (data instanceof IrisBlockData d) {
writer.setData(b.getX(), b.getY(), b.getZ(), d.getCustom());
}
}, null, irisData);
}
}

View File

@@ -0,0 +1,19 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.math.RNG;
public interface IrisStaticPlacement {
int x();
int y();
int z();
@ChunkCoordinates
default boolean shouldPlace(int chunkX, int chunkZ) {
return x() >> 4 == chunkX && z() >> 4 == chunkZ;
}
void place(MantleWriter writer, RNG rng, IrisData data);
}

View File

@@ -0,0 +1,49 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Static Placements")
@Data
public class IrisStaticPlacements {
@Desc("List of static jigsaw structures")
@ArrayType(type = IrisStaticStructurePlacement.class)
private KList<IrisStaticStructurePlacement> structures = new KList<>();
@Desc("List of static objects")
@ArrayType(type = IrisStaticObjectPlacement.class)
private KList<IrisStaticObjectPlacement> objects = new KList<>();
@ChunkCoordinates
public KList<IrisStaticStructurePlacement> getStructures(int chunkX, int chunkZ) {
return filter(structures.stream(), chunkX, chunkZ);
}
@ChunkCoordinates
public KList<IrisStaticObjectPlacement> getObjects(int chunkX, int chunkZ) {
return filter(objects.stream(), chunkX, chunkZ);
}
@ChunkCoordinates
public KList<IrisStaticPlacement> getAll(int chunkX, int chunkZ) {
return filter(Stream.concat(structures.stream(), objects.stream()), chunkX, chunkZ);
}
private <T extends IrisStaticPlacement> KList<T> filter(Stream<T> stream, int chunkX, int chunkZ) {
return stream.filter(p -> p.shouldPlace(chunkX, chunkZ))
.collect(Collectors.toCollection(KList::new));
}
}

View File

@@ -0,0 +1,65 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.jigsaw.PlannedStructure;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.RNG;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Desc("Static Jigsaw Structure Placement")
@Accessors(chain = true, fluent = true)
@NoArgsConstructor
@AllArgsConstructor
public class IrisStaticStructurePlacement implements IrisStaticPlacement {
@Required
@Desc("The X coordinate to spawn the structure at")
private int x = 0;
@Required
@Desc("The Y coordinate to spawn the structure at")
private int y = 0;
@Required
@Desc("The Z coordinate to spawn the structure at")
private int z = 0;
@Required
@ArrayType(min = 1, type = String.class)
@RegistryListResource(IrisJigsawStructure.class)
@Desc("The structures to place")
private KList<String> structures;
public int maxDimension(IrisData data) {
return data.getJigsawStructureLoader().loadAll(structures)
.stream()
.mapToInt(IrisJigsawStructure::getMaxDimension)
.max()
.orElse(0);
}
@Override
public void place(MantleWriter writer, RNG rng, IrisData data) {
IrisJigsawStructure jigsaw = null;
while (jigsaw == null && !structures.isEmpty()) {
String loadKey = structures.popRandom(rng);
jigsaw = data.getJigsawStructureLoader().load(loadKey);
if (jigsaw == null)
Iris.error("Jigsaw structure not found " + loadKey);
}
if (jigsaw == null) {
Iris.error("No jigsaw structure found for " + structures);
return;
}
new PlannedStructure(jigsaw, new IrisPosition(x, y, z), rng, false)
.place(writer, writer.getMantle(), writer.getEngine());
}
}

View File

@@ -18,38 +18,34 @@ import java.io.File;
public class IrisVanillaLootTable extends IrisLootTable { public class IrisVanillaLootTable extends IrisLootTable {
private final LootTable lootTable; private final LootTable lootTable;
public KList<ItemStack> getLoot(RNG rng, World world, int x, int y, int z) {
return new KList<>(lootTable.populateLoot(rng, new LootContext.Builder(new Location(world, x, y, z)).build()));
}
@Override @Override
public String getName() { public String getName() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return "Vanilla " + lootTable.getKey();
} }
@Override @Override
public int getRarity() { public int getRarity() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public int getMaxPicked() { public int getMaxPicked() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public int getMinPicked() { public int getMinPicked() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public int getMaxTries() { public int getMaxTries() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public KList<IrisLoot> getLoot() { public KList<IrisLoot> getLoot() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return new KList<>();
} }
@Override @Override
@@ -59,26 +55,26 @@ public class IrisVanillaLootTable extends IrisLootTable {
@Override @Override
public String getFolderName() { public String getFolderName() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a folder name");
} }
@Override @Override
public String getTypeName() { public String getTypeName() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a type name");
} }
@Override @Override
public File getLoadFile() { public File getLoadFile() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a load file");
} }
@Override @Override
public IrisData getLoader() { public IrisData getLoader() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a loader");
} }
@Override @Override
public KList<String> getPreprocessors() { public KList<String> getPreprocessors() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return new KList<>();
} }
} }

View File

@@ -1,33 +1,40 @@
package com.volmit.iris.engine.object; package com.volmit.iris.engine.object;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NonNull; import lombok.NonNull;
import lombok.ToString; import lombok.ToString;
import org.apache.commons.io.function.IOFunction; import org.apache.commons.io.function.IOFunction;
import org.bukkit.DyeColor; import org.bukkit.*;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.block.*; import org.bukkit.block.*;
import org.bukkit.block.banner.Pattern; import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType; import org.bukkit.block.banner.PatternType;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@ToString @ToString
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class LegacyTileData extends TileData { public class LegacyTileData extends TileData {
private static final Map<Integer, IOFunction<DataInputStream, Handler>> legacy = Map.of( private static final Map<Integer, Pair<Builder, IOFunction<DataInputStream, Handler>>> legacy = Map.of(
0, SignHandler::new, 0, new Pair<>(SignHandler::fromBukkit, SignHandler::new),
1, SpawnerHandler::new, 1, new Pair<>(SpawnerHandler::fromBukkit, SpawnerHandler::new),
2, BannerHandler::new); 2, new Pair<>(BannerHandler::fromBukkit, BannerHandler::new));
private static final AtomicCache<Tag<Material>> SIGNS = new AtomicCache<>();
private final int id; private final int id;
private final Handler handler; private final Handler handler;
@@ -36,7 +43,24 @@ public class LegacyTileData extends TileData {
var factory = legacy.get(id); var factory = legacy.get(id);
if (factory == null) if (factory == null)
throw new IOException("Unknown tile type: " + id); throw new IOException("Unknown tile type: " + id);
handler = factory.apply(in); handler = factory.getB().apply(in);
}
private LegacyTileData(int id, Handler handler) {
this.id = id;
this.handler = handler;
}
@Nullable
public static LegacyTileData fromBukkit(@NonNull BlockState tileState) {
var type = tileState.getType();
for (var id : legacy.keySet()) {
var factory = legacy.get(id);
var handler = factory.getA().apply(tileState, type);
if (handler != null)
return new LegacyTileData(id, handler);
}
return null;
} }
@Override @Override
@@ -77,8 +101,14 @@ public class LegacyTileData extends TileData {
void toBukkit(Block block); void toBukkit(Block block);
} }
@FunctionalInterface
private interface Builder {
@Nullable Handler apply(@NonNull BlockState blockState, @NonNull Material type);
}
@ToString @ToString
@EqualsAndHashCode @EqualsAndHashCode
@AllArgsConstructor
private static class SignHandler implements Handler { private static class SignHandler implements Handler {
private final String line1; private final String line1;
private final String line2; private final String line2;
@@ -94,6 +124,13 @@ public class LegacyTileData extends TileData {
dyeColor = DyeColor.values()[in.readByte()]; dyeColor = DyeColor.values()[in.readByte()];
} }
@SuppressWarnings("deprecation")
private static SignHandler fromBukkit(BlockState blockState, Material type) {
if (!signsTag().isTagged(type) || !(blockState instanceof Sign sign))
return null;
return new SignHandler(sign.getLine(0), sign.getLine(1), sign.getLine(2), sign.getLine(3), sign.getColor());
}
@Override @Override
public Material getMaterial() { public Material getMaterial() {
return Material.OAK_SIGN; return Material.OAK_SIGN;
@@ -101,7 +138,7 @@ public class LegacyTileData extends TileData {
@Override @Override
public boolean isApplicable(BlockData data) { public boolean isApplicable(BlockData data) {
return Tag.ALL_SIGNS.isTagged(data.getMaterial()); return signsTag().isTagged(data.getMaterial());
} }
@Override @Override
@@ -126,6 +163,7 @@ public class LegacyTileData extends TileData {
} }
@ToString @ToString
@EqualsAndHashCode @EqualsAndHashCode
@AllArgsConstructor
private static class SpawnerHandler implements Handler { private static class SpawnerHandler implements Handler {
private final EntityType type; private final EntityType type;
@@ -133,6 +171,12 @@ public class LegacyTileData extends TileData {
type = EntityType.values()[in.readShort()]; type = EntityType.values()[in.readShort()];
} }
private static SpawnerHandler fromBukkit(BlockState blockState, Material material) {
if (material != Material.SPAWNER || !(blockState instanceof CreatureSpawner spawner))
return null;
return new SpawnerHandler(spawner.getSpawnedType());
}
@Override @Override
public Material getMaterial() { public Material getMaterial() {
return Material.SPAWNER; return Material.SPAWNER;
@@ -157,6 +201,7 @@ public class LegacyTileData extends TileData {
} }
@ToString @ToString
@EqualsAndHashCode @EqualsAndHashCode
@AllArgsConstructor
private static class BannerHandler implements Handler { private static class BannerHandler implements Handler {
private final KList<Pattern> patterns; private final KList<Pattern> patterns;
private final DyeColor baseColor; private final DyeColor baseColor;
@@ -172,6 +217,12 @@ public class LegacyTileData extends TileData {
} }
} }
private static BannerHandler fromBukkit(BlockState blockState, Material type) {
if (!Tag.BANNERS.isTagged(type) || !(blockState instanceof Banner banner))
return null;
return new BannerHandler(new KList<>(banner.getPatterns()), banner.getBaseColor());
}
@Override @Override
public Material getMaterial() { public Material getMaterial() {
return Material.WHITE_BANNER; return Material.WHITE_BANNER;
@@ -200,4 +251,32 @@ public class LegacyTileData extends TileData {
banner.update(); banner.update();
} }
} }
private static Tag<Material> signsTag() {
return SIGNS.aquire(() -> {
var signs = Bukkit.getTag("blocks", NamespacedKey.minecraft("all_signs"), Material.class);
if (signs != null)
return signs;
return new Tag<>() {
@Override
public boolean isTagged(@NotNull Material item) {
return item.getKey().getKey().endsWith("_sign");
}
@NotNull
@Override
public Set<Material> getValues() {
return StreamSupport.stream(Registry.MATERIAL.spliterator(), false)
.filter(this::isTagged)
.collect(Collectors.toUnmodifiableSet());
}
@NotNull
@Override
public NamespacedKey getKey() {
return NamespacedKey.minecraft("all_signs");
}
};
});
}
} }

View File

@@ -53,9 +53,15 @@ public class TileData implements Cloneable {
return false; return false;
} }
public static TileData getTileState(Block block) { public static TileData getTileState(Block block, boolean useLegacy) {
if (!INMS.get().hasTile(block.getType())) if (!INMS.get().hasTile(block.getType()))
return null; return null;
if (useLegacy) {
var legacy = LegacyTileData.fromBukkit(block.getState());
if (legacy != null)
return legacy;
}
return new TileData().fromBukkit(block); return new TileData().fromBukkit(block);
} }

View File

@@ -30,6 +30,4 @@ public @interface ArrayType {
Class<?> type(); Class<?> type();
int min() default 0; int min() default 0;
int max() default Integer.MAX_VALUE;
} }

View File

@@ -1,6 +1,5 @@
package com.volmit.iris.engine.object.annotations; package com.volmit.iris.engine.object.annotations;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.framework.ListFunction; import com.volmit.iris.engine.framework.ListFunction;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
@@ -13,5 +12,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME) @Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD}) @Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListFunction { public @interface RegistryListFunction {
Class<? extends ListFunction<IrisData, KList<String>>> value(); Class<? extends ListFunction<KList<String>>> value();
} }

View File

@@ -4,12 +4,14 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.framework.ListFunction; import com.volmit.iris.engine.framework.ListFunction;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.loot.LootTable;
import org.bukkit.loot.LootTables; import org.bukkit.loot.LootTables;
import java.util.Arrays;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class LootTableKeyFunction implements ListFunction<IrisData, KList<String>> { public class LootTableKeyFunction implements ListFunction<KList<String>> {
@Override @Override
public String key() { public String key() {
return "loot-table-key"; return "loot-table-key";
@@ -22,8 +24,9 @@ public class LootTableKeyFunction implements ListFunction<IrisData, KList<String
@Override @Override
public KList<String> apply(IrisData data) { public KList<String> apply(IrisData data) {
return Arrays.stream(LootTables.values()) return StreamSupport.stream(Registry.LOOT_TABLES.spliterator(), false)
.map(LootTables::getKey) .map(LootTables::getLootTable)
.map(LootTable::getKey)
.map(NamespacedKey::toString) .map(NamespacedKey::toString)
.collect(Collectors.toCollection(KList::new)); .collect(Collectors.toCollection(KList::new));
} }

View File

@@ -5,7 +5,7 @@ import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.framework.ListFunction; import com.volmit.iris.engine.framework.ListFunction;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
public class StructureKeyFunction implements ListFunction<IrisData, KList<String>> { public class StructureKeyFunction implements ListFunction<KList<String>> {
@Override @Override
public String key() { public String key() {
return "structure-key"; return "structure-key";

View File

@@ -36,7 +36,6 @@ import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder; import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder; import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
import com.volmit.iris.util.io.ReactiveFolder; import com.volmit.iris.util.io.ReactiveFolder;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper; import com.volmit.iris.util.scheduling.Looper;
@@ -50,7 +49,6 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
@@ -89,7 +87,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
private final AtomicInteger a = new AtomicInteger(0); private final AtomicInteger a = new AtomicInteger(0);
private final CompletableFuture<Integer> spawnChunks = new CompletableFuture<>(); private final CompletableFuture<Integer> spawnChunks = new CompletableFuture<>();
private final boolean smartVanillaHeight; private final boolean smartVanillaHeight;
private RollingSequence mergeDuration;
private Engine engine; private Engine engine;
private Looper hotloader; private Looper hotloader;
private StudioMode lastMode; private StudioMode lastMode;
@@ -106,7 +103,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
populators = new KList<>(); populators = new KList<>();
loadLock = new Semaphore(LOAD_LOCKS); loadLock = new Semaphore(LOAD_LOCKS);
this.world = world; this.world = world;
this.mergeDuration = new RollingSequence(20);
this.hotloadChecker = new ChronoLatch(1000, false); this.hotloadChecker = new ChronoLatch(1000, false);
this.studio = studio; this.studio = studio;
this.dataLocation = dataLocation; this.dataLocation = dataLocation;
@@ -383,13 +379,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
} }
} }
@EventHandler
private void onChunkGeneration(ChunkLoadEvent event) {
if (engine == null ||!event.isNewChunk() || !engine.getWorld().realWorld().equals(event.getWorld()) || !engine.getDimension().isEnableExperimentalMerger())
return;
engine.getMerger().generateVanillaUnderground(event.getChunk().getX(), event.getChunk().getZ(), event.getChunk(), engine);
}
@Override @Override
public int getBaseHeight(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull HeightMap heightMap) { public int getBaseHeight(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull HeightMap heightMap) {
return 4; return 4;

View File

@@ -80,15 +80,6 @@ public class KList<T> extends ArrayList<T> implements List<T> {
return indexOf(v); return indexOf(v);
} }
/**
* Remove the last element
*/
public KList<T> removeLast() {
remove(last());
return this;
}
public void addMultiple(T t, int c) { public void addMultiple(T t, int c) {
for (int i = 0; i < c; i++) { for (int i = 0; i < c; i++) {
add(t); add(t);
@@ -496,7 +487,7 @@ public class KList<T> extends ArrayList<T> implements List<T> {
return pop(); return pop();
} }
return remove(rng.i(0, last())); return remove(rng.i(0, size()));
} }
public KList<T> sub(int f, int t) { public KList<T> sub(int f, int t) {

View File

@@ -28,6 +28,7 @@ import java.util.Comparator;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
public class KMap<K, V> extends ConcurrentHashMap<K, V> { public class KMap<K, V> extends ConcurrentHashMap<K, V> {
@@ -151,6 +152,17 @@ public class KMap<K, V> extends ConcurrentHashMap<K, V> {
return this; return this;
} }
/**
* Merge with another map
*
* @param m the map to merge
* @return this map (builder)
*/
public KMap<K, V> merge(KMap<K, V> m, BiFunction<V, V, V> merger) {
m.forEach((k, v) -> merge(k, v, merger));
return this;
}
/** /**
* Return a copy of this map * Return a copy of this map
* *

Some files were not shown because too many files have changed in this diff Show More