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

Compare commits

...

92 Commits

Author SHA1 Message Date
Aidan Aeternum
d7270f66e1 v+ 2025-02-06 16:16:11 -05:00
Aidan Aeternum
b220b1bffa Merge pull request #1168 from VolmitSoftware/dev
3.6.0
2025-02-06 16:15:05 -05:00
Julian Krings
4796fe98cb fix modern tile states not applying properly 2025-02-05 15:20:34 +01:00
Julian Krings
ece905ec6e fix registry lookup failing on some server versions 2025-02-04 21:11:08 +01:00
Julian Krings
53c9e7c04c drop 1.19.x support (#1167) 2025-02-04 13:04:48 +01:00
Julian Krings
29f6f52443 add noise based spread type (#1164) 2025-02-04 13:04:28 +01:00
Julian Krings
a778cc51a6 Expression functions (#1165) 2025-02-04 13:03:49 +01:00
Julian Krings
c6963d0cd3 fix world delete command crashing servers (#1166) 2025-02-04 13:03:33 +01:00
pixel
489844f61b Updated README.md to JDK21 2025-02-03 22:19:38 +01:00
Aidan Aeternum
4d1b0246ca v+ 2025-02-01 10:55:58 -05:00
Aidan Aeternum
13f3511fa8 Merge pull request #1159 from VolmitSoftware/dev
3.5.9
2025-02-01 10:54:00 -05:00
Julian Krings
f6f2766315 fix ignoring some custom blocks (#1158) 2025-01-30 13:12:15 +01:00
Aidan Aeternum
56530a1245 v+ 2025-01-29 17:51:36 -05:00
Aidan Aeternum
210a1f29a7 Merge pull request #1156 from VolmitSoftware/dev
3.5.8
2025-01-29 15:51:16 -07:00
Julian Krings
847bf972ae improve performance related to custom blocks (#1155) 2025-01-27 15:22:10 +01:00
Aidan Aeternum
e5d21fdf7e v+ 2025-01-25 09:48:00 -07:00
Aidan Aeternum
0b2fd3b358 v+ 2025-01-25 09:47:17 -07:00
Aidan Aeternum
10484d1226 Merge pull request #1153 from VolmitSoftware/dev
3.5.7
2025-01-25 09:46:58 -07:00
Julian Krings
ce0092c52a Fix creation deadlock (#1154) 2025-01-25 14:54:21 +01:00
Julian Krings
474e033c2b Feat/1.21.4 (#1152) 2025-01-24 18:03:12 +01:00
Aidan Aeternum
62aad1f497 v+ 2025-01-23 14:46:15 -07:00
Aidan Aeternum
32b5157682 Update build.gradle 2025-01-23 14:44:53 -07:00
Aidan Aeternum
70717ea282 Merge pull request #1151 from VolmitSoftware/dev
3.5.6
2025-01-23 14:44:24 -07:00
Julian Krings
15975f108c Fix compile 2025-01-22 22:52:21 +01:00
Julian Krings
66c66e82c1 remove "smart" vanilla height (#1150) 2025-01-22 22:47:39 +01:00
Julian Krings
4f6da95d8e fix radius calculation skipping pieces (#1149) 2025-01-22 22:47:28 +01:00
Aidan Aeternum
b37ccbdf01 v+ 2025-01-17 08:27:58 -05:00
Aidan Aeternum
30dbe0881a Merge pull request #1145 from VolmitSoftware/dev
3.5.5
2025-01-17 05:26:26 -08:00
Julian Krings
20ad4657a9 fix null pointer preventing the entity schema from generating (#1142) 2025-01-15 11:30:55 +01:00
Julian Krings
d4986f42a6 Fix decorator determinism (#1144) 2025-01-15 11:30:34 +01:00
Aidan Aeternum
8df15c0c2d v+ 2025-01-12 14:12:43 -08:00
Aidan Aeternum
24e1c578c8 Merge pull request #1139 from VolmitSoftware/dev
3.5.4
2025-01-12 14:10:50 -08:00
Julian Krings
1c3bff7559 fix sculk veins not properly placing with decorators (#1137) 2025-01-12 15:37:10 +01:00
Julian Krings
a09657b4d0 precalculate pack hash on engine setup (#1138) 2025-01-12 15:36:54 +01:00
Aidan Aeternum
910220d3ca v+ 2025-01-08 18:22:26 -08:00
Aidan Aeternum
fc05c24e3a Merge pull request #1135 from VolmitSoftware/dev
3.5.3
2025-01-08 18:20:43 -08: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
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
Julian Krings
1f9c72d093 fix compile 2024-11-09 13:58:10 +01:00
Julian Krings
a1495a10e5 updater fixes 2024-11-08 21:01:58 +01:00
Julian Krings
11ae48bea1 revert previous 2024-10-31 21:33:24 +01:00
Julian Krings
b0f4b29a2d ehh 2024-10-31 21:05:07 +01:00
Julian Krings
c38bb1cd01 stability improvements for the chunk updater 2024-10-30 15:59:31 +01:00
Julian Krings
7faa727bd2 midsave ChunkUpdater improvements 2024-10-29 22:12:22 +01:00
Julian Krings
9e40259ca2 fix LegacyTileData not placing 2024-10-17 19:18:11 +02:00
Julian Krings
94a7692735 add force place for stronghold 2024-10-17 18:48:17 +02:00
Julian Krings
8b803a87f0 rename CrucibleDataProvider to MythicCrucibleDataProvider to fit naming conventions 2024-10-17 11:28:50 +02:00
Julian Krings
3ae6e92eaf woops 2024-10-16 22:05:47 +02:00
Julian Krings
0f3c52a5aa cleanup CrucibleDataProvider and fix furniture support 2024-10-16 21:59:38 +02:00
Schroddinger
747be7aa09 MythicCrucible support. Currently under testing.
(cherry picked from commit 06d0f0748bfb3a69b663c2c3604b65f52cb4c5c2)
2024-10-16 21:37:54 +02:00
Brian Fopiano
d651f204f8 Merge pull request #1117 from hUwUtao/master
make javadoc buildable...
2024-10-02 00:43:56 -04:00
stdpi
2bd3ac7a9b Merge branch 'VolmitSoftware:master' into master 2024-09-25 02:00:31 +07:00
Brian Neumann-Fopiano
5e437b34e3 Revert "Update LICENSE.md"
This reverts commit 6c6c9654c1.
2024-09-24 14:58:10 -04:00
stdpi
a5ef89a128 add irisDev task to copy javadocs and sources jar 2024-09-22 17:35:00 +07:00
stdpi
558b8e4eca add more jar package (javadocJar sourcesJar) 2024-09-22 16:09:48 +07:00
stdpi
0a001b8a63 fix: javadoc tolerate bad html
and match encoding, ugh
2024-09-22 04:48:18 +07:00
Brian Fopiano
6c6c9654c1 Update LICENSE.md 2024-09-09 16:54:57 -04:00
150 changed files with 3743 additions and 4155 deletions

View File

@@ -15,17 +15,17 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
### Command Line Builds
1. Install [Java JDK 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
1. Install [Java JDK 21](https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html)
2. Set the JDK installation path to `JAVA_HOME` as an environment variable.
* Windows
1. Start > Type `env` and press Enter
2. Advanced > Environment Variables
3. Under System Variables, click `New...`
4. Variable Name: `JAVA_HOME`
5. Variable Value: `C:\Program Files\Java\jdk-17.0.1` (verify this exists after installing java don't just copy
5. Variable Value: `C:\Program Files\Java\jdk-21.0.1` (verify this exists after installing java don't just copy
the example text)
* MacOS
1. Run `/usr/libexec/java_home -V` and look for Java 17
1. Run `/usr/libexec/java_home -V` and look for Java 21
2. Run `sudo nano ~/.zshenv`
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
@@ -35,7 +35,7 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
### IDE Builds (for development)
* Configure ITJ Gradle to use JDK 17 (in settings, search for gradle)
* Configure ITJ Gradle to use JDK 21 (in settings, search for gradle)
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
prefer.
* Resync the project & run your newly created task (under the development folder in gradle tasks!)

View File

@@ -32,7 +32,8 @@ plugins {
id "de.undercouch.download" version "5.0.1"
}
version '3.4.3-1.19.2-1.21.1'
version '3.6.0-1.20.1-1.21.4'
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
// ======================== WINDOWS =============================
@@ -43,7 +44,8 @@ registerCustomOutputTask('Coco', 'D://mcsm/plugins')
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.4 - Development/plugins')
registerCustomOutputTask('PixelFury', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins')
registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins')
// ========================== UNIX ==============================
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
@@ -52,26 +54,22 @@ registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugin
// ==============================================================
def NMS_BINDINGS = Map.of(
"v1_21_R1", "1.21-R0.1-SNAPSHOT",
"v1_21_R3", "1.21.4-R0.1-SNAPSHOT",
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
"v1_21_R1", "1.21.1-R0.1-SNAPSHOT",
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
"v1_19_R3", "1.19.4-R0.1-SNAPSHOT",
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
)
def JVM_VERSION = Map.of(
"v1_21_R1", 21,
"v1_20_R4", 21,
)
def JVM_VERSION = Map.of()
NMS_BINDINGS.each { nms ->
project(":nms:${nms.key}") {
apply plugin: 'java'
apply plugin: 'com.volmit.nmstools'
nmsTools {
it.jvm = JVM_VERSION.getOrDefault(nms.key, 17)
it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
it.version = nms.value
}
@@ -92,6 +90,7 @@ shadowJar {
relocate 'com.dfsek.paralithic', 'com.volmit.iris.util.paralithic'
relocate 'io.papermc.lib', 'com.volmit.iris.util.paper'
relocate 'net.kyori', 'com.volmit.iris.util.kyori'
relocate 'org.bstats', 'com.volmit.util.metrics'
archiveFileName.set("Iris-${project.version}.jar")
}
@@ -109,33 +108,36 @@ allprojects {
repositories {
mavenCentral()
maven { url "https://repo.papermc.io/repository/maven-public/"}
maven { url "https://repo.papermc.io/repository/maven-public/" }
maven { url "https://repo.codemc.org/repository/maven-public" }
maven { url "https://mvn.lumine.io/repository/maven-public/" }
maven { url "https://jitpack.io"}
maven { url "https://jitpack.io" }
maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots" }
maven { url "https://mvn.lumine.io/repository/maven/" }
maven { url "https://repo.triumphteam.dev/snapshots" }
maven { url "https://repo.mineinabyss.com/releases" }
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 {
// Provided or Classpath
compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'
compileOnly 'org.projectlombok:lombok:1.18.36'
annotationProcessor 'org.projectlombok:lombok:1.18.36'
// Shaded
implementation 'com.dfsek:Paralithic:0.4.0'
implementation 'com.dfsek:paralithic:0.8.1'
implementation 'io.papermc:paperlib:1.0.5'
implementation "net.kyori:adventure-text-minimessage:4.17.0"
implementation 'net.kyori:adventure-platform-bukkit:4.3.4'
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:cuda-platform:12.3-8.9-1.5.10'
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
compileOnly 'io.lumine:MythicCrucible-Dist:2.0.0'
// Dynamically Loaded
compileOnly 'io.timeandspace:smoothie-map:2.0.2'
@@ -149,6 +151,7 @@ allprojects {
compileOnly 'rhino:js:1.7R2'
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
compileOnly 'org.apache.commons:commons-lang3:3.12.0'
compileOnly 'com.github.oshi:oshi-core:6.6.5'
}
/**
@@ -158,20 +161,35 @@ allprojects {
options.compilerArgs << '-parameters'
options.encoding = "UTF-8"
}
javadoc {
options.encoding = "UTF-8"
options.addStringOption('Xdoclint:none', '-quiet')
}
task sourcesJar(type: Jar, dependsOn: classes) {
archiveClassifier.set('sources')
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
archiveClassifier.set('javadoc')
from javadoc.destinationDir
}
}
if (JavaVersion.current().toString() != "17") {
if (JavaVersion.current().toString() != "21") {
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("=== For IDEs ===")
System.err.println("1. Configure the project for Java 17")
System.err.println("2. Configure the bundled gradle to use Java 17 in settings")
System.err.println("1. Configure the project for Java 21")
System.err.println("2. Configure the bundled gradle to use Java 21 in settings")
System.err.println()
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("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("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-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("=========================================================================================================")
System.err.println()
@@ -185,6 +203,20 @@ task iris(type: Copy) {
dependsOn(build)
}
// with classifier: 'javadoc' and 'sources'
task irisDev(type: Copy) {
group "iris"
from("core/build/libs/core-javadoc.jar", "core/build/libs/core-sources.jar")
rename { String fileName ->
fileName.replace("core", "Iris-${version}")
}
into layout.buildDirectory.asFile.get()
dependsOn(iris)
dependsOn("core:sourcesJar")
dependsOn("core:javadocJar")
}
def registerCustomOutputTask(name, path) {
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
return;

View File

@@ -62,7 +62,7 @@ dependencies {
// Third Party Integrations
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.PlaceholderAPI:placeholderapi:2.11.3'
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
@@ -71,6 +71,9 @@ dependencies {
//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.

View File

@@ -40,6 +40,7 @@ import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.platform.DummyChunkGenerator;
import com.volmit.iris.core.safeguard.IrisSafeguard;
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.KMap;
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.parallel.MultiBurst;
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.VolmitSender;
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.ShurikenQueue;
import io.papermc.lib.PaperLib;
import lombok.Getter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.serializer.ComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.WorldCreator;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.DrilldownPie;
import org.bstats.charts.SimplePie;
import org.bstats.charts.SingleLineChart;
import org.bukkit.*;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -77,33 +77,31 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.*;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.IllegalPluginAccessException;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import oshi.SystemInfo;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.math.RoundingMode;
import java.net.URL;
import java.util.Date;
import java.util.Map;
import java.text.NumberFormat;
import java.util.*;
import java.util.regex.Matcher;
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.ServerBootSFG.passedserversoftware;
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
@SuppressWarnings("CanBeFinal")
public class Iris extends VolmitPlugin implements Listener {
public static final String OVERWORLD_TAG = "3800";
public static final String OVERWORLD_TAG = "31010";
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
@@ -512,11 +510,10 @@ public class Iris extends VolmitPlugin implements Listener {
continue;
}
Iris.info("2 World: %s | Generator: %s", s, generator);
if (Bukkit.getWorlds().stream().anyMatch(w -> w.getName().equals(s))) {
if (Bukkit.getWorld(s) != null)
continue;
}
Iris.info("Loading World: %s | Generator: %s", s, generator);
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
new WorldCreator(s)
@@ -664,7 +661,50 @@ public class Iris extends VolmitPlugin implements Listener {
private void bstats() {
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::getEngine)
.collect(Collectors.toMap(engine -> engine.getDimension().getLoadKey(), engine -> {
var hash32 = engine.getHash32().getNow(null);
if (hash32 == null) return Map.of();
int version = engine.getDimension().getVersion();
String checksum = Long.toHexString(hash32);
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);
});
}
}
@@ -739,7 +779,7 @@ public class Iris extends VolmitPlugin implements Listener {
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
}
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
}
public void splash() {

View File

@@ -25,7 +25,9 @@ import com.volmit.iris.util.json.JSONException;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.ChronoLatch;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.File;
import java.io.IOException;
@@ -42,6 +44,7 @@ public class IrisSettings {
private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency();
private IrisSettingsStudio studio = new IrisSettingsStudio();
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
public static int getThreadCount(int c) {
return switch (c) {
@@ -144,6 +147,30 @@ public class IrisSettings {
public int scriptLoaderCacheSize = 512;
}
@Data
public static class IrisSettingsUpdater {
public double threadMultiplier = 2;
public double chunkLoadSensitivity = 0.7;
public MsRange emptyMsRange = new MsRange(80, 100);
public MsRange defaultMsRange = new MsRange(20, 40);
public double getThreadMultiplier() {
return Math.min(Math.abs(threadMultiplier), 0.1);
}
public double getChunkLoadSensitivity() {
return Math.min(chunkLoadSensitivity, 0.9);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class MsRange {
public int min = 20;
public int max = 40;
}
@Data
public static class IrisSettingsGeneral {
public boolean DoomsdayAnnihilationSelfDestructMode = false;

View File

@@ -21,36 +21,25 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.ServerConfigurator;
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.v1X.NMSBinding1X;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisConverter;
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.mantle.components.MantleObjectComponent;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisCave;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisEntity;
import com.volmit.iris.util.data.Dimension;
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.CountingDataInputStream;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.VolmitSender;
import io.lumine.mythic.bukkit.adapters.BukkitEntity;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4FrameInputStream;
@@ -58,10 +47,7 @@ import net.jpountz.lz4.LZ4FrameOutputStream;
import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EntityType;
import java.io.*;
import java.net.InetAddress;
@@ -152,12 +138,14 @@ public class CommandDeveloper implements DecreeExecutor {
@Decree(description = "Test")
public void packBenchmark(
@Param(description = "The pack to bench", aliases = {"pack"})
IrisDimension dimension
@Param(description = "The pack to bench", aliases = {"pack"}, defaultValue = "overworld")
IrisDimension dimension,
@Param(description = "Radius in regions", defaultValue = "5")
int radius,
@Param(description = "Open GUI while benchmarking", defaultValue = "false")
boolean gui
) {
Iris.info("test");
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1);
new IrisPackBenchmarking(dimension, radius, gui);
}
@Decree(description = "Upgrade to another Minecraft version")
@@ -262,7 +250,7 @@ public class CommandDeveloper implements DecreeExecutor {
VolmitSender sender = sender();
service.submit(() -> {
try {
DataInputStream raw = new DataInputStream(new FileInputStream(file));
CountingDataInputStream raw = CountingDataInputStream.wrap(new FileInputStream(file));
TectonicPlate plate = new TectonicPlate(height, raw);
raw.close();
@@ -281,7 +269,7 @@ public class CommandDeveloper implements DecreeExecutor {
if (size == 0)
size = tmp.length();
start = System.currentTimeMillis();
DataInputStream din = createInput(tmp, algorithm);
CountingDataInputStream din = createInput(tmp, algorithm);
new TectonicPlate(height, din);
din.close();
d2 += System.currentTimeMillis() - start;
@@ -301,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);
return new DataInputStream(switch (algorithm) {
return CountingDataInputStream.wrap(switch (algorithm) {
case "gzip" -> new GZIPInputStream(in);
case "lz4f" -> new LZ4FrameInputStream(in);
case "lz4b" -> new LZ4BlockInputStream(in);

View File

@@ -20,9 +20,7 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisBenchmarking;
@@ -43,9 +41,7 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Difficulty;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.configuration.ConfigurationSection;
@@ -55,10 +51,8 @@ import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -94,9 +88,7 @@ public class CommandIris implements DecreeExecutor {
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
IrisDimension type,
@Param(description = "The seed to generate the world with", defaultValue = "1337")
long seed,
@Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false")
boolean vanillaheight
long seed
) {
if(sender() instanceof Player) {
if (incompatibilities.get("Multiverse-Core")) {
@@ -140,7 +132,6 @@ public class CommandIris implements DecreeExecutor {
.seed(seed)
.sender(sender())
.studio(false)
.smartVanillaHeight(vanillaheight)
.create();
} catch (Throwable e) {
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
@@ -274,6 +265,17 @@ public class CommandIris implements DecreeExecutor {
return;
}
sender().sendMessage(C.GREEN + "Removing world: " + world.getName());
if (!IrisToolbelt.evacuate(world)) {
sender().sendMessage(C.RED + "Failed to evacuate world: " + world.getName());
return;
}
if (!Bukkit.unloadWorld(world, false)) {
sender().sendMessage(C.RED + "Failed to unload world: " + world.getName());
return;
}
try {
if (IrisToolbelt.removeWorld(world)) {
sender().sendMessage(C.GREEN + "Successfully removed " + world.getName() + " from bukkit.yml");
@@ -286,27 +288,32 @@ public class CommandIris implements DecreeExecutor {
}
IrisToolbelt.evacuate(world, "Deleting world");
deletingWorld = true;
Bukkit.unloadWorld(world, false);
int retries = 12;
if (delete) {
if (!delete) {
deletingWorld = false;
return;
}
VolmitSender sender = sender();
J.a(() -> {
int retries = 12;
if (deleteDirectory(world.getWorldFolder())) {
sender().sendMessage(C.GREEN + "Successfully removed world folder");
sender.sendMessage(C.GREEN + "Successfully removed world folder");
} else {
while(true){
if (deleteDirectory(world.getWorldFolder())){
sender().sendMessage(C.GREEN + "Successfully removed world folder");
sender.sendMessage(C.GREEN + "Successfully removed world folder");
break;
}
retries--;
if (retries == 0){
sender().sendMessage(C.RED + "Failed to remove world folder");
sender.sendMessage(C.RED + "Failed to remove world folder");
break;
}
J.sleep(3000);
}
}
}
deletingWorld = false;
deletingWorld = false;
});
}
public static boolean deleteDirectory(File dir) {
@@ -649,6 +656,6 @@ public class CommandIris implements DecreeExecutor {
ff.mkdirs();
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
}
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
}
}

View File

@@ -60,7 +60,7 @@ public class CommandJigsaw implements DecreeExecutor {
try {
var world = world();
WorldObjectPlacer placer = new WorldObjectPlacer(world);
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG());
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG(), true);
VolmitSender sender = sender();
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));

View File

@@ -28,6 +28,8 @@ import com.volmit.iris.core.tools.IrisConverter;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.data.Cuboid;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.data.registry.Materials;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
@@ -36,12 +38,9 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Direction;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.scheduling.Queue;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
@@ -54,7 +53,7 @@ import java.util.*;
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
public class CommandObject implements DecreeExecutor {
private static final Set<Material> skipBlocks = Set.of(E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS"), Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
private static final Set<Material> skipBlocks = Set.of(Materials.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
Material.POPPY, Material.DANDELION);
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
@@ -79,7 +78,10 @@ public class CommandObject implements DecreeExecutor {
futureBlockChanges.put(block, block.getBlockData());
block.setBlockData(d);
if (d instanceof IrisCustomData data) {
block.setBlockData(data.getBase());
Iris.warn("Tried to place custom block at " + x + ", " + y + ", " + z + " which is not supported!");
} else block.setBlockData(d);
}
@Override
@@ -376,9 +378,11 @@ public class CommandObject implements DecreeExecutor {
@Param(description = "The file to store it in, can use / for subfolders")
String name,
@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) {
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.service.ConversionSVC;
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.engine.framework.Engine;
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.MultiBurst;
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.O;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
@@ -64,7 +62,6 @@ import io.papermc.lib.PaperLib;
import org.bukkit.*;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
@@ -79,7 +76,6 @@ import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@@ -176,7 +172,7 @@ public class CommandStudio implements DecreeExecutor {
KList<Runnable> js = new KList<>();
BurstExecutor b = MultiBurst.burst.burst();
b.setMulticore(false);
int rad = engine.getMantle().getRealRadius();
int rad = engine.getMantle().getRadius();
for (int i = -(radius + rad); i <= radius + rad; i++) {
for (int j = -(radius + rad); j <= radius + rad; j++) {
engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ());
@@ -306,7 +302,7 @@ public class CommandStudio implements DecreeExecutor {
Inventory inv = Bukkit.createInventory(null, 27 * 2);
try {
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
engine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, player().getWorld(), player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
} catch (Throwable e) {
Iris.reportError(e);
sender().sendMessage(C.RED + "Cannot add items to virtual inventory because of: " + e.getMessage());
@@ -329,7 +325,7 @@ public class CommandStudio implements DecreeExecutor {
inv.clear();
}
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
engine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, player().getWorld(), player().getLocation().getBlockX(), player().getLocation().getBlockY(), player().getLocation().getBlockZ(), 1);
}, 0, fast ? 5 : 35));
sender().sendMessage(C.GREEN + "Opening inventory now!");

View File

@@ -43,6 +43,10 @@ public class CommandUpdater implements DecreeExecutor {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
if (chunkUpdater != null) {
chunkUpdater.stop();
}
chunkUpdater = new ChunkUpdater(world);
if (sender().isPlayer()) {
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
@@ -53,14 +57,7 @@ public class CommandUpdater implements DecreeExecutor {
}
@Decree(description = "Pause the updater")
public void pause(
@Param(description = "World to pause the Updater at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
public void pause( ) {
if (chunkUpdater == null) {
sender().sendMessage(C.GOLD + "You cant pause something that doesnt exist?");
return;
@@ -68,40 +65,32 @@ public class CommandUpdater implements DecreeExecutor {
boolean status = chunkUpdater.pause();
if (sender().isPlayer()) {
if (status) {
sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + chunkUpdater.getName());
} else {
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
}
} else {
if (status) {
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + chunkUpdater.getName());
} else {
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + chunkUpdater.getName());
}
}
}
@Decree(description = "Stops the updater")
public void stop(
@Param(description = "World to stop the Updater at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
public void stop() {
if (chunkUpdater == null) {
sender().sendMessage(C.GOLD + "You cant stop something that doesnt exist?");
return;
}
if (sender().isPlayer()) {
sender().sendMessage("Stopping Updater for: " + C.GRAY + world.getName());
sender().sendMessage("Stopping Updater for: " + C.GRAY + chunkUpdater.getName());
} else {
Iris.info("Stopping Updater for: " + C.GRAY + world.getName());
Iris.info("Stopping Updater for: " + C.GRAY + chunkUpdater.getName());
}
chunkUpdater.stop();
}
}

View File

@@ -0,0 +1,113 @@
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.IrisLootTable;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.scheduling.J;
import lombok.Getter;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.world.LootGenerateEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootContext;
import org.bukkit.loot.LootTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Random;
@Getter
public class IrisLootEvent extends Event {
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 Block block;
private final InventorySlotType slot;
private final KList<IrisLootTable> tables;
/**
* Constructor for IrisLootEvent with mode selection.
*
* @param engine The engine instance.
* @param block The block associated with the event.
* @param slot The inventory slot type.
* @param tables The list of IrisLootTables. (mutable*)
*/
public IrisLootEvent(Engine engine, Block block, InventorySlotType slot, KList<IrisLootTable> tables) {
this.engine = engine;
this.block = block;
this.slot = slot;
this.tables = tables;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
/**
* Required method to get the HandlerList for this event.
*
* @return The HandlerList.
*/
public static HandlerList getHandlerList() {
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

@@ -276,9 +276,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List
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), (float) (n * n * n * n * n * n), (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);
int rgb = color.getRGB();
img.setRGB(xx, z, rgb);
} catch (Throwable ignored) {

View File

@@ -30,6 +30,7 @@ import com.volmit.iris.engine.object.IrisWorld;
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.data.registry.Attributes;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.BlockPosition;
import com.volmit.iris.util.math.M;
@@ -56,6 +57,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.BiFunction;
import static com.volmit.iris.util.data.registry.Attributes.MAX_HEALTH;
public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener {
private static final long serialVersionUID = 2094606939770332040L;
private final KList<LivingEntity> lastEntities = new KList<>();
@@ -636,7 +639,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
k.add("Pos: " + h.getLocation().getBlockX() + ", " + h.getLocation().getBlockY() + ", " + h.getLocation().getBlockZ());
k.add("UUID: " + h.getUniqueId());
k.add("HP: " + h.getHealth() + " / " + h.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
k.add("HP: " + h.getHealth() + " / " + h.getAttribute(MAX_HEALTH).getValue());
drawCardTR(g, k);
}

View File

@@ -55,10 +55,10 @@ public class IrisRenderer {
IrisBiome b = renderer.getBiome((int) Math.round(x), renderer.getMaxHeight() - 1, (int) Math.round(z));
IrisBiomeGeneratorLink g = b.getGenerators().get(0);
Color c;
if (g.getMax(renderer) <= 0) {
if (g.getMax() <= 0) {
// Max is below water level, so it is most likely an ocean biome
c = Color.BLUE;
} else if (g.getMin(renderer) < 0) {
} else if (g.getMin() < 0) {
// Min is below water level, but max is not, so it is most likely a shore biome
c = Color.YELLOW;
} else {

View File

@@ -9,6 +9,7 @@ import com.willfp.ecoitems.items.EcoItems;
import org.bukkit.NamespacedKey;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException;
@@ -33,23 +34,27 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
}
}
@NotNull
@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());
}
@NotNull
@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());
if (item == null) throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key());
return itemStack.get(item).clone();
}
@NotNull
@Override
public Identifier[] getBlockTypes() {
return new Identifier[0];
}
@NotNull
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
@@ -66,7 +71,7 @@ public class EcoItemsDataProvider extends ExternalDataProvider {
}
@Override
public boolean isValidProvider(Identifier id, boolean isItem) {
public boolean isValidProvider(@NotNull Identifier id, boolean 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 org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException;
import java.util.Optional;
@@ -20,23 +21,27 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
Iris.info("Setting up ExecutableItems Link...");
}
@NotNull
@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());
}
@NotNull
@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())
.map(item -> item.buildItem(1, Optional.empty()))
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));
}
@NotNull
@Override
public Identifier[] getBlockTypes() {
return new Identifier[0];
}
@NotNull
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
@@ -53,7 +58,7 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
}
@Override
public boolean isValidProvider(Identifier key, boolean isItem) {
public boolean isValidProvider(@NotNull Identifier key, boolean 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.util.collection.KMap;
import com.volmit.iris.util.data.IrisCustomData;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.MissingResourceException;
@Getter
@RequiredArgsConstructor
public abstract class ExternalDataProvider {
@Getter
@NonNull
private final String pluginId;
@Nullable
public Plugin getPlugin() {
return Bukkit.getPluginManager().getPlugin(pluginId);
}
@@ -28,23 +34,60 @@ public abstract class ExternalDataProvider {
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<>());
}
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 IrisCustomData} 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<>());
}
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 IrisCustomData}
*
* @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

@@ -6,7 +6,7 @@ import com.volmit.iris.core.service.ExternalDataSVC;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.reflect.WrappedField;
import com.volmit.iris.util.reflect.WrappedReturningMethod;
import org.bukkit.Bukkit;
@@ -16,6 +16,7 @@ import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Leaves;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.MissingResourceException;
@@ -51,8 +52,9 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
}
}
@NotNull
@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());
if (o == null)
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
@@ -62,18 +64,19 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
BlockData blockData = Bukkit.createBlockData(material);
if (IrisSettings.get().getGenerator().preventLeafDecay && blockData instanceof Leaves leaves)
leaves.setPersistent(true);
return new IrisBlockData(blockData, ExternalDataSVC.buildState(blockId, state));
return new IrisCustomData(blockData, ExternalDataSVC.buildState(blockId, state));
}
@NotNull
@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()))
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
return itemDataField.get(itemId.key()).get();
}
@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);
blockId = pair.getA();
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false});
@@ -86,6 +89,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
}
}
@NotNull
@Override
public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>();
@@ -101,6 +105,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
return names.toArray(new Identifier[0]);
}
@NotNull
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
@@ -117,7 +122,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
}
@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());
}

View File

@@ -7,6 +7,7 @@ import dev.lone.itemsadder.api.CustomBlock;
import dev.lone.itemsadder.api.CustomStack;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException;
@@ -32,13 +33,15 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
}
}
@NotNull
@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());
}
@NotNull
@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());
if (stack == null) {
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
@@ -46,6 +49,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
return stack.getItemStack();
}
@NotNull
@Override
public Identifier[] getBlockTypes() {
KList<Identifier> keys = new KList<>();
@@ -55,6 +59,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
return keys.toArray(new Identifier[0]);
}
@NotNull
@Override
public Identifier[] getItemTypes() {
KList<Identifier> keys = new KList<>();
@@ -65,7 +70,7 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
}
@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());
}
}

View File

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

View File

@@ -0,0 +1,171 @@
/*
* 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.IrisCustomData;
import com.volmit.iris.util.math.RNG;
import io.lumine.mythic.bukkit.BukkitAdapter;
import io.lumine.mythic.bukkit.utils.serialize.Chroma;
import io.lumine.mythiccrucible.MythicCrucible;
import io.lumine.mythiccrucible.items.CrucibleItem;
import io.lumine.mythiccrucible.items.ItemManager;
import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.MissingResourceException;
import java.util.Optional;
public class MythicCrucibleDataProvider extends ExternalDataProvider {
private ItemManager itemManager;
public MythicCrucibleDataProvider() {
super("MythicCrucible");
}
@Override
public void init() {
Iris.info("Setting up MythicCrucible Link...");
try {
this.itemManager = MythicCrucible.inst().getItemManager();
} catch (Exception e) {
Iris.error("Failed to set up MythicCrucible Link: Unable to fetch MythicCrucible instance!");
}
}
@NotNull
@Override
public BlockData getBlockData(@NotNull Identifier blockId, @NotNull KMap<String, String> state) throws MissingResourceException {
CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key())
.orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()));
CustomBlockItemContext blockItemContext = crucibleItem.getBlockData();
FurnitureItemContext furnitureItemContext = crucibleItem.getFurnitureData();
if (furnitureItemContext != null) {
return new IrisCustomData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
} else if (blockItemContext != null) {
return blockItemContext.getBlockData();
}
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 {
Optional<CrucibleItem> opt = this.itemManager.getItem(itemId.key());
return BukkitAdapter.adapt(opt.orElseThrow(() ->
new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()))
.getMythicItem()
.generateItemStack(1));
}
@NotNull
@Override
public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>();
for (CrucibleItem item : this.itemManager.getItems()) {
if (item.getBlockData() == null) continue;
try {
Identifier key = new Identifier("crucible", item.getInternalName());
if (getBlockData(key) != null) {
Iris.info("getBlockTypes: Block loaded '" + item.getInternalName() + "'");
names.add(key);
}
} catch (MissingResourceException ignored) {}
}
return names.toArray(new Identifier[0]);
}
@NotNull
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
for (CrucibleItem item : this.itemManager.getItems()) {
try {
Identifier key = new Identifier("crucible", item.getInternalName());
if (getItemStack(key) != null) {
Iris.info("getItemTypes: Item loaded '" + item.getInternalName() + "'");
names.add(key);
}
} catch (MissingResourceException ignored) {}
}
return names.toArray(new Identifier[0]);
}
@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();
Optional<CrucibleItem> item = itemManager.getItem(blockId.key());
if (item.isEmpty()) return;
FurnitureItemContext furniture = item.get().getFurnitureData();
if (furniture == null) return;
float yaw = 0;
BlockFace face = BlockFace.NORTH;
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
RNG rng = new RNG(seed);
if ("true".equals(state.get("randomYaw"))) {
yaw = rng.f(0, 360);
} else if (state.containsKey("yaw")) {
yaw = Float.parseFloat(state.get("yaw"));
}
if ("true".equals(state.get("randomFace"))) {
BlockFace[] faces = BlockFace.values();
face = faces[rng.i(0, faces.length - 1)];
} else if (state.containsKey("face")) {
face = BlockFace.valueOf(state.get("face").toUpperCase());
}
if (face == BlockFace.SELF) {
face = BlockFace.NORTH;
}
BiomeColor type = null;
Chroma color = 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;
color = Chroma.of(biomeColor.getRGB());
}
furniture.place(block, face, yaw, color);
}
@Override
public boolean isValidProvider(@NotNull Identifier key, boolean isItem) {
return key.namespace().equalsIgnoreCase("crucible");
}
}

View File

@@ -26,6 +26,7 @@ import org.bukkit.plugin.Plugin;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
public class MythicMobsLink {
@@ -54,6 +55,6 @@ public class MythicMobsLink {
}
public Collection<String> getMythicMobTypes() {
return isEnabled() ? MythicBukkit.inst().getMobManager().getMobNames() : null;
return isEnabled() ? MythicBukkit.inst().getMobManager().getMobNames() : List.of();
}
}

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.IrisCustomData;
import com.volmit.iris.util.math.RNG;
import org.bukkit.Color;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.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 IrisCustomData(data, blockState);
} else if (NexoFurniture.isFurniture(blockId.key())) {
return new IrisCustomData(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.parallel.BurstExecutor;
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.J;
import lombok.Data;
@@ -337,6 +338,15 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
this.imageLoader = registerLoader(IrisImage.class);
this.scriptLoader = registerLoader(IrisScript.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();
}
@@ -434,6 +444,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
return adapter.read(reader);
} catch (Throwable e) {
Iris.error("Failed to read " + typeToken.getRawType().getCanonicalName() + "... faking objects a little to load the file at least.");
Iris.reportError(e);
try {
return (T) typeToken.getRawType().getConstructor().newInstance();
} catch (Throwable ignored) {

View File

@@ -27,10 +27,13 @@ import java.util.Map;
public class INMS {
private static final Map<String, String> REVISION = Map.of(
"1.20.5", "v1_20_R4",
"1.20.6", "v1_20_R4",
"1.21", "v1_21_R1",
"1.21.1", "v1_21_R1"
"1.20.5", "v1_20_R4",
"1.20.6", "v1_20_R4",
"1.21", "v1_21_R1",
"1.21.1", "v1_21_R1",
"1.21.2", "v1_21_R2",
"1.21.3", "v1_21_R2",
"1.21.4", "v1_21_R3"
);
//@done
private static final INMSBinding binding = bind();

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.datapack.v1192.DataFixerV1192;
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 lombok.AccessLevel;
import lombok.Getter;
@@ -13,7 +14,8 @@ import java.util.function.Supplier;
@Getter
public enum DataVersion {
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<>();
@Getter(AccessLevel.NONE)
private final Supplier<IDataFixer> constructor;

View File

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

@@ -21,7 +21,6 @@ package com.volmit.iris.core.nms.v1X;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
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.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
@@ -32,7 +31,6 @@ import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
@@ -40,8 +38,8 @@ import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.structure.Structure;
import org.bukkit.inventory.ItemStack;
import java.awt.*;
import java.awt.Color;
import java.util.stream.StreamSupport;
public class NMSBinding1X implements INMSBinding {
private static final boolean supportsCustomHeight = testCustomHeight();
@@ -113,7 +111,7 @@ public class NMSBinding1X implements INMSBinding {
@Override
public KList<String> getStructureKeys() {
var list = Registry.STRUCTURE.stream()
var list = StreamSupport.stream(Registry.STRUCTURE.spliterator(), false)
.map(Structure::getKey)
.map(NamespacedKey::toString)
.toList();

View File

@@ -1,16 +1,21 @@
package com.volmit.iris.core.pregenerator;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.core.tools.IrisToolbelt;
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.format.Form;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.profile.LoadBalancer;
import com.volmit.iris.util.scheduling.J;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
@@ -23,53 +28,40 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class ChunkUpdater {
private AtomicBoolean paused;
private AtomicBoolean cancelled;
private KMap<Chunk, Long> lastUse;
private final RollingSequence chunksPerSecond;
private final AtomicInteger worldheightsize;
private final AtomicInteger worldwidthsize;
private final AtomicInteger totalChunks;
private final AtomicInteger totalMaxChunks;
private final AtomicInteger totalMcaregions;
private final AtomicInteger position;
private AtomicInteger chunksProcessed;
private AtomicInteger chunksUpdated;
private AtomicLong startTime;
private ExecutorService executor;
private ExecutorService chunkExecutor;
private ScheduledExecutorService scheduler;
private CompletableFuture future;
private CountDownLatch latch;
private final Object pauseLock;
private final AtomicBoolean paused = new AtomicBoolean();
private final AtomicBoolean cancelled = new AtomicBoolean();
private final KMap<Long, Pair<Long, AtomicInteger>> lastUse = new KMap<>();
private final RollingSequence chunksPerSecond = new RollingSequence(5);
private final AtomicInteger totalMaxChunks = new AtomicInteger();
private final AtomicInteger chunksProcessed = new AtomicInteger();
private final AtomicInteger chunksProcessedLast = new AtomicInteger();
private final AtomicInteger chunksUpdated = new AtomicInteger();
private final AtomicBoolean serverEmpty = new AtomicBoolean(true);
private final AtomicLong lastCpsTime = new AtomicLong(M.ms());
private final int coreLimit = (int) Math.max(Runtime.getRuntime().availableProcessors() * IrisSettings.get().getUpdater().getThreadMultiplier(), 1);
private final Semaphore semaphore = new Semaphore(256);
private final LoadBalancer loadBalancer = new LoadBalancer(semaphore, 256, IrisSettings.get().getUpdater().emptyMsRange);
private final AtomicLong startTime = new AtomicLong();
private final Dimensions dimensions;
private final PregenTask task;
private final ExecutorService executor = Executors.newFixedThreadPool(coreLimit);
private final ExecutorService chunkExecutor = Executors.newFixedThreadPool(coreLimit);
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private final CountDownLatch latch;
private final Engine engine;
private final World world;
public ChunkUpdater(World world) {
this.engine = IrisToolbelt.access(world).getEngine();
this.chunksPerSecond = new RollingSequence(5);
this.world = world;
this.lastUse = new KMap();
this.worldheightsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 1));
this.worldwidthsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 0));
int m = Math.max(worldheightsize.get(), worldwidthsize.get());
this.executor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
this.chunkExecutor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
this.scheduler = Executors.newScheduledThreadPool(1);
this.future = new CompletableFuture<>();
this.startTime = new AtomicLong();
this.worldheightsize.set(m);
this.worldwidthsize.set(m);
this.totalMaxChunks = new AtomicInteger((worldheightsize.get() / 16) * (worldwidthsize.get() / 16));
this.chunksProcessed = new AtomicInteger();
this.chunksUpdated = new AtomicInteger();
this.position = new AtomicInteger(0);
this.dimensions = calculateWorldDimensions(new File(world.getWorldFolder(), "region"));
this.task = dimensions.task();
this.totalMaxChunks.set(dimensions.count * 1024);
this.latch = new CountDownLatch(totalMaxChunks.get());
this.paused = new AtomicBoolean(false);
this.pauseLock = new Object();
this.cancelled = new AtomicBoolean(false);
this.totalChunks = new AtomicInteger(0);
this.totalMcaregions = new AtomicInteger(0);
}
public String getName() {
return world.getName();
}
public int getChunks() {
@@ -97,7 +89,6 @@ public class ChunkUpdater {
cancelled.set(true);
}
private void update() {
Iris.info("Updating..");
try {
@@ -106,11 +97,11 @@ public class ChunkUpdater {
try {
if (!paused.get()) {
long eta = computeETA();
long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000;
int processed = chunksProcessed.get();
double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0;
double last = processed - chunksProcessedLast.getAndSet(processed);
double cps = last / ((M.ms() - lastCpsTime.getAndSet(M.ms())) / 1000d);
chunksPerSecond.put(cps);
double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100;
double percentage = ((double) processed / (double) totalMaxChunks.get()) * 100;
if (!cancelled.get()) {
Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta,
2), percentage);
@@ -120,35 +111,20 @@ public class ChunkUpdater {
e.printStackTrace();
}
}, 0, 3, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(this::unloadChunks, 0, 1, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(() -> {
boolean empty = Bukkit.getOnlinePlayers().isEmpty();
if (serverEmpty.getAndSet(empty) == empty)
return;
loadBalancer.setRange(empty ? IrisSettings.get().getUpdater().emptyMsRange : IrisSettings.get().getUpdater().defaultMsRange);
}, 0, 10, TimeUnit.SECONDS);
CompletableFuture.runAsync(() -> {
for (int i = 0; i < totalMaxChunks.get(); i++) {
if (paused.get()) {
synchronized (pauseLock) {
try {
pauseLock.wait();
} catch (InterruptedException e) {
Iris.error("Interrupted while waiting for executor: ");
e.printStackTrace();
break;
}
}
}
executor.submit(() -> {
if (!cancelled.get()) {
processNextChunk();
}
latch.countDown();
});
}
}).thenRun(() -> {
try {
latch.await();
close();
} catch (Exception e) {
Thread.currentThread().interrupt();
}
});
var t = new Thread(() -> {
run();
close();
}, "Iris Chunk Updater - " + world.getName());
t.setPriority(Thread.MAX_PRIORITY);
t.start();
} catch (Exception e) {
e.printStackTrace();
@@ -157,14 +133,16 @@ public class ChunkUpdater {
public void close() {
try {
unloadAndSaveAllChunks();
loadBalancer.close();
semaphore.acquire(256);
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
chunkExecutor.shutdown();
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
scheduler.shutdownNow();
} catch (Exception ignored) {
}
unloadAndSaveAllChunks();
} catch (Exception ignored) {}
if (cancelled.get()) {
Iris.info("Updated: " + Form.f(chunksUpdated.get()) + " Chunks");
Iris.info("Irritated: " + Form.f(chunksProcessed.get()) + " of " + Form.f(totalMaxChunks.get()));
@@ -175,18 +153,69 @@ public class ChunkUpdater {
}
}
private void processNextChunk() {
int pos = position.getAndIncrement();
int[] coords = getChunk(pos);
if (loadChunksIfGenerated(coords[0], coords[1])) {
Chunk c = world.getChunkAt(coords[0], coords[1]);
engine.updateChunk(c);
chunksUpdated.incrementAndGet();
private void run() {
task.iterateRegions((rX, rZ) -> {
if (cancelled.get())
return;
while (paused.get()) {
J.sleep(50);
}
if (rX < dimensions.min.getX() || rX > dimensions.max.getX() || rZ < dimensions.min.getZ() || rZ > dimensions.max.getZ()) {
return;
}
PregenTask.iterateRegion(rX, rZ, (x, z) -> {
while (paused.get() && !cancelled.get()) {
J.sleep(50);
}
try {
semaphore.acquire();
} catch (InterruptedException ignored) {
return;
}
chunkExecutor.submit(() -> {
try {
if (!cancelled.get())
processChunk(x, z);
} finally {
latch.countDown();
semaphore.release();
}
});
});
});
}
private void processChunk(int x, int z) {
if (!loadChunksIfGenerated(x, z)) {
chunksProcessed.getAndIncrement();
return;
}
try {
Chunk c = world.getChunkAt(x, z);
engine.getMantle().getMantle().getChunk(c);
engine.updateChunk(c);
for (int xx = -1; xx <= 1; xx++) {
for (int zz = -1; zz <= 1; zz++) {
var counter = lastUse.get(Cache.key(x + xx, z + zz));
if (counter != null) counter.getB().decrementAndGet();
}
}
} finally {
chunksUpdated.incrementAndGet();
chunksProcessed.getAndIncrement();
}
chunksProcessed.getAndIncrement();
}
private boolean loadChunksIfGenerated(int x, int z) {
if (engine.getMantle().getMantle().hasFlag(x, z, MantleFlag.ETCHED))
return false;
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) {
@@ -196,45 +225,79 @@ public class ChunkUpdater {
}
AtomicBoolean generated = new AtomicBoolean(true);
KList<Future<?>> futures = new KList<>(9);
CountDownLatch latch = new CountDownLatch(9);
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
int xx = x + dx;
int zz = z + dz;
futures.add(chunkExecutor.submit(() -> {
Chunk c;
executor.submit(() -> {
try {
c = PaperLib.getChunkAtAsync(world, xx, zz, false).get();
} catch (InterruptedException | ExecutionException e) {
generated.set(false);
return;
}
if (!c.isLoaded()) {
CountDownLatch latch = new CountDownLatch(1);
J.s(() -> {
c.load(false);
latch.countDown();
});
Chunk c;
try {
latch.await();
} catch (InterruptedException ignored) {}
c = PaperLib.getChunkAtAsync(world, xx, zz, false, true)
.thenApply(chunk -> {
if (chunk != null)
chunk.addPluginChunkTicket(Iris.instance);
return chunk;
}).get();
} catch (InterruptedException | ExecutionException e) {
generated.set(false);
return;
}
if (c == null) {
generated.set(false);
return;
}
if (!c.isLoaded()) {
var future = J.sfut(() -> c.load(false));
if (future != null) future.join();
}
if (!PaperLib.isChunkGenerated(c.getWorld(), xx, zz))
generated.set(false);
var pair = lastUse.computeIfAbsent(Cache.key(c), k -> new Pair<>(0L, new AtomicInteger(-1)));
pair.setA(M.ms());
pair.getB().updateAndGet(i -> i == -1 ? 1 : ++i);
} finally {
latch.countDown();
}
if (!c.isGenerated()) {
generated.set(false);
}
lastUse.put(c, M.ms());
}));
});
}
}
while (!futures.isEmpty()) {
futures.removeIf(Future::isDone);
try {
Thread.sleep(50);
} catch (InterruptedException ignored) {}
try {
latch.await();
} catch (InterruptedException e) {
Iris.info("Interrupted while waiting for chunks to load");
}
return generated.get();
}
private synchronized void unloadChunks() {
for (var key : new ArrayList<>(lastUse.keySet())) {
if (key == null) continue;
var pair = lastUse.get(key);
if (pair == null) continue;
var lastUseTime = pair.getA();
var counter = pair.getB();
if (lastUseTime == null || counter == null)
continue;
if (M.ms() - lastUseTime >= 5000 && counter.get() == 0) {
int x = Cache.keyX(key);
int z = Cache.keyZ(key);
J.s(() -> {
world.removePluginChunkTicket(x, z, Iris.instance);
world.unloadChunk(x, z);
lastUse.remove(key);
});
}
}
}
private void unloadAndSaveAllChunks() {
try {
J.sfut(() -> {
@@ -243,13 +306,7 @@ public class ChunkUpdater {
return;
}
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
Long lastUseTime = lastUse.get(i);
if (lastUseTime != null && M.ms() - lastUseTime >= 5000) {
i.unload();
lastUse.remove(i);
}
}
unloadChunks();
world.save();
}).get();
} catch (Throwable e) {
@@ -266,7 +323,7 @@ public class ChunkUpdater {
);
}
public int calculateWorldDimensions(File regionDir, Integer o) {
private Dimensions calculateWorldDimensions(File regionDir) {
File[] files = regionDir.listFiles((dir, name) -> name.endsWith(".mca"));
int minX = Integer.MAX_VALUE;
@@ -279,40 +336,23 @@ public class ChunkUpdater {
int x = Integer.parseInt(parts[1]);
int z = Integer.parseInt(parts[2]);
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (z < minZ) minZ = z;
if (z > maxZ) maxZ = z;
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minZ = Math.min(minZ, z);
maxZ = Math.max(maxZ, z);
}
int oX = minX + ((maxX - minX) / 2);
int oZ = minZ + ((maxZ - minZ) / 2);
int height = (maxX - minX + 1) * 32 * 16;
int width = (maxZ - minZ + 1) * 32 * 16;
int height = maxX - minX + 1;
int width = maxZ - minZ + 1;
if (o == 1) {
return height;
}
if (o == 0) {
return width;
}
return 0;
return new Dimensions(new Position2(minX, minZ), new Position2(maxX, maxZ), height * width, PregenTask.builder()
.width((int) Math.ceil(width / 2d))
.height((int) Math.ceil(height / 2d))
.center(new Position2(oX, oZ))
.build());
}
public int[] getChunk(int position) {
int p = -1;
AtomicInteger xx = new AtomicInteger();
AtomicInteger zz = new AtomicInteger();
Spiraler s = new Spiraler(worldheightsize.get() * 2, worldwidthsize.get() * 2, (x, z) -> {
xx.set(x);
zz.set(z);
});
while (s.hasNext() && p++ < position) {
s.next();
}
int[] coords = new int[2];
coords[0] = xx.get();
coords[1] = zz.get();
return coords;
}
private record Dimensions(Position2 min, Position2 max, int count, PregenTask task) { }
}

View File

@@ -15,7 +15,6 @@ 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.Builder;
import lombok.Data;
import lombok.Getter;
import org.bukkit.Bukkit;
@@ -261,14 +260,14 @@ public class DeepSearchPregenerator extends Thread implements Listener {
}
@Data
@Builder
@lombok.Builder
public static class DeepSearchJob {
private World world;
@Builder.Default
@lombok.Builder.Default
private int radiusBlocks = 5000;
@Builder.Default
@lombok.Builder.Default
private int position = 0;
@Builder.Default
@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.J;
import io.papermc.lib.PaperLib;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import org.bukkit.Bukkit;
@@ -264,22 +263,22 @@ public class LazyPregenerator extends Thread implements Listener {
}
@Data
@Builder
@lombok.Builder
public static class LazyPregenJob {
private String world;
@Builder.Default
@lombok.Builder.Default
private int healingPosition = 0;
@Builder.Default
@lombok.Builder.Default
private boolean healing = false;
@Builder.Default
@lombok.Builder.Default
private int chunksPerMinute = 32;
@Builder.Default
@lombok.Builder.Default
private int radiusBlocks = 5000;
@Builder.Default
@lombok.Builder.Default
private int position = 0;
@Builder.Default
@lombok.Builder.Default
boolean silent = false;
@Builder.Default
@lombok.Builder.Default
boolean paused = false;
}
}

View File

@@ -18,7 +18,6 @@ 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.Builder;
import lombok.Data;
import lombok.Getter;
import org.apache.logging.log4j.core.util.ExecutorServices;
@@ -328,14 +327,14 @@ public class TurboPregenerator extends Thread implements Listener {
}
@Data
@Builder
@lombok.Builder
public static class TurboPregenJob {
private String world;
@Builder.Default
@lombok.Builder.Default
private int radiusBlocks = 5000;
@Builder.Default
@lombok.Builder.Default
private int position = 0;
@Builder.Default
@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.PregeneratorMethod;
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.mantle.Mantle;
import com.volmit.iris.util.math.M;
@@ -34,12 +33,12 @@ import org.bukkit.World;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
public class AsyncPregenMethod implements PregeneratorMethod {
private final World world;
private final MultiBurst burst;
private final KList<Future<?>> future;
private final Semaphore semaphore;
private final Map<Chunk, Long> lastUse;
public AsyncPregenMethod(World world, int threads) {
@@ -49,7 +48,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
this.world = world;
burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY);
future = new KList<>(256);
semaphore = new Semaphore(256);
this.lastUse = new KMap<>();
}
@@ -63,7 +62,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
Long lastUseTime = lastUse.get(i);
if (lastUseTime != null && M.ms() - lastUseTime >= 10000) {
if (!i.isLoaded() || (lastUseTime != null && M.ms() - lastUseTime >= 10000)) {
i.unload();
lastUse.remove(i);
}
@@ -85,37 +84,8 @@ public class AsyncPregenMethod implements PregeneratorMethod {
} catch (InterruptedException ignored) {
} catch (Throwable e) {
e.printStackTrace();
}
}
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();
}
} finally {
semaphore.release();
}
}
@@ -131,14 +101,13 @@ public class AsyncPregenMethod implements PregeneratorMethod {
@Override
public void close() {
waitForChunks();
semaphore.acquireUninterruptibly(256);
unloadAndSaveAllChunks();
burst.close();
}
@Override
public void save() {
waitForChunksPartial(256);
unloadAndSaveAllChunks();
}
@@ -155,10 +124,12 @@ public class AsyncPregenMethod implements PregeneratorMethod {
@Override
public void generateChunk(int x, int z, PregenListener listener) {
listener.onChunkGenerating(x, z);
if (future.size() > 256) {
waitForChunksPartial(256);
try {
semaphore.acquire();
} catch (InterruptedException e) {
return;
}
future.add(burst.complete(() -> completeChunk(x, z, listener)));
burst.complete(() -> completeChunk(x, z, listener));
}
@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.IrisRegistrant;
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.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.json.JSONArray;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.reflect.OldEnum;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class SchemaBuilder {
@@ -44,7 +46,6 @@ public class SchemaBuilder {
private static final String SYMBOL_TYPE__N = "";
private static final JSONArray POTION_TYPES = getPotionTypes();
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 final KMap<String, JSONObject> definitions;
private final Class<?> root;
@@ -262,7 +263,7 @@ public class SchemaBuilder {
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put("enum", ITEM_TYPES);
j.put("enum", B.getItemTypes());
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!)");
} else if (k.getType().isEnum()) {
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "");
JSONArray a = new JSONArray();
boolean advanced = k.getType().isAnnotationPresent(Desc.class);
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!)");
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
} else if (OldEnum.isOldEnum(k.getType())) {
fancyType = addEnum(k.getType(), prop, description, OldEnum.values(k.getType()), OldEnum::name);
}
}
case "object" -> {
@@ -468,7 +440,7 @@ public class SchemaBuilder {
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put("enum", ITEM_TYPES);
j.put("enum", B.getItemTypes());
definitions.put(key, j);
}
@@ -519,39 +491,9 @@ public class SchemaBuilder {
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
} else if (t.type().isEnum()) {
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s";
JSONArray a = new JSONArray();
boolean advanced = t.type().isAnnotationPresent(Desc.class);
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!)");
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
} else if (OldEnum.isOldEnum(t.type())) {
fancyType = addEnumList(prop, description, t, OldEnum.values(t.type()), OldEnum::name);
}
}
}
@@ -584,7 +526,7 @@ public class SchemaBuilder {
if (value instanceof List) {
d.add(" ");
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("* Default Value is a default object (create this object to see default properties)");
} else {
@@ -630,6 +572,50 @@ public class SchemaBuilder {
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) {
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
return "integer";
@@ -643,7 +629,7 @@ public class SchemaBuilder {
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";
}

View File

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

View File

@@ -37,7 +37,7 @@ public class UtilsSFG {
}
if (ServerBootSFG.unsuportedversion) {
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.20.1 > 1.21.4");
}
if (!ServerBootSFG.passedserversoftware) {
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 + "- 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 + "- 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) {
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 java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class BoardSVC implements IrisService, BoardProvider {
private final KMap<Player, PlayerBoard> boards = new KMap<>();
@@ -104,11 +105,11 @@ public class BoardSVC implements IrisService, BoardProvider {
@Data
public static class PlayerBoard {
private final Player player;
private final KList<String> lines;
private final CopyOnWriteArrayList<String> lines;
public PlayerBoard(Player player) {
this.player = player;
this.lines = new KList<>();
this.lines = new CopyOnWriteArrayList<>();
update();
}

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.plugin.IrisService;
import lombok.Data;
import lombok.NonNull;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
@@ -46,9 +47,13 @@ public class ExternalDataSVC implements IrisService {
Iris.info("Loading ExternalDataProvider...");
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
providers.add(new OraxenDataProvider());
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
Iris.info("Oraxen found, loading OraxenDataProvider...");
providers.add(new NexoDataProvider());
if (Bukkit.getPluginManager().getPlugin("Nexo") != null) {
Iris.info("Nexo found, loading NexoDataProvider...");
}
providers.add(new MythicCrucibleDataProvider());
if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
Iris.info("MythicCrucible found, loading MythicCrucibleDataProvider...");
}
providers.add(new ItemAdderDataProvider());
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
@@ -95,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) {
var pair = parseState(key);
Identifier mod = pair.getA();

View File

@@ -63,7 +63,12 @@ public class StudioSVC implements IrisService {
if (!f.exists()) {
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

@@ -27,6 +27,7 @@ import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.Cuboid;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.math.BlockPosition;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.plugin.IrisService;
@@ -34,7 +35,6 @@ import com.volmit.iris.util.scheduling.J;
import org.bukkit.*;
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.type.Sapling;
import org.bukkit.event.EventHandler;
@@ -142,7 +142,9 @@ public class TreeSVC implements IrisService {
public void set(int x, int y, int z, BlockData d) {
Block b = event.getWorld().getBlockAt(x, y, z);
BlockState state = b.getState();
state.setBlockData(d);
if (d instanceof IrisCustomData data)
state.setBlockData(data.getBase());
else state.setBlockData(d);
blockStateList.add(b.getState());
dataCache.put(new Location(event.getWorld(), x, y, z), d);
}
@@ -213,12 +215,17 @@ public class TreeSVC implements IrisService {
block = false;
if (!iGrow.isCancelled()) {
for (BlockState block : iGrow.getBlocks()) {
Location l = block.getLocation();
for (BlockState state : iGrow.getBlocks()) {
Location l = state.getLocation();
if (dataCache.containsKey(l)) {
l.getBlock().setBlockData(dataCache.get(l), false);
}
BlockData d = dataCache.get(l);
if (d == null) continue;
Block block = l.getBlock();
if (d instanceof IrisCustomData data) {
block.setBlockData(data.getBase(), false);
Iris.service(ExternalDataSVC.class).processUpdate(engine, block, data.getCustom());
} else block.setBlockData(d);
}
}
});

View File

@@ -30,15 +30,12 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.matter.Matter;
import com.volmit.iris.util.matter.WorldMatter;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.S;
import com.volmit.iris.util.scheduling.SR;
import com.volmit.iris.util.scheduling.jobs.Job;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -56,11 +53,11 @@ import java.awt.Color;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import static com.volmit.iris.util.data.registry.Particles.CRIT_MAGIC;
import static com.volmit.iris.util.data.registry.Particles.REDSTONE;
public class WandSVC implements IrisService {
private static final Particle CRIT_MAGIC = E.getOrDefault(Particle.class, "CRIT_MAGIC", "CRIT");
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
private static final int MS_PER_TICK = Integer.parseInt(System.getProperty("iris.ms_per_tick", "30"));
private static ItemStack dust;
@@ -76,7 +73,7 @@ public class WandSVC implements IrisService {
* @param p The wand player
* @return The new object
*/
public static IrisObject createSchematic(Player p) {
public static IrisObject createSchematic(Player p, boolean legacy) {
if (!isHoldingWand(p)) {
return null;
}
@@ -132,7 +129,7 @@ public class WandSVC implements IrisService {
continue;
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 {
i++;
}

View File

@@ -24,10 +24,8 @@ import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.pregenerator.PregenTask;
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.platform.PlatformChunkGenerator;
import com.volmit.iris.core.safeguard.UtilsSFG;
import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.C;
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.AtomicReference;
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
@@ -86,7 +83,6 @@ public class IrisCreator {
* Benchmark mode
*/
private boolean benchmark = false;
private boolean smartVanillaHeight = false;
public static boolean removeFromBukkitYml(String name) throws IOException {
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
@@ -126,14 +122,11 @@ public class IrisCreator {
if (sender == null)
sender = Iris.getSender();
if (!studio()) {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
}
if (benchmark) {
if (!studio() || benchmark) {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
}
PlatformChunkGenerator access = null;
PlatformChunkGenerator access;
AtomicReference<World> world = new AtomicReference<>();
AtomicDouble pp = new AtomicDouble(0);
O<Boolean> done = new O<>();
@@ -143,7 +136,6 @@ public class IrisCreator {
.name(name)
.seed(seed)
.studio(studio)
.smartVanillaHeight(smartVanillaHeight)
.create();
ServerConfigurator.installDataPacks(false);

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

View File

@@ -32,7 +32,6 @@ public class IrisWorldCreator {
private String name;
private boolean studio = false;
private String dimensionName = null;
private boolean smartVanillaHeight = false;
private long seed = 1337;
public IrisWorldCreator() {
@@ -64,11 +63,6 @@ public class IrisWorldCreator {
return this;
}
public IrisWorldCreator smartVanillaHeight(boolean smartVanillaHeight) {
this.smartVanillaHeight = smartVanillaHeight;
return this;
}
public WorldCreator create() {
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
@@ -82,7 +76,7 @@ public class IrisWorldCreator {
.build();
ChunkGenerator g = new BukkitChunkGenerator(w, studio, studio
? dim.getLoader().getDataFolder() :
new File(w.worldFolder(), "iris/pack"), dimensionName, smartVanillaHeight);
new File(w.worldFolder(), "iris/pack"), dimensionName);
return new WorldCreator(name)

View File

@@ -20,8 +20,6 @@ package com.volmit.iris.core.wand;
import com.volmit.iris.util.data.Cuboid;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
@@ -29,8 +27,9 @@ import org.bukkit.util.Vector;
import java.awt.*;
import static com.volmit.iris.util.data.registry.Particles.REDSTONE;
public class WandSelection {
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
private final Cuboid c;
private final Player p;
private static final double STEP = 0.10;

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

View File

@@ -21,10 +21,10 @@ package com.volmit.iris.engine;
import com.google.common.util.concurrent.AtomicDouble;
import com.google.gson.Gson;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
import com.volmit.iris.core.gui.PregeneratorJob;
import com.volmit.iris.core.loader.ResourceLoader;
import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.core.project.IrisProject;
@@ -53,7 +53,6 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -63,11 +62,10 @@ import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Data
@EqualsAndHashCode(exclude = "context")
@@ -92,6 +90,7 @@ public class IrisEngine implements Engine {
private final AtomicBoolean cleaning;
private final ChronoLatch cleanLatch;
private final SeedManager seedManager;
private CompletableFuture<Long> hash32;
private EngineMode mode;
private EngineEffects effects;
private EngineExecutionEnvironment execution;
@@ -174,8 +173,17 @@ public class IrisEngine implements Engine {
complex = new IrisComplex(this);
execution = new IrisExecutionEnvironment(this);
effects = new IrisEngineEffects(this);
hash32 = new CompletableFuture<>();
setupMode();
J.a(this::computeBiomeMaxes);
J.a(() -> {
File[] roots = getData().getLoaders()
.values()
.stream()
.map(ResourceLoader::getRoot)
.toArray(File[]::new);
hash32.complete(IO.hashRecursive(roots));
});
} catch (Throwable e) {
Iris.error("FAILED TO SETUP ENGINE!");
e.printStackTrace();

View File

@@ -18,7 +18,7 @@
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.framework.Engine;
import com.volmit.iris.engine.mantle.EngineMantle;
@@ -27,23 +27,13 @@ import com.volmit.iris.engine.mantle.components.MantleCarvingComponent;
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.KMap;
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.mantle.Mantle;
import com.volmit.iris.util.parallel.BurstExecutor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.bukkit.util.BlockVector;
import lombok.*;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Data
@EqualsAndHashCode(exclude = "engine")
@@ -51,8 +41,9 @@ import java.util.concurrent.atomic.AtomicInteger;
public class IrisEngineMantle implements EngineMantle {
private final Engine engine;
private final Mantle mantle;
private final KList<MantleComponent> components;
private final int radius;
@Getter(AccessLevel.NONE)
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 MantleObjectComponent object;
private final MantleJigsawComponent jigsaw;
@@ -60,8 +51,7 @@ public class IrisEngineMantle implements EngineMantle {
public IrisEngineMantle(Engine engine) {
this.engine = engine;
this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight());
radius = radCache.aquire(this::computeParallaxSize);
components = new KList<>();
components = new KMap<>();
registerComponent(new MantleCarvingComponent(this));
registerComponent(new MantleFluidBodyComponent(this));
jigsaw = new MantleJigsawComponent(this);
@@ -70,9 +60,49 @@ public class IrisEngineMantle implements EngineMantle {
registerComponent(object);
}
@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
public void registerComponent(MantleComponent c) {
components.add(c);
components.computeIfAbsent(c.getPriority(), k -> new KList<>()).add(c);
componentsCache.reset();
}
@Override
@@ -84,243 +114,4 @@ public class IrisEngineMantle implements EngineMantle {
public MantleObjectComponent getObjectComponent() {
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();
IrisEngineSpawnerCooldown cd = null;
for (IrisEngineSpawnerCooldown j : ed.getSpawnerCooldowns()) {
for (IrisEngineSpawnerCooldown j : ed.getSpawnerCooldowns().copy()) {
if (j.getSpawner().equals(i.getLoadKey())) {
cd = j;
}

View File

@@ -21,7 +21,7 @@ package com.volmit.iris.engine.data.chunk;
import com.volmit.iris.core.nms.BiomeBaseInjector;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.util.data.IrisBiomeStorage;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.data.IrisCustomData;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -121,7 +121,7 @@ public class LinkedTerrainChunk implements TerrainChunk {
@Override
public synchronized void setBlock(int x, int y, int z, BlockData blockData) {
if (blockData instanceof IrisBlockData d)
if (blockData instanceof IrisCustomData d)
blockData = d.getBase();
rawChunkData.setBlock(x, y, z, blockData);
}

View File

@@ -20,7 +20,7 @@ package com.volmit.iris.engine.data.chunk;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.BiomeBaseInjector;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.nbt.mca.Chunk;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import lombok.AllArgsConstructor;
@@ -89,7 +89,7 @@ public class MCATerrainChunk implements TerrainChunk {
if (blockData == null) {
Iris.error("NULL BD");
}
if (blockData instanceof IrisBlockData data)
if (blockData instanceof IrisCustomData data)
blockData = data.getBase();
mcaChunk.setBlockStateAt(xx, y, zz, NBTWorld.getCompound(blockData), false);

View File

@@ -18,18 +18,16 @@
package com.volmit.iris.engine.decorator;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisDecorationPart;
import com.volmit.iris.engine.object.IrisDecorator;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.block.data.type.PointedDripstone;
public class IrisCeilingDecorator extends IrisEngineDecorator {
@@ -40,20 +38,14 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
@BlockCoordinates
@Override
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
IrisDecorator decorator = getDecorator(biome, realX, realZ);
RNG rng = getRNG(realX, realZ);
IrisDecorator decorator = getDecorator(rng, biome, realX, realZ);
if (decorator != null) {
if (!decorator.isStacking()) {
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()));
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()));
}
}
data.set(x, height, z, fixFaces(decorator.getBlockData100(biome, rng, realX, height, realZ, getData()), data, x, z, realX, height, realZ));
} else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
int stack = decorator.getHeight(rng, realX, realZ, getData());
if (decorator.isScaleStack()) {
stack = Math.min((int) Math.ceil((double) max * ((double) stack / 100)), decorator.getAbsoluteMaxStack());
} else {
@@ -61,7 +53,7 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
}
if (stack == 1) {
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
data.set(x, height, z, decorator.getBlockDataForTop(biome, rng, realX, height, realZ, getData()));
return;
}
@@ -74,8 +66,8 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
double threshold = (((double) i) / (double) (stack - 1));
BlockData bd = threshold >= decorator.getTopThreshold() ?
decorator.getBlockDataForTop(biome, getRng(), realX, h, realZ, getData()) :
decorator.getBlockData100(biome, getRng(), realX, h, realZ, getData());
decorator.getBlockDataForTop(biome, rng, realX, h, realZ, getData()) :
decorator.getBlockData100(biome, rng, realX, h, realZ, getData());
if (bd instanceof PointedDripstone) {
PointedDripstone.Thickness th = PointedDripstone.Thickness.BASE;
@@ -105,24 +97,4 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
}
}
}
private BlockData fixFaces(BlockData b, int x, int y, int z) {
if (B.isVineBlock(b)) {
MultipleFacing data = (MultipleFacing) b.clone();
boolean found = false;
for (BlockFace f : BlockFace.values()) {
if (!f.isCartesian())
continue;
Material m = getEngine().getMantle().get(x + f.getModX(), y + f.getModY(), z + f.getModZ()).getMaterial();
if (m.isSolid()) {
found = true;
data.setFace(f, m.isSolid());
}
}
if (!found)
data.setFace(BlockFace.UP, true);
return data;
}
return b;
}
}

View File

@@ -19,7 +19,6 @@
package com.volmit.iris.engine.decorator;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedComponent;
import com.volmit.iris.engine.framework.EngineDecorator;
@@ -27,30 +26,42 @@ import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisDecorationPart;
import com.volmit.iris.engine.object.IrisDecorator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.math.RNG;
import lombok.Getter;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockSupport;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
public abstract class IrisEngineDecorator extends EngineAssignedComponent implements EngineDecorator {
@Getter
private final RNG rng;
@Getter
private final IrisDecorationPart part;
private final long seed;
private final long modX, modZ;
public IrisEngineDecorator(Engine engine, String name, IrisDecorationPart part) {
super(engine, name + " Decorator");
this.part = part;
this.rng = new RNG(getSeed() + 29356788 - (part.ordinal() * 10439677L));
this.seed = getSeed() + 29356788 - (part.ordinal() * 10439677L);
this.modX = 29356788 ^ (part.ordinal() + 6);
this.modZ = 10439677 ^ (part.ordinal() + 1);
}
protected IrisDecorator getDecorator(IrisBiome biome, double realX, double realZ) {
KList<IrisDecorator> v = new KList<>();
RNG rng = new RNG(Cache.key((int) realX, (int) realZ));
@BlockCoordinates
protected RNG getRNG(int x, int z) {
return new RNG(x * modX + z * modZ + seed);
}
protected IrisDecorator getDecorator(RNG rng, IrisBiome biome, double realX, double realZ) {
KList<IrisDecorator> v = new KList<>();
RNG gRNG = new RNG(seed);
for (IrisDecorator i : biome.getDecorators()) {
try {
if (i.getPartOf().equals(part) && i.getBlockData(biome, this.rng, realX, realZ, getData()) != null) {
if (i.getPartOf().equals(part) && i.getBlockData(biome, gRNG, realX, realZ, getData()) != null) {
v.add(i);
}
} catch (Throwable e) {
@@ -65,4 +76,40 @@ public abstract class IrisEngineDecorator extends EngineAssignedComponent implem
return null;
}
protected BlockData fixFaces(BlockData b, Hunk<BlockData> hunk, int rX, int rZ, int x, int y, int z) {
if (B.isVineBlock(b)) {
MultipleFacing data = (MultipleFacing) b.clone();
data.getFaces().forEach(f -> data.setFace(f, false));
boolean found = false;
for (BlockFace f : BlockFace.values()) {
if (!f.isCartesian())
continue;
int yy = y + f.getModY();
BlockData r = getEngine().getMantle().get(x + f.getModX(), yy, z + f.getModZ());
if (r.isFaceSturdy(f.getOppositeFace(), BlockSupport.FULL)) {
found = true;
data.setFace(f, true);
continue;
}
int xx = rX + f.getModX();
int zz = rZ + f.getModZ();
if (xx < 0 || xx > 15 || zz < 0 || zz > 15 || yy < 0 || yy > hunk.getHeight())
continue;
r = hunk.get(xx, yy, zz);
if (r.isFaceSturdy(f.getOppositeFace(), BlockSupport.FULL)) {
found = true;
data.setFace(f, true);
}
}
if (!found)
data.setFace(BlockFace.DOWN, true);
return data;
}
return b;
}
}

View File

@@ -18,13 +18,13 @@
package com.volmit.iris.engine.decorator;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisDecorationPart;
import com.volmit.iris.engine.object.IrisDecorator;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import org.bukkit.block.data.BlockData;
public class IrisSeaFloorDecorator extends IrisEngineDecorator {
@@ -35,7 +35,8 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
@BlockCoordinates
@Override
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
IrisDecorator decorator = getDecorator(biome, realX, realZ);
RNG rng = getRNG(realX, realZ);
IrisDecorator decorator = getDecorator(rng, biome, realX, realZ);
if (decorator != null) {
if (!decorator.isStacking()) {
@@ -44,25 +45,17 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
return;
}
if (height >= 0 || height < getEngine().getHeight()) {
if (null != decorator.getBlockDataForTop(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()));
}
data.set(x, height, z, decorator.getBlockData100(biome, rng, realX, height, realZ, getData()));
}
} else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
int stack = decorator.getHeight(rng, realX, realZ, getData());
if (decorator.isScaleStack()) {
int maxStack = max - height;
stack = (int) Math.ceil((double) maxStack * ((double) stack / 100));
} else stack = Math.min(stack, max - height);
if (stack == 1) {
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
data.set(x, height, z, decorator.getBlockDataForTop(biome, rng, realX, height, realZ, getData()));
return;
}
@@ -74,8 +67,8 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
double threshold = ((double) i) / (stack - 1);
data.set(x, h, z, threshold >= decorator.getTopThreshold() ?
decorator.getBlockDataForTop(biome, getRng(), realX, h, realZ, getData()) :
decorator.getBlockData100(biome, getRng(), realX, h, realZ, getData()));
decorator.getBlockDataForTop(biome, rng, realX, h, realZ, getData()) :
decorator.getBlockData100(biome, rng, realX, h, realZ, getData()));
}
}
}

View File

@@ -18,13 +18,13 @@
package com.volmit.iris.engine.decorator;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisDecorationPart;
import com.volmit.iris.engine.object.IrisDecorator;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import org.bukkit.block.data.BlockData;
public class IrisSeaSurfaceDecorator extends IrisEngineDecorator {
@@ -35,28 +35,23 @@ public class IrisSeaSurfaceDecorator extends IrisEngineDecorator {
@BlockCoordinates
@Override
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
IrisDecorator decorator = getDecorator(biome, realX, realZ);
RNG rng = getRNG(realX, realZ);
IrisDecorator decorator = getDecorator(rng, biome, realX, realZ);
if (decorator != null) {
if (!decorator.isStacking()) {
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()));
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()));
}
data.set(x, height + 1, z, decorator.getBlockData100(biome, rng, realX, height, realZ, getData()));
}
} else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
int stack = decorator.getHeight(rng, realX, realZ, getData());
if (decorator.isScaleStack()) {
int maxStack = max - height;
stack = (int) Math.ceil((double) maxStack * ((double) stack / 100));
}
if (stack == 1) {
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
data.set(x, height, z, decorator.getBlockDataForTop(biome, rng, realX, height, realZ, getData()));
return;
}
@@ -68,8 +63,8 @@ public class IrisSeaSurfaceDecorator extends IrisEngineDecorator {
double threshold = ((double) i) / (stack - 1);
data.set(x, h + 1, z, threshold >= decorator.getTopThreshold() ?
decorator.getBlockDataForTop(biome, getRng().nextParallelRNG(i), realX, h, realZ, getData()) :
decorator.getBlockData100(biome, getRng().nextParallelRNG(i), realX, h, realZ, getData()));
decorator.getBlockDataForTop(biome, rng, realX, h, realZ, getData()) :
decorator.getBlockData100(biome, rng, realX, h, realZ, getData()));
}
}
}

View File

@@ -18,13 +18,13 @@
package com.volmit.iris.engine.decorator;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisDecorationPart;
import com.volmit.iris.engine.object.IrisDecorator;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import org.bukkit.block.data.BlockData;
public class IrisShoreLineDecorator extends IrisEngineDecorator {
@@ -42,7 +42,8 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
Math.round(getComplex().getHeightStream().get(realX, realZ1)) < getComplex().getFluidHeight() ||
Math.round(getComplex().getHeightStream().get(realX, realZ_1)) < getComplex().getFluidHeight()
) {
IrisDecorator decorator = getDecorator(biome, realX, realZ);
RNG rng = getRNG(realX, realZ);
IrisDecorator decorator = getDecorator(rng, biome, realX, realZ);
if (decorator != null) {
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
@@ -51,22 +52,16 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
}
if (!decorator.isStacking()) {
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()));
}
data.set(x, height + 1, z, decorator.getBlockData100(biome, rng, realX, height, realZ, getData()));
} else {
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
int stack = decorator.getHeight(rng, realX, realZ, getData());
if (decorator.isScaleStack()) {
int maxStack = max - height;
stack = (int) Math.ceil((double) maxStack * ((double) stack / 100));
} else stack = Math.min(max - height, stack);
if (stack == 1) {
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
data.set(x, height, z, decorator.getBlockDataForTop(biome, rng, realX, height, realZ, getData()));
return;
}
@@ -74,8 +69,8 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
int h = height + i;
double threshold = ((double) i) / (stack - 1);
data.set(x, h + 1, z, threshold >= decorator.getTopThreshold() ?
decorator.getBlockDataForTop(biome, getRng(), realX, h, realZ, getData()) :
decorator.getBlockData100(biome, getRng(), realX, h, realZ, getData()));
decorator.getBlockDataForTop(biome, rng, realX, h, realZ, getData()) :
decorator.getBlockData100(biome, rng, realX, h, realZ, getData()));
}
}
}

View File

@@ -19,7 +19,6 @@
package com.volmit.iris.engine.decorator;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.InferredType;
import com.volmit.iris.engine.object.IrisBiome;
@@ -28,11 +27,11 @@ import com.volmit.iris.engine.object.IrisDecorator;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.block.data.type.PointedDripstone;
public class IrisSurfaceDecorator extends IrisEngineDecorator {
@@ -48,7 +47,8 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
}
BlockData bd, bdx;
IrisDecorator decorator = getDecorator(biome, realX, realZ);
RNG rng = getRNG(realX, realZ);
IrisDecorator decorator = getDecorator(rng, biome, realX, realZ);
bdx = data.get(x, height, z);
boolean underwater = height < getDimension().getFluidHeight();
@@ -59,7 +59,7 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
}
if (!decorator.isStacking()) {
bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
bd = decorator.getBlockData100(biome, rng, realX, height, realZ, getData());
if (!underwater) {
if (!canGoOn(bd, bdx) && (!decorator.isForcePlace() && decorator.getForceBlock() == null)) {
@@ -68,12 +68,12 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
}
if (decorator.getForceBlock() != null) {
data.set(x, height, z, fixFaces(decorator.getForceBlock().getBlockData(getData()), x, height, z));
data.set(x, height, z, fixFaces(decorator.getForceBlock().getBlockData(getData()), data, x, z, realX, height, realZ));
} else if (!decorator.isForcePlace()) {
if (decorator.getWhitelist() != null && decorator.getWhitelist().stream().noneMatch(d -> d.getBlockData(getData()).equals(bdx))) {
return;
}
if (decorator.getBlacklist() != null && decorator.getWhitelist().stream().anyMatch(d -> d.getBlockData(getData()).equals(bdx))) {
if (decorator.getBlacklist() != null && decorator.getBlacklist().stream().anyMatch(d -> d.getBlockData(getData()).equals(bdx))) {
return;
}
}
@@ -91,14 +91,14 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
}
if (B.isAir(data.get(x, height + 1, z))) {
data.set(x, height + 1, z, fixFaces(bd, x, height + 1, z));
data.set(x, height + 1, z, fixFaces(bd, data, x, z, realX, height + 1, realZ));
}
} else {
if (height < getDimension().getFluidHeight()) {
max = getDimension().getFluidHeight();
}
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
int stack = decorator.getHeight(rng, realX, realZ, getData());
if (decorator.isScaleStack()) {
stack = Math.min((int) Math.ceil((double) max * ((double) stack / 100)), decorator.getAbsoluteMaxStack());
@@ -107,7 +107,7 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
}
if (stack == 1) {
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
data.set(x, height, z, decorator.getBlockDataForTop(biome, rng, realX, height, realZ, getData()));
return;
}
@@ -115,8 +115,8 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
int h = height + i;
double threshold = ((double) i) / (stack - 1);
bd = threshold >= decorator.getTopThreshold() ?
decorator.getBlockDataForTop(biome, getRng(), realX, h, realZ, getData()) :
decorator.getBlockData100(biome, getRng(), realX, h, realZ, getData());
decorator.getBlockDataForTop(biome, rng, realX, h, realZ, getData()) :
decorator.getBlockData100(biome, rng, realX, h, realZ, getData());
if (bd == null) {
break;
@@ -158,24 +158,4 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
}
}
}
private BlockData fixFaces(BlockData b, int x, int y, int z) {
if (B.isVineBlock(b)) {
MultipleFacing data = (MultipleFacing) b.clone();
boolean found = false;
for (BlockFace f : BlockFace.values()) {
if (!f.isCartesian())
continue;
Material m = getEngine().getMantle().get(x + f.getModX(), y + f.getModY(), z + f.getModZ()).getMaterial();
if (m.isSolid()) {
found = true;
data.setFace(f, m.isSolid());
}
}
if (!found)
data.setFace(BlockFace.UP, true);
return data;
}
return b;
}
}

View File

@@ -20,6 +20,7 @@ package com.volmit.iris.engine.framework;
import com.volmit.iris.Iris;
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.Renderer;
import com.volmit.iris.core.link.Identifier;
@@ -27,6 +28,7 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.ExternalDataSVC;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.data.cache.Cache;
@@ -40,7 +42,7 @@ import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.format.C;
@@ -57,15 +59,13 @@ import com.volmit.iris.util.matter.TileWrapper;
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.reflect.W;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import com.volmit.iris.util.stream.ProceduralStream;
import io.papermc.lib.PaperLib;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -76,10 +76,12 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.awt.*;
import java.awt.Color;
import java.util.Arrays;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -257,10 +259,8 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
if (B.isUpdatable(data)) {
getMantle().updateBlock(x, y, z);
}
if (data instanceof IrisBlockData d) {
getMantle().getMantle().set(x, y, z, d.getCustom());
} else {
getMantle().getMantle().remove(x, y, z, Identifier.class);
if (data instanceof IrisCustomData) {
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM, true);
}
}
@@ -273,33 +273,43 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
for (int z = -1; z <= 1; z++) {
if (c.getWorld().isChunkLoaded(c.getX() + x, c.getZ() + z))
continue;
Iris.debug("Chunk %s, %s [%s, %s] is not loaded".formatted(c.getX() + x, c.getZ() + z, x, z));
var msg = "Chunk %s, %s [%s, %s] is not loaded".formatted(c.getX() + x, c.getZ() + z, x, z);
if (W.getStack().getCallerClass().equals(ChunkUpdater.class)) Iris.warn(msg);
else Iris.debug(msg);
return;
}
}
if (!getMantle().getMantle().isLoaded(c)) {
Iris.debug("Mantle Chunk " + c.getX() + c.getX() + " is not loaded");
var mantle = getMantle().getMantle();
if (!mantle.isLoaded(c)) {
var msg = "Mantle Chunk " + c.getX() + c.getX() + " is not loaded";
if (W.getStack().getCallerClass().equals(ChunkUpdater.class)) Iris.warn(msg);
else Iris.debug(msg);
return;
}
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.TILE, () -> J.s(() -> {
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, v) -> {
var chunk = mantle.getChunk(c);
if (chunk.isFlagged(MantleFlag.ETCHED)) return;
chunk.flag(MantleFlag.ETCHED, true);
Semaphore semaphore = new Semaphore(3);
chunk.raiseFlag(MantleFlag.TILE, run(semaphore, () -> J.s(() -> {
mantle.iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, v) -> {
int betterY = y + getWorld().minHeight();
if (!TileData.setTileState(c.getBlock(x, betterY, z), v.getData()))
Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), v.getData().getMaterial().name());
});
}));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.CUSTOM, () -> J.s(() -> {
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> {
})));
chunk.raiseFlag(MantleFlag.CUSTOM, run(semaphore, () -> J.s(() -> {
mantle.iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> {
Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v);
});
}));
})));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.UPDATE, () -> J.s(() -> {
chunk.raiseFlag(MantleFlag.UPDATE, run(semaphore, () -> J.s(() -> {
PrecisionStopwatch p = PrecisionStopwatch.start();
KMap<Long, Integer> updates = new KMap<>();
RNG r = new RNG(Cache.key(c.getX(), c.getZ()));
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterCavern.class, (x, yf, z, v) -> {
mantle.iterateChunk(c.getX(), c.getZ(), MatterCavern.class, (x, yf, z, v) -> {
int y = yf + getWorld().minHeight();
if (!B.isFluid(c.getBlock(x & 15, y, z & 15).getBlockData())) {
return;
@@ -329,7 +339,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
});
updates.forEach((k, v) -> update(Cache.keyX(k), v, Cache.keyZ(k), c, r));
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterUpdate.class, (x, yf, z, v) -> {
mantle.iterateChunk(c.getX(), c.getZ(), MatterUpdate.class, (x, yf, z, v) -> {
int y = yf + getWorld().minHeight();
if (v != null && v.isUpdate()) {
int vx = x & 15;
@@ -340,9 +350,25 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
}
}
});
getMantle().getMantle().deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class);
mantle.deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class);
getMetrics().getUpdates().put(p.getMilliseconds());
}, RNG.r.i(0, 20)));
}, RNG.r.i(0, 20))));
try {
semaphore.acquire(3);
} catch (InterruptedException ignored) {}
}
private static Runnable run(Semaphore semaphore, Runnable runnable) {
return () -> {
if (!semaphore.tryAcquire())
return;
try {
runnable.run();
} finally {
semaphore.release();
}
};
}
@BlockCoordinates
@@ -388,7 +414,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
if (tables.isEmpty())
return;
InventoryHolder m = (InventoryHolder) block.getState();
addItems(false, m.getInventory(), rx, tables, slot, x, y, z, 15);
addItems(false, m.getInventory(), rx, tables, slot, c.getWorld(), x, y, z, 15);
} catch (Throwable e) {
Iris.reportError(e);
@@ -441,7 +467,10 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
}
@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)) {
list.clear();
}
@@ -476,10 +505,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
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();
injectTables(tables, getDimension().getLoot());
injectTables(tables, region.getLoot());
injectTables(tables, biomeSurface.getLoot());
injectTables(tables, biomeUnder.getLoot());
boolean fallback = tables.isEmpty();
injectTables(tables, getDimension().getLoot(), fallback);
injectTables(tables, region.getLoot(), fallback);
injectTables(tables, biomeSurface.getLoot(), fallback);
injectTables(tables, biomeUnder.getLoot(), fallback);
if (tables.isNotEmpty()) {
int target = (int) Math.round(tables.size() * multiplier);
@@ -497,16 +527,16 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
}
@Override
default void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, 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<>();
int b = 4;
for (IrisLootTable i : tables) {
if (i == null)
continue;
b++;
items.addAll(i.getLoot(debug, rng, slot, 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()) {
PaperLib.getChunkAtAsync(getWorld().realWorld(), x >> 4, z >> 4).thenAccept((c) -> {
@@ -580,6 +610,8 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
int getGenerated();
CompletableFuture<Long> getHash32();
default <T> IrisPosition lookForStreamResult(T find, ProceduralStream<T> stream, Function2<T, T, Boolean> matcher, long timeout) {
AtomicInteger checked = new AtomicInteger();
AtomicLong time = new AtomicLong(M.ms());

View File

@@ -1,32 +0,0 @@
package com.volmit.iris.engine.framework;
import com.volmit.iris.engine.object.InventorySlotType;
import com.volmit.iris.engine.object.IrisLootTable;
import com.volmit.iris.util.collection.KList;
import lombok.Getter;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@Getter
public class IrisLootEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final Engine engine;
private final Block block;
private final InventorySlotType slot;
private final KList<IrisLootTable> tables;
public IrisLootEvent(Engine engine, Block block, InventorySlotType slot, KList<IrisLootTable> tables) {
this.engine = engine;
this.block = block;
this.slot = slot;
this.tables = tables;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,8 +1,10 @@
package com.volmit.iris.engine.framework;
import com.volmit.iris.core.loader.IrisData;
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 fancyName();
}

View File

@@ -23,15 +23,16 @@ import com.volmit.iris.engine.object.IrisLootReference;
import com.volmit.iris.engine.object.IrisLootTable;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.RNG;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.inventory.Inventory;
public interface LootProvider {
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);
void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, int x, int y, int z, int mgf);
void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, World world, int x, int y, int z, int mgf);
}

View File

@@ -5,7 +5,7 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.data.cache.Cache;
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.object.IObjectPlacer;
import com.volmit.iris.engine.object.InventorySlotType;
@@ -13,6 +13,7 @@ import com.volmit.iris.engine.object.IrisLootTable;
import com.volmit.iris.engine.object.TileData;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.math.RNG;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -20,8 +21,6 @@ import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.InventoryHolder;
@@ -74,13 +73,17 @@ public class WorldObjectPlacer implements IObjectPlacer {
if (tables.isEmpty())
return;
InventoryHolder m = (InventoryHolder) block.getState();
engine.addItems(false, m.getInventory(), rx, tables, slot, x, y, z, 15);
engine.addItems(false, m.getInventory(), rx, tables, slot, world, x, y, z, 15);
} catch (Throwable e) {
Iris.reportError(e);
}
}
block.setBlockData(d);
if (d instanceof IrisCustomData data) {
block.setBlockData(data.getBase());
Iris.warn("Tried to place custom block at " + x + ", " + y + ", " + z + " which is not supported!");
} else block.setBlockData(d);
}
@Override

View File

@@ -25,7 +25,6 @@ import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
@@ -50,16 +49,18 @@ public class PlannedStructure {
private IrisPosition position;
private IrisData data;
private RNG rng;
private boolean forcePlace;
private boolean verbose;
private boolean terminating;
public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng) {
public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng, boolean forcePlace) {
terminating = false;
verbose = true;
this.pieces = new KList<>();
this.structure = structure;
this.position = position;
this.rng = rng;
this.forcePlace = forcePlace || structure.isForcePlace();
this.data = structure.getLoader();
generateStartPiece();
@@ -108,6 +109,9 @@ public class PlannedStructure {
} else {
options.setMode(i.getPiece().getPlaceMode());
}
if (forcePlace) {
options.setForcePlace(true);
}
IrisObject v = i.getObject();
int sx = (v.getW() / 2);
@@ -150,9 +154,6 @@ public class PlannedStructure {
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
e.set(b.getX(), b.getY(), b.getZ(), container);
if (data instanceof IrisBlockData d) {
e.set(b.getX(), b.getY(), b.getZ(), d.getCustom());
}
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
}

View File

@@ -20,10 +20,10 @@ package com.volmit.iris.engine.mantle;
import com.volmit.iris.core.IrisSettings;
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.framework.Engine;
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.MantleObjectComponent;
import com.volmit.iris.engine.object.IObjectPlacer;
@@ -34,6 +34,7 @@ import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.hunk.Hunk;
@@ -44,7 +45,6 @@ import com.volmit.iris.util.matter.*;
import com.volmit.iris.util.matter.slices.UpdateMatter;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import java.util.concurrent.TimeUnit;
@@ -59,7 +59,9 @@ public interface EngineMantle extends IObjectPlacer {
int getRadius();
KList<MantleComponent> getComponents();
int getRealRadius();
KList<Pair<KList<MantleComponent>, Integer>> getComponents();
void registerComponent(MantleComponent c);
@@ -103,7 +105,10 @@ public interface EngineMantle extends IObjectPlacer {
@Override
default void set(int x, int y, int z, BlockData d) {
getMantle().set(x, y, z, d == null ? AIR : d);
if (d instanceof IrisCustomData data) {
getMantle().set(x, y, z, data.getBase());
getMantle().set(x, y, z, data.getCustom());
} else getMantle().set(x, y, z, d == null ? AIR : d);
}
@Override
@@ -187,39 +192,37 @@ public interface EngineMantle extends IObjectPlacer {
return getEngine().burst();
}
default int getRealRadius() {
return (int) Math.ceil(getRadius() / 2D);
}
@ChunkCoordinates
default void generateMatter(int x, int z, boolean multicore, ChunkContext context) {
synchronized (this) {
if (!getEngine().getDimension().isUseMantle()) {
return;
}
if (!getEngine().getDimension().isUseMantle()) {
return;
}
int s = getRealRadius();
BurstExecutor burst = burst().burst(multicore);
MantleWriter writer = getMantle().write(this, x, z, s * 2);
for (int i = -s; i <= s; i++) {
for (int j = -s; j <= s; j++) {
int xx = i + x;
int zz = j + z;
burst.queue(() -> {
IrisContext.touch(getEngine().getContext());
getMantle().raiseFlag(xx, zz, MantleFlag.PLANNED, () -> {
MantleChunk mc = getMantle().getChunk(xx, zz);
try (MantleWriter writer = getMantle().write(this, x, z, getRadius() * 2)) {
var iterator = getComponents().iterator();
while (iterator.hasNext()) {
var pair = iterator.next();
int radius = pair.getB();
boolean last = !iterator.hasNext();
BurstExecutor burst = burst().burst(radius * 2 + 1);
burst.setMulticore(multicore);
for (MantleComponent k : getComponents()) {
generateMantleComponent(writer, xx, zz, k, mc, context);
}
for (int i = -radius; i <= radius; i++) {
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 {
private final EngineMantle engineMantle;
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.MantleFlag;
import com.volmit.iris.util.parallel.BurstExecutor;
import org.jetbrains.annotations.NotNull;
public interface MantleComponent {
default int getRadius() {
return getEngineMantle().getRealRadius();
}
public interface MantleComponent extends Comparable<MantleComponent> {
int getPriority();
int getRadius();
default IrisData getData() {
return getEngineMantle().getData();
@@ -62,4 +63,9 @@ public interface MantleComponent {
@ChunkCoordinates
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

@@ -29,13 +29,13 @@ import com.volmit.iris.engine.object.IrisPosition;
import com.volmit.iris.engine.object.TileData;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.function.Function3;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.mantle.MantleChunk;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.Matter;
import lombok.Data;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.Vector;
@@ -44,7 +44,7 @@ import java.util.List;
import java.util.Set;
@Data
public class MantleWriter implements IObjectPlacer {
public class MantleWriter implements IObjectPlacer, AutoCloseable {
private final EngineMantle engineMantle;
private final Mantle mantle;
private final KMap<Long, MantleChunk> cachedChunks;
@@ -62,7 +62,7 @@ public class MantleWriter implements IObjectPlacer {
for (int i = -radius; i <= radius; i++) {
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());
}
}
}
@@ -167,7 +167,10 @@ public class MantleWriter implements IObjectPlacer {
@Override
public void set(int x, int y, int z, BlockData d) {
setData(x, y, z, d);
if (d instanceof IrisCustomData data) {
setData(x, y, z, data.getBase());
setData(x, y, z, data.getCustom());
} else setData(x, y, z, d);
}
@Override
@@ -633,4 +636,12 @@ public class MantleWriter implements IObjectPlacer {
return cx >= this.x - radius && cx <= this.x + 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.mantle.MantleFlag;
import com.volmit.iris.util.math.RNG;
import lombok.Getter;
@Getter
public class MantleCarvingComponent extends IrisMantleComponent {
private final int radius = computeRadius();
public MantleCarvingComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.CARVED);
super(engineMantle, MantleFlag.CARVED, 0);
}
@Override
@@ -56,4 +60,21 @@ public class MantleCarvingComponent extends IrisMantleComponent {
private void carve(IrisCarving carving, MantleWriter writer, RNG rng, int cx, int cz) {
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.mantle.MantleFlag;
import com.volmit.iris.util.math.RNG;
import lombok.Getter;
@Getter
public class MantleFluidBodyComponent extends IrisMantleComponent {
private final int radius = computeRadius();
public MantleFluidBodyComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.FLUID_BODIES);
super(engineMantle, MantleFlag.FLUID_BODIES, 0);
}
@Override
@@ -56,4 +60,20 @@ public class MantleFluidBodyComponent extends IrisMantleComponent {
private void generate(IrisFluidBodies bodies, MantleWriter writer, RNG rng, int cx, int cz) {
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.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.noise.CNG;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class MantleJigsawComponent extends IrisMantleComponent {
@Getter
private final int radius = computeRadius();
private final CNG cng;
public MantleJigsawComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.JIGSAW);
super(engineMantle, MantleFlag.JIGSAW, 1);
cng = NoiseStyle.STATIC.create(new RNG(jigsaw()));
}
@@ -66,7 +69,7 @@ public class MantleJigsawComponent extends IrisMantleComponent {
for (Position2 pos : poss) {
if (x == pos.getX() >> 4 && z == pos.getZ() >> 4) {
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(getDimension().getStronghold());
place(writer, pos.toIris(), structure, new RNG(seed));
place(writer, pos.toIris(), structure, new RNG(seed), true);
return;
}
}
@@ -87,12 +90,14 @@ public class MantleJigsawComponent extends IrisMantleComponent {
private boolean placeStructures(MantleWriter writer, long seed, int x, int z, KList<IrisJigsawStructurePlacement> structures,
KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
IrisJigsawStructurePlacement i = pick(structures, seed, x, z);
if (i == null || checkMinDistances(i.collectMinDistances(), x, z, cachedRegions, cache, distanceCache))
return false;
try {
if (i == null || checkMinDistances(i.collectMinDistances(), x, z, cachedRegions, cache, distanceCache))
return false;
} catch (Throwable ignored) {}
RNG rng = new RNG(seed);
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
return place(writer, position, structure, rng);
return place(writer, position, structure, rng, false);
}
@ChunkCoordinates
@@ -156,16 +161,41 @@ public class MantleJigsawComponent extends IrisMantleComponent {
@ChunkCoordinates
private IrisJigsawStructurePlacement pick(List<IrisJigsawStructurePlacement> structures, long seed, int x, int z) {
return IRare.pick(structures.stream()
.filter(p -> p.shouldPlace(getDimension().getJigsawStructureDivisor(), jigsaw(), x, z))
.filter(p -> p.shouldPlace(getData(), getDimension().getJigsawStructureDivisor(), jigsaw(), x, z))
.toList(), new RNG(seed).nextDouble());
}
@BlockCoordinates
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
return new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng, boolean forcePlace) {
return new PlannedStructure(structure, position, rng, forcePlace).place(writer, getMantle(), writer.getEngine());
}
private long jigsaw() {
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

@@ -24,23 +24,34 @@ 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.*;
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.data.B;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.documentation.BlockCoordinates;
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.math.RNG;
import com.volmit.iris.util.matter.MatterStructurePOI;
import com.volmit.iris.util.noise.CNG;
import com.volmit.iris.util.noise.NoiseType;
import com.volmit.iris.util.parallel.BurstExecutor;
import lombok.Getter;
import org.bukkit.util.BlockVector;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@Getter
public class MantleObjectComponent extends IrisMantleComponent {
private final int radius = computeRadius();
public MantleObjectComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.OBJECT);
super(engineMantle, MantleFlag.OBJECT, 1);
}
@Override
@@ -104,9 +115,6 @@ public class MantleObjectComponent extends IrisMantleComponent {
if (objectPlacement.isDolphinTarget() && objectPlacement.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, getData());
}
}
@@ -146,4 +154,112 @@ public class MantleObjectComponent extends IrisMantleComponent {
return v;
}
private int computeRadius() {
var dimension = getDimension();
AtomicInteger xg = new AtomicInteger();
AtomicInteger zg = new AtomicInteger();
KSet<String> objects = new KSet<>();
KMap<IrisObjectScale, KList<String>> scalars = new KMap<>();
for (var region : dimension.getAllRegions(this::getData)) {
for (var j : region.getObjects()) {
if (j.getScale().canScaleBeyond()) {
scalars.put(j.getScale(), j.getPlace());
} else {
objects.addAll(j.getPlace());
}
}
}
for (var biome : dimension.getAllBiomes(this::getData)) {
for (var j : biome.getObjects()) {
if (j.getScale().canScaleBeyond()) {
scalars.put(j.getScale(), j.getPlace());
} else {
objects.addAll(j.getPlace());
}
}
}
BurstExecutor e = getEngineMantle().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();
}
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
Iris.warn("Object " + i + " has a large size (" + bv + ") and may increase memory usage!");
}
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();
}
if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) {
Iris.warn("Object " + j + " has a large size (" + bv + ") and may increase memory usage! (Object scaled up to " + Form.pc(ms, 2) + ")");
}
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();
return Math.max(xg.get(), zg.get());
}
}

View File

@@ -25,10 +25,7 @@ import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineMode;
import com.volmit.iris.engine.framework.EngineStage;
import com.volmit.iris.engine.framework.IrisEngineMode;
import com.volmit.iris.engine.modifier.IrisCarveModifier;
import com.volmit.iris.engine.modifier.IrisDepositModifier;
import com.volmit.iris.engine.modifier.IrisPerfectionModifier;
import com.volmit.iris.engine.modifier.IrisPostModifier;
import com.volmit.iris.engine.modifier.*;
import org.bukkit.block.data.BlockData;
public class ModeOverworld extends IrisEngineMode implements EngineMode {
@@ -41,6 +38,7 @@ public class ModeOverworld extends IrisEngineMode implements EngineMode {
var post = new IrisPostModifier(getEngine());
var deposit = new IrisDepositModifier(getEngine());
var perfection = new IrisPerfectionModifier(getEngine());
var custom = new IrisCustomModifier(getEngine());
EngineStage sBiome = (x, z, k, p, m, c) -> biome.actuate(x, z, p, m, c);
EngineStage sGenMatter = (x, z, k, p, m, c) -> generateMatter(x >> 4, z >> 4, m, c);
EngineStage sTerrain = (x, z, k, p, m, c) -> terrain.actuate(x, z, k, m, c);
@@ -50,6 +48,7 @@ public class ModeOverworld extends IrisEngineMode implements EngineMode {
EngineStage sPost = (x, z, k, p, m, c) -> post.modify(x, z, k, m, c);
EngineStage sInsertMatter = (x, z, K, p, m, c) -> getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, K, m);
EngineStage sPerfection = (x, z, k, p, m, c) -> perfection.modify(x, z, k, m, c);
EngineStage sCustom = (x, z, k, p, m, c) -> custom.modify(x, z, k, m, c);
registerStage(burst(
sGenMatter,
@@ -65,6 +64,6 @@ public class ModeOverworld extends IrisEngineMode implements EngineMode {
sDecorant
));
registerStage(sPerfection);
registerStage(sCustom);
}
}

View File

@@ -57,7 +57,7 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore, ChunkContext context) {
PrecisionStopwatch p = PrecisionStopwatch.start();
Mantle mantle = getEngine().getMantle().getMantle();
MantleChunk mc = getEngine().getMantle().getMantle().getChunk(x, z);
MantleChunk mc = getEngine().getMantle().getMantle().getChunk(x, z).use();
KMap<Long, KList<Integer>> positions = new KMap<>();
KMap<IrisPosition, MatterCavern> walls = new KMap<>();
Consumer4<Integer, Integer, Integer, MatterCavern> iterator = (xx, yy, zz, c) -> {
@@ -166,6 +166,7 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
});
getEngine().getMetrics().getDeposit().put(p.getMilliseconds());
mc.release();
}
private void processZone(Hunk<BlockData> output, MantleChunk mc, Mantle mantle, CaveZone zone, int rx, int rz, int xx, int zz) {
@@ -211,14 +212,6 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
biome.setInferredType(InferredType.CAVE);
for (IrisDecorator i : biome.getDecorators()) {
if (i.getPartOf().equals(IrisDecorationPart.NONE) && B.isSolid(output.get(rx, zone.getFloor() - 1, rz))) {
decorant.getSurfaceDecorator().decorate(rx, rz, xx, xx, xx, zz, zz, zz, output, biome, zone.getFloor() - 1, zone.airThickness());
} else if (i.getPartOf().equals(IrisDecorationPart.CEILING) && B.isSolid(output.get(rx, zone.getCeiling() + 1, rz))) {
decorant.getCeilingDecorator().decorate(rx, rz, xx, xx, xx, zz, zz, zz, output, biome, zone.getCeiling(), zone.airThickness());
}
}
KList<BlockData> blocks = biome.generateLayers(getDimension(), xx, zz, rng, 3, zone.floor, getData(), getComplex());
for (int i = 0; i < zone.floor - 1; i++) {
@@ -260,6 +253,14 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
output.set(rx, zone.ceiling + i + 1, rz, b);
}
}
for (IrisDecorator i : biome.getDecorators()) {
if (i.getPartOf().equals(IrisDecorationPart.NONE) && B.isSolid(output.get(rx, zone.getFloor() - 1, rz))) {
decorant.getSurfaceDecorator().decorate(rx, rz, xx, xx, xx, zz, zz, zz, output, biome, zone.getFloor() - 1, zone.airThickness());
} else if (i.getPartOf().equals(IrisDecorationPart.CEILING) && B.isSolid(output.get(rx, zone.getCeiling() + 1, rz))) {
decorant.getCeilingDecorator().decorate(rx, rz, xx, xx, xx, zz, zz, zz, output, biome, zone.getCeiling(), zone.airThickness());
}
}
}
@Data

View File

@@ -0,0 +1,43 @@
package com.volmit.iris.engine.modifier;
import com.volmit.iris.core.link.Identifier;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import org.bukkit.block.data.BlockData;
public class IrisCustomModifier extends EngineAssignedModifier<BlockData> {
public IrisCustomModifier(Engine engine) {
super(engine, "Custom");
}
@Override
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore, ChunkContext context) {
var mc = getEngine().getMantle().getMantle().getChunk(x >> 4, z >> 4);
if (!mc.isFlagged(MantleFlag.CUSTOM_ACTIVE)) return;
mc.use();
BurstExecutor burst = MultiBurst.burst.burst(output.getHeight());
burst.setMulticore(multicore);
for (int y = 0; y < output.getHeight(); y++) {
int finalY = y;
burst.queue(() -> {
for (int rX = 0; rX < output.getWidth(); rX++) {
for (int rZ = 0; rZ < output.getDepth(); rZ++) {
BlockData b = output.get(rX, finalY, rZ);
if (!(b instanceof IrisCustomData d)) continue;
mc.getOrCreate(finalY >> 4)
.slice(Identifier.class)
.set(rX, finalY & 15, rZ, d.getCustom());
output.set(rX, finalY, rZ, d.getBase());
}
}
});
}
burst.complete();
mc.release();
}
}

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.EngineAssignedModifier;
import com.volmit.iris.engine.object.IrisBiome;
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.engine.object.*;
import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.HeightMap;
@@ -45,30 +42,26 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore, ChunkContext context) {
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());
}
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z, boolean multicore, ChunkContext context) {
RNG ro = rx.nextParallelRNG(x * x).nextParallelRNG(z * z);
public void generateDeposits(Hunk<BlockData> terrain, int x, int z, boolean multicore, ChunkContext context) {
IrisRegion region = context.getRegion().get(7, 7);
IrisBiome biome = context.getBiome().get(7, 7);
BurstExecutor burst = burst().burst(multicore);
long seed = x * 341873128712L + z * 132897987541L;
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 (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) {
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 : biome.getDeposits()) {
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) {
burst.queue(() -> generate(k, terrain, ro, x, z, false, context));
}
burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(seed), x, z, false, context));
}
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) {
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());
int af = (int) Math.floor(clump.getW() / 2D);
int bf = (int) Math.floor(16D - (clump.getW() / 2D));
int dim = clump.getW();
int min = dim / 2;
int max = (int) (16D - dim / 2D);
if (af > bf || af < 0 || bf > 15) {
af = 6;
bf = 9;
if (min > max || min < 0 || max > 15) {
min = 6;
max = 9;
}
af = Math.max(af - 1, 0);
int x = rng.i(af, bf);
int z = rng.i(af, bf);
int x = rng.i(min, max + 1);
int z = rng.i(min, max + 1);
int height = (he != null ? he.getHeight((cx << 4) + x, (cz << 4) + z) : (int) (Math.round(
context.getHeight().get(x, z)
))) - 7;
if (height <= 0) {
return;
}
if (height <= 0)
continue;
int i = Math.max(0, k.getMinHeight());
int minY = Math.max(0, k.getMinHeight());
// 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) {
return;
}
if (minY >= maxY)
continue;
int h = rng.i(i, a);
int y = rng.i(minY, maxY + 1);
if (h > k.getMaxHeight() || h < k.getMinHeight() || h > height - 2) {
return;
}
if (y > k.getMaxHeight() || y < k.getMinHeight() || y > height - 2)
continue;
for (BlockVector j : clump.getBlocks().keySet()) {
int nx = j.getBlockX() + x;
int ny = j.getBlockY() + h;
int ny = j.getBlockY() + y;
int nz = j.getBlockZ() + z;
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

@@ -200,7 +200,7 @@ public class IrisBiome extends IrisRegistrant implements IRare {
KMap<String, Integer> l = new KMap<>();
for (IrisBiomeGeneratorLink i : getGenerators()) {
l.put(i.getGenerator(), i.getMax(engine));
l.put(i.getGenerator(), i.getMax());
}
@@ -216,7 +216,7 @@ public class IrisBiome extends IrisRegistrant implements IRare {
KMap<String, Integer> l = new KMap<>();
for (IrisBiomeGeneratorLink i : getGenerators()) {
l.put(i.getGenerator(), i.getMin(engine));
l.put(i.getGenerator(), i.getMin());
}
return l;
@@ -457,7 +457,7 @@ public class IrisBiome extends IrisRegistrant implements IRare {
int maxHeight = 0;
for (IrisBiomeGeneratorLink i : getGenerators()) {
maxHeight += i.getMax(engine);
maxHeight += i.getMax();
}
return maxHeight;
@@ -470,7 +470,7 @@ public class IrisBiome extends IrisRegistrant implements IRare {
int maxHeight = 0;
for (IrisBiomeGeneratorLink i : getGenerators()) {
maxHeight += i.getMax(engine);
maxHeight += i.getMax();
}
int gg = 0;

View File

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

View File

@@ -18,9 +18,7 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.interpolation.IrisInterpolation;
@@ -39,18 +37,16 @@ public class IrisBiomeGeneratorLink {
@RegistryListResource(IrisGenerator.class)
@Desc("The generator id")
private String generator = "default";
@DependsOn({ "min", "max" })
@DependsOn({"min", "max"})
@Required
@MinNumber(-2032) // TODO: WARNING HEIGHT
@MaxNumber(2032) // TODO: WARNING HEIGHT
@Desc("The min block value (value + fluidHeight)")
@Getter(AccessLevel.NONE)
private int min = 0;
@DependsOn({ "min", "max" })
@DependsOn({"min", "max"})
@Required
@MinNumber(-2032) // TODO: WARNING HEIGHT
@MaxNumber(2032) // TODO: WARNING HEIGHT
@Getter(AccessLevel.NONE)
@Desc("The max block value (value + fluidHeight)")
private int max = 0;
@@ -66,70 +62,6 @@ public class IrisBiomeGeneratorLink {
});
}
private int[] getBiomeGeneratorsRaw(Engine engine) {
int max = engine.getDimension().getMinHeight();
int min = engine.getDimension().getMaxHeight();
for (IrisBiome biome : engine.getAllBiomes()) {
for (IrisBiomeGeneratorLink i : biome.getGenerators()) {
int biomeRawMax = i.getMaxRaw();
int biomeRawMin = i.getMinRaw();
if (max < biomeRawMax)
max = biomeRawMax;
if (min > biomeRawMin)
min = biomeRawMin;
}
}
return new int[] { min, max };
}
private int calculateHeight(Engine engine, int option) {
int dmx = engine.getDimension().getMaxHeight();
int dmn = engine.getDimension().getMinHeight();
int[] heights = getBiomeGeneratorsRaw(engine);
int gmx = heights[1];
int gmn = heights[0];
int mx = getMaxRaw();
int mn = getMinRaw();
if (engine.getDimension().isSmartVanillaHeight()) {
if (mx > 0)
mx = Math.min((int) (((float) mx / (float) gmx) * 300.0f), 300);
if (mx < 0)
mx = Math.min((int) (((float) mx / (float) gmn) * 300.0f), 56);
if (mn > 0)
mn = Math.min((int) (((float) mn / (float) gmx) * 300.0f), 300);
if (mn < 0)
mn = Math.min((int) (((float) mn / (float) gmn) * 300.0f), 56);
}
if (option == 1) {
return mx;
}
if (option == 0) {
return mn;
}
Iris.error("Fatal Generator error!");
return 0;
}
public int getMax(Engine engine) {
return calculateHeight(engine, 1);
}
public int getMin(Engine engine) {
return calculateHeight(engine, 0);
}
private int getMaxRaw() {
return max;
}
private int getMinRaw() {
return min;
}
public double getHeight(DataProvider xg, double x, double z, long seed) {
double g = getCachedGenerator(xg).getHeight(x, z, seed);
g = g < 0 ? 0 : g;

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.object.annotations.*;
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 lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BlockVector;
@Snippet("deposit")
@Accessors(chain = true)
@@ -69,6 +70,14 @@ public class IrisDepositGenerator {
@MaxNumber(2048)
@Desc("The minimum amount of clumps per chunk")
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
@ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The palette of blocks to be used in this deposit generator")
@@ -90,35 +99,62 @@ public class IrisDepositGenerator {
return objectsf;
});
return objects.get(rng.i(0, objects.size() - 1));
return objects.get(rng.i(0, objects.size()));
}
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) {
int s = rngv.i(minSize, maxSize);
int dim = Math.min(11, (int) Math.round(Math.pow(maxSize, 1D / 3D)));
int w = dim / 2;
int s = rngv.i(minSize, maxSize + 1);
if (s == 1) {
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);
if (s == 1) {
o.getBlocks().put(o.getCenter(), nextBlock(rngv, rdata));
} else {
while (s > 0) {
s--;
BlockVector ang = new BlockVector(rngv.i(-w, w), rngv.i(-w, w), rngv.i(-w, w));
BlockVector pos = o.getCenter().clone().add(ang).toBlockVector();
o.getBlocks().put(pos, nextBlock(rngv, rdata));
int volume = dim * dim * dim;
if (s >= volume) {
int x = 0, y = 0, z = 0;
while (z < dim) {
o.setUnsigned(x++, y, z, 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;
}
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) {

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
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.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*;
@@ -233,8 +234,6 @@ public class IrisDimension extends IrisRegistrant {
private IrisRange dimensionHeightEnd = new IrisRange(-64, 320);
@Desc("Define the min and max Y bounds of this dimension. Please keep in mind that Iris internally generates from 0 to (max - min). \n\nFor example at -64 to 320, Iris is internally generating to 0 to 384, then on outputting chunks, it shifts it down by the min height (64 blocks). The default is -64 to 320. \n\nThe fluid height is placed at (fluid height + min height). So a fluid height of 63 would actually show up in the world at 1.")
private IrisRange dimensionHeightNether = new IrisRange(-64, 320);
@Desc("Enable smart vanilla height")
private boolean smartVanillaHeight = false;
@RegistryListResource(IrisBiome.class)
@Desc("Keep this either undefined or empty. Setting any biome name into this will force iris to only generate the specified biome. Great for testing.")
private String focus = "";
@@ -487,10 +486,10 @@ public class IrisDimension extends IrisRegistrant {
{
"pack": {
"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) {
Iris.reportError(e);
e.printStackTrace();

View File

@@ -29,7 +29,6 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.plugin.Chunks;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
@@ -57,6 +56,8 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static com.volmit.iris.util.data.registry.Particles.ITEM;
@SuppressWarnings("ALL")
@Accessors(chain = true)
@NoArgsConstructor
@@ -66,7 +67,6 @@ import java.util.concurrent.atomic.AtomicReference;
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisEntity extends IrisRegistrant {
private static final Particle ITEM = E.getOrDefault(Particle.class, "ITEM_CRACK", "ITEM");
@Required
@Desc("The type of entity to spawn. To spawn a mythic mob, set this type to unknown and define mythic type.")
private EntityType type = EntityType.UNKNOWN;
@@ -271,7 +271,7 @@ public class IrisEntity extends IrisRegistrant {
for (String fi : getLoot().getTables()) {
IrisLootTable i = gen.getData().getLootLoader().load(fi);
items.addAll(i.getLoot(gen.isStudio(), rng.nextParallelRNG(345911), InventorySlotType.STORAGE, finalAt.getBlockX(), finalAt.getBlockY(), finalAt.getBlockZ()));
items.addAll(i.getLoot(gen.isStudio(), rng.nextParallelRNG(345911), InventorySlotType.STORAGE, finalAt.getWorld(), finalAt.getBlockX(), finalAt.getBlockY(), finalAt.getBlockZ()));
}
return items;

View File

@@ -24,6 +24,7 @@ import com.dfsek.paralithic.eval.parser.Scope;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.IrisExpressionFunction.FunctionContext;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.Required;
@@ -46,12 +47,14 @@ import lombok.experimental.Accessors;
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisExpression extends IrisRegistrant {
private static final Parser parser = new Parser();
@ArrayType(type = IrisExpressionLoad.class, min = 1)
@Desc("Variables to use in this expression")
private KList<IrisExpressionLoad> variables = new KList<>();
@ArrayType(type = IrisExpressionFunction.class, min = 1)
@Desc("Functions to use in this expression")
private KList<IrisExpressionFunction> functions = new KList<>();
@Required
@Desc("The expression. Inherited variables are x, y and z. Avoid using those variable names.")
private String expression;
@@ -62,6 +65,7 @@ public class IrisExpression extends IrisRegistrant {
private Expression expression() {
return expressionCache.aquire(() -> {
Scope scope = new Scope(); // Create variable scope. This scope can hold both constants and invocation variables.
Parser parser = new Parser();
try {
for (IrisExpressionLoad i : variables) {
@@ -76,6 +80,12 @@ public class IrisExpression extends IrisRegistrant {
Iris.error("Script Variable load error in " + getLoadFile().getPath());
}
for (IrisExpressionFunction f : functions) {
if (!f.isValid()) continue;
f.setData(getLoader());
parser.registerFunction(f.getName(), f);
}
try {
return parser.parse(getExpression(), scope);
} catch (Throwable e) {
@@ -103,7 +113,7 @@ public class IrisExpression extends IrisRegistrant {
g[m++] = z;
g[m] = -1;
return expression().evaluate(g);
return expression().evaluate(new FunctionContext(rng), g);
}
public double evaluate(RNG rng, double x, double y, double z) {
@@ -117,7 +127,7 @@ public class IrisExpression extends IrisRegistrant {
g[m++] = y;
g[m] = z;
return expression().evaluate(g);
return expression().evaluate(new FunctionContext(rng), g);
}
@Override

View File

@@ -0,0 +1,101 @@
package com.volmit.iris.engine.object;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.paralithic.node.Statefulness;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.annotations.Snippet;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.math.RNG;
import lombok.*;
import lombok.experimental.Accessors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Snippet("expression-function")
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Represents a function to use in your expression. Do not set the name to x, y, or z, also don't duplicate names.")
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisExpressionFunction implements DynamicFunction {
@Required
@Desc("The function to assign this value to. Do not set the name to x, y, or z")
private String name;
@Desc("If defined, this variable will use a generator style as it's value")
private IrisGeneratorStyle styleValue = null;
@Desc("If defined, iris will use an internal stream from the engine as it's value")
private IrisEngineStreamType engineStreamValue = null;
@MinNumber(2)
@Desc("Number of arguments for the function")
private int args = 2;
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private transient final KMap<FunctionContext, Provider> cache = new KMap<>();
private transient IrisData data;
public boolean isValid() {
return styleValue != null || engineStreamValue != null;
}
@Override
public int getArgNumber() {
if (engineStreamValue != null) return 2;
return Math.max(args, 2);
}
@NotNull
@Override
public Statefulness statefulness() {
return Statefulness.STATEFUL;
}
@Override
public double eval(double... doubles) {
return 0;
}
@Override
public double eval(@Nullable Context raw, double... args) {
return cache.computeIfAbsent((FunctionContext) raw, context -> {
assert context != null;
if (engineStreamValue != null) {
var stream = engineStreamValue.get(data.getEngine());
return d -> stream.get(d[0], d[1]);
}
if (styleValue != null) {
return styleValue.createNoCache(context.rng, data)::noise;
}
return d -> Double.NaN;
}).eval(args);
}
public record FunctionContext(@NonNull RNG rng) implements Context {
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
FunctionContext that = (FunctionContext) o;
return rng.getSeed() == that.rng.getSeed();
}
@Override
public int hashCode() {
return Long.hashCode(rng.getSeed());
}
}
@FunctionalInterface
private interface Provider {
double eval(double... args);
}
}

View File

@@ -23,12 +23,11 @@ import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.annotations.Snippet;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.noise.CNG;
import com.volmit.iris.util.stream.ProceduralStream;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.*;
import lombok.experimental.Accessors;
@Snippet("expression-load")
@@ -57,6 +56,9 @@ public class IrisExpressionLoad {
private transient AtomicCache<ProceduralStream<Double>> streamCache = new AtomicCache<>();
private transient AtomicCache<Double> valueCache = new AtomicCache<>();
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private transient final KMap<Long, CNG> styleCache = new KMap<>();
public double getValue(RNG rng, IrisData data, double x, double z) {
if (engineValue != null) {
@@ -68,7 +70,8 @@ public class IrisExpressionLoad {
}
if (styleValue != null) {
return styleValue.create(rng, data).noise(x, z);
return styleCache.computeIfAbsent(rng.getSeed(), k -> styleValue.createNoCache(new RNG(k), data))
.noise(x, z);
}
return staticValue;
@@ -84,7 +87,8 @@ public class IrisExpressionLoad {
}
if (styleValue != null) {
return styleValue.create(rng, data).noise(x, y, z);
return styleCache.computeIfAbsent(rng.getSeed(), k -> styleValue.createNoCache(new RNG(k), data))
.noise(x, y, z);
}
return staticValue;

View File

@@ -22,6 +22,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.engine.object.annotations.functions.StructureKeyFunction;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.plugin.VolmitSender;
@@ -73,6 +74,9 @@ public class IrisJigsawStructure extends IrisRegistrant {
@Desc("The minecraft key to use when creating treasure maps")
private String structureKey = null;
@Desc("Force Place the whole structure")
private boolean forcePlace = false;
private transient AtomicCache<Integer> maxDimension = new AtomicCache<>();
private void loadPool(String p, KList<String> pools, KList<String> pieces) {
@@ -135,13 +139,21 @@ public class IrisJigsawStructure extends IrisRegistrant {
loadPiece(i, pools, pieces);
}
if (pieces.isEmpty()) {
int max = 0;
for (String i : getPieces()) {
max = Math.max(max, getLoader().getJigsawPieceLoader().load(i).getMax2dDimension());
}
return max;
}
int avg = 0;
for (String i : pieces) {
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

@@ -19,13 +19,8 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MaxNumber;
import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.annotations.Snippet;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.documentation.ChunkCoordinates;
@@ -54,6 +49,7 @@ public class IrisJigsawStructurePlacement implements IRare {
private int rarity = 100;
@Required
@DependsOn({"spacing", "separation"})
@Desc("The salt to use when generating the structure (to differentiate structures)")
@MinNumber(Long.MIN_VALUE)
@MaxNumber(Long.MAX_VALUE)
@@ -61,16 +57,26 @@ public class IrisJigsawStructurePlacement implements IRare {
@Required
@MinNumber(0)
@DependsOn({"salt", "separation"})
@Desc("Average distance in chunks between two neighboring generation attempts")
private int spacing = -1;
@Required
@MinNumber(0)
@DependsOn({"salt", "spacing"})
@Desc("Minimum distance in chunks between two neighboring generation attempts\nThe maximum distance of two neighboring generation attempts is 2*spacing - separation")
private int separation = -1;
@Desc("The method used to spread the structure")
private SpreadType spreadType = SpreadType.TRIANGULAR;
private SpreadType spreadType = SpreadType.LINEAR;
@DependsOn({"spreadType"})
@Desc("The noise style to use when spreadType is set to 'NOISE'\nThis ignores the spacing and separation parameters")
private IrisGeneratorStyle style = new IrisGeneratorStyle();
@DependsOn({"spreadType", "style"})
@Desc("Threshold for noise style")
private double threshold = 0.5;
@ArrayType(type = IrisJigsawMinDistance.class)
@Desc("List of minimum distances to check for")
@@ -89,20 +95,29 @@ public class IrisJigsawStructurePlacement implements IRare {
}
private void calculateMissing(double divisor, long seed) {
seed = seed + hashCode();
if (salt != 0 && separation > 0 && spacing > 0)
return;
seed *= (long) structure.hashCode() * rarity;
if (salt == 0) {
salt = new RNG(seed).nextLong(Integer.MIN_VALUE, Integer.MAX_VALUE);
salt = new RNG(seed).l(Integer.MIN_VALUE, Integer.MAX_VALUE);
}
if (separation == -1 || spacing == -1) {
separation = (int) Math.round(rarity / divisor);
spacing = new RNG(seed).nextInt(separation, separation * 2);
spacing = new RNG(seed).i(separation, separation * 2);
}
}
@ChunkCoordinates
public boolean shouldPlace(double divisor, long seed, int x, int z) {
public boolean shouldPlace(IrisData data, double divisor, long seed, int x, int z) {
calculateMissing(divisor, seed);
if (spreadType != SpreadType.NOISE)
return shouldPlaceSpread(seed, x, z);
return style.create(new RNG(seed + salt), data).noise(x, z) > threshold;
}
private boolean shouldPlaceSpread(long seed, int x, int z) {
if (separation > spacing) {
separation = spacing;
Iris.warn("JigsawStructurePlacement: separation must be less than or equal to spacing");
@@ -123,7 +138,9 @@ public class IrisJigsawStructurePlacement implements IRare {
@Desc("Linear spread")
LINEAR(RNG::i),
@Desc("Triangular spread")
TRIANGULAR((rng, bound) -> (rng.i(bound) + rng.i(bound)) / 2);
TRIANGULAR((rng, bound) -> (rng.i(bound) + rng.i(bound)) / 2),
@Desc("Noise based spread\nThis ignores the spacing and separation parameters")
NOISE((rng, bound) -> 0);
private final SpreadMethod method;
SpreadType(SpreadMethod method) {

View File

@@ -27,5 +27,7 @@ public enum IrisLootMode {
@Desc("Clear all loot tables then add this table")
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

@@ -33,6 +33,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
@Accessors(chain = true)
@@ -67,7 +68,7 @@ public class IrisLootTable extends IrisRegistrant {
@ArrayType(min = 1, type = IrisLoot.class)
private KList<IrisLoot> loot = new KList<>();
public KList<ItemStack> getLoot(boolean debug, RNG rng, InventorySlotType slot, int x, int y, int z) {
public KList<ItemStack> getLoot(boolean debug, RNG rng, InventorySlotType slot, World world, int x, int y, int z) {
KList<ItemStack> lootf = new KList<>();
int m = 0;

View File

@@ -29,7 +29,7 @@ import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.data.IrisCustomData;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.interpolation.IrisInterpolation;
import com.volmit.iris.util.json.JSONObject;
@@ -53,8 +53,6 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.block.data.Waterlogged;
@@ -562,7 +560,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);
if (block == null) {
@@ -571,7 +569,7 @@ public class IrisObject extends IrisRegistrant {
} else {
BlockData data = block.getBlockData();
getBlocks().put(v, data);
TileData state = TileData.getTileState(block);
TileData state = TileData.getTileState(block, legacy);
if (state != null) {
Iris.debug("Saved State " + v);
getStates().put(v, state);
@@ -663,7 +661,18 @@ public class IrisObject extends IrisRegistrant {
yrand = yrand > 0 ? rng.i(0, yrand) : yrand < 0 ? rng.i(yrand, 0) : yrand;
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) {
y = (c != null ? c.getSurface() : placer.getHighest(x, z, getLoader(), config.isUnderwater())) + rty;
if (!config.isForcePlace()) {
@@ -932,7 +941,7 @@ public class IrisObject extends IrisRegistrant {
if (j.isExact() ? k.matches(data) : k.getMaterial().equals(data.getMaterial())) {
BlockData newData = j.getReplace(rng, i.getX() + x, i.getY() + y, i.getZ() + z, rdata).clone();
if (newData.getMaterial() == data.getMaterial() && !(newData instanceof IrisBlockData || data instanceof IrisBlockData))
if (newData.getMaterial() == data.getMaterial() && !(newData instanceof IrisCustomData || data instanceof IrisCustomData))
data = data.merge(newData);
else
data = newData;
@@ -1001,8 +1010,9 @@ public class IrisObject extends IrisRegistrant {
}
boolean wouldReplace = B.isSolid(placer.get(xx, yy, zz)) && B.isVineBlock(data);
boolean place = !data.getMaterial().equals(Material.AIR) && !data.getMaterial().equals(Material.CAVE_AIR) && !wouldReplace;
if (!data.getMaterial().equals(Material.AIR) && !data.getMaterial().equals(Material.CAVE_AIR) && !wouldReplace) {
if (data instanceof IrisCustomData || place) {
placer.set(xx, yy, zz, data);
if (tile != null) {
placer.setTile(xx, yy, zz, tile);

View File

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

View File

@@ -34,9 +34,15 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.TreeType;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Function;
@Snippet("object-placer")
@EqualsAndHashCode()
@@ -103,6 +109,8 @@ public class IrisObjectPlacement {
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!")
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)")
private boolean bottom = false;
@Desc("If set to true, air will be placed before the schematic places.")
@@ -123,6 +131,9 @@ public class IrisObjectPlacement {
@ArrayType(min = 1, type = IrisObjectLoot.class)
@Desc("The loot tables to apply to these objects")
private KList<IrisObjectLoot> loot = new KList<>();
@ArrayType(min = 1, type = IrisObjectVanillaLoot.class)
@Desc("The vanilla loot tables to apply to these objects")
private KList<IrisObjectVanillaLoot> vanillaLoot = new KList<>();
@Desc("Whether the given loot tables override any and all other loot tables available in the dimension, region or biome.")
private boolean overrideGlobalLoot = false;
@Desc("This object / these objects override the following trees when they grow...")
@@ -211,46 +222,63 @@ public class IrisObjectPlacement {
private TableCache getCache(IrisData manager) {
return cache.aquire(() -> {
TableCache tc = new TableCache();
TableCache cache = new TableCache();
for (IrisObjectLoot loot : getLoot()) {
if (loot == null)
continue;
IrisLootTable table = manager.getLootLoader().load(loot.getName());
if (table == null) {
Iris.warn("Couldn't find loot table " + loot.getName());
continue;
cache.merge(getCache(manager, getVanillaLoot(), IrisObjectPlacement::getVanillaTable));
cache.merge(getCache(manager, getLoot(), manager.getLootLoader()::load));
return cache;
});
}
private TableCache getCache(IrisData manager, KList<? extends IObjectLoot> list, Function<String, IrisLootTable> loader) {
TableCache tc = new TableCache();
for (IObjectLoot loot : list) {
if (loot == null)
continue;
IrisLootTable table = loader.apply(loot.getName());
if (table == null) {
Iris.warn("Couldn't find loot table " + loot.getName());
continue;
}
if (loot.getFilter().isEmpty()) //Table applies to all containers
{
tc.global.put(table, loot.getWeight());
} else if (!loot.isExact()) //Table is meant to be by type
{
for (BlockData filterData : loot.getFilter(manager)) {
if (!tc.basic.containsKey(filterData.getMaterial())) {
tc.basic.put(filterData.getMaterial(), new WeightedRandom<>());
}
tc.basic.get(filterData.getMaterial()).put(table, loot.getWeight());
}
if (loot.getFilter().isEmpty()) //Table applies to all containers
{
tc.global.put(table, loot.getWeight());
} else if (!loot.isExact()) //Table is meant to be by type
{
for (BlockData filterData : loot.getFilter(manager)) {
if (!tc.basic.containsKey(filterData.getMaterial())) {
tc.basic.put(filterData.getMaterial(), new WeightedRandom<>());
}
tc.basic.get(filterData.getMaterial()).put(table, loot.getWeight());
} else //Filter is exact
{
for (BlockData filterData : loot.getFilter(manager)) {
if (!tc.exact.containsKey(filterData.getMaterial())) {
tc.exact.put(filterData.getMaterial(), new KMap<>());
}
} else //Filter is exact
{
for (BlockData filterData : loot.getFilter(manager)) {
if (!tc.exact.containsKey(filterData.getMaterial())) {
tc.exact.put(filterData.getMaterial(), new KMap<>());
}
if (!tc.exact.get(filterData.getMaterial()).containsKey(filterData)) {
tc.exact.get(filterData.getMaterial()).put(filterData, new WeightedRandom<>());
}
tc.exact.get(filterData.getMaterial()).get(filterData).put(table, loot.getWeight());
if (!tc.exact.get(filterData.getMaterial()).containsKey(filterData)) {
tc.exact.get(filterData.getMaterial()).put(filterData, new WeightedRandom<>());
}
tc.exact.get(filterData.getMaterial()).get(filterData).put(table, loot.getWeight());
}
}
return tc;
});
}
return tc;
}
@Nullable
private static IrisVanillaLootTable getVanillaTable(String name) {
return Optional.ofNullable(NamespacedKey.fromString(name))
.map(Bukkit::getLootTable)
.map(IrisVanillaLootTable::new)
.orElse(null);
}
/**
@@ -262,7 +290,6 @@ public class IrisObjectPlacement {
*/
public IrisLootTable getTable(BlockData data, IrisData dataManager) {
TableCache cache = getCache(dataManager);
if (B.isStorageChest(data)) {
IrisLootTable picked = null;
if (cache.exact.containsKey(data.getMaterial()) && cache.exact.get(data.getMaterial()).containsKey(data)) {
@@ -283,5 +310,11 @@ public class IrisObjectPlacement {
final transient WeightedRandom<IrisLootTable> global = new WeightedRandom<>();
final transient KMap<Material, WeightedRandom<IrisLootTable>> basic = 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

@@ -0,0 +1,50 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.engine.object.annotations.functions.LootTableKeyFunction;
import com.volmit.iris.util.collection.KList;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.block.data.BlockData;
@Snippet("object-vanilla-loot")
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Represents vanilla loot within this object or jigsaw piece")
@Data
public class IrisObjectVanillaLoot implements IObjectLoot {
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
@ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The list of blocks this loot table should apply to")
private KList<IrisBlockData> filter = new KList<>();
@Desc("Exactly match the block data or not")
private boolean exact = false;
@Desc("The vanilla loot table key")
@Required
@RegistryListFunction(LootTableKeyFunction.class)
private String name;
@Desc("The weight of this loot table being chosen")
private int weight = 1;
public KList<BlockData> getFilter(IrisData rdata) {
return filterCache.aquire(() ->
{
KList<BlockData> b = new KList<>();
for (IrisBlockData i : filter) {
BlockData bx = i.getBlockData(rdata);
if (bx != null) {
b.add(bx);
}
}
return b;
});
}
}

View File

@@ -0,0 +1,80 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootContext;
import org.bukkit.loot.LootTable;
import java.io.File;
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisVanillaLootTable extends IrisLootTable {
private final LootTable lootTable;
@Override
public String getName() {
return "Vanilla " + lootTable.getKey();
}
@Override
public int getRarity() {
return 0;
}
@Override
public int getMaxPicked() {
return 0;
}
@Override
public int getMinPicked() {
return 0;
}
@Override
public int getMaxTries() {
return 0;
}
@Override
public KList<IrisLoot> getLoot() {
return new KList<>();
}
@Override
public KList<ItemStack> getLoot(boolean debug, RNG rng, InventorySlotType slot, 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
public String getFolderName() {
throw new UnsupportedOperationException("VanillaLootTables do not have a folder name");
}
@Override
public String getTypeName() {
throw new UnsupportedOperationException("VanillaLootTables do not have a type name");
}
@Override
public File getLoadFile() {
throw new UnsupportedOperationException("VanillaLootTables do not have a load file");
}
@Override
public IrisData getLoader() {
throw new UnsupportedOperationException("VanillaLootTables do not have a loader");
}
@Override
public KList<String> getPreprocessors() {
return new KList<>();
}
}

View File

@@ -1,28 +1,40 @@
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.KMap;
import com.volmit.iris.util.scheduling.J;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
import org.apache.commons.io.function.IOFunction;
import org.bukkit.DyeColor;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@ToString
@EqualsAndHashCode(callSuper = false)
public class LegacyTileData extends TileData {
private static final Map<Integer, IOFunction<DataInputStream, Handler>> legacy = Map.of(
0, SignHandler::new,
1, SpawnerHandler::new,
2, BannerHandler::new);
private static final Map<Integer, Pair<Builder, IOFunction<DataInputStream, Handler>>> legacy = Map.of(
0, new Pair<>(SignHandler::fromBukkit, SignHandler::new),
1, new Pair<>(SpawnerHandler::fromBukkit, SpawnerHandler::new),
2, new Pair<>(BannerHandler::fromBukkit, BannerHandler::new));
private static final AtomicCache<Tag<Material>> SIGNS = new AtomicCache<>();
private final int id;
private final Handler handler;
@@ -31,7 +43,39 @@ public class LegacyTileData extends TileData {
var factory = legacy.get(id);
if (factory == null)
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
public @NonNull KMap<String, Object> getProperties() {
return new KMap<>();
}
@Override
public @NonNull Material getMaterial() {
return handler.getMaterial();
}
@Override
public boolean isApplicable(BlockData data) {
return handler.isApplicable(data);
}
@Override
@@ -51,12 +95,20 @@ public class LegacyTileData extends TileData {
}
private interface Handler {
Material getMaterial();
boolean isApplicable(BlockData data);
void toBinary(DataOutputStream out) throws IOException;
void toBukkit(Block block);
}
@FunctionalInterface
private interface Builder {
@Nullable Handler apply(@NonNull BlockState blockState, @NonNull Material type);
}
@ToString
@EqualsAndHashCode
@AllArgsConstructor
private static class SignHandler implements Handler {
private final String line1;
private final String line2;
@@ -72,6 +124,23 @@ public class LegacyTileData extends TileData {
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
public Material getMaterial() {
return Material.OAK_SIGN;
}
@Override
public boolean isApplicable(BlockData data) {
return signsTag().isTagged(data.getMaterial());
}
@Override
public void toBinary(DataOutputStream out) throws IOException {
out.writeUTF(line1);
@@ -94,6 +163,7 @@ public class LegacyTileData extends TileData {
}
@ToString
@EqualsAndHashCode
@AllArgsConstructor
private static class SpawnerHandler implements Handler {
private final EntityType type;
@@ -101,6 +171,22 @@ public class LegacyTileData extends TileData {
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
public Material getMaterial() {
return Material.SPAWNER;
}
@Override
public boolean isApplicable(BlockData data) {
return data.getMaterial() == Material.SPAWNER;
}
@Override
public void toBinary(DataOutputStream out) throws IOException {
out.writeShort(type.ordinal());
@@ -115,6 +201,7 @@ public class LegacyTileData extends TileData {
}
@ToString
@EqualsAndHashCode
@AllArgsConstructor
private static class BannerHandler implements Handler {
private final KList<Pattern> patterns;
private final DyeColor baseColor;
@@ -130,6 +217,22 @@ 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
public Material getMaterial() {
return Material.WHITE_BANNER;
}
@Override
public boolean isApplicable(BlockData data) {
return Tag.BANNERS.isTagged(data.getMaterial());
}
@Override
public void toBinary(DataOutputStream out) throws IOException {
out.writeByte(baseColor.ordinal());
@@ -148,4 +251,32 @@ public class LegacyTileData extends TileData {
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

@@ -35,7 +35,6 @@ import java.io.IOException;
@SuppressWarnings("ALL")
@Getter
@ToString
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@@ -53,9 +52,15 @@ public class TileData implements Cloneable {
return false;
}
public static TileData getTileState(Block block) {
public static TileData getTileState(Block block, boolean useLegacy) {
if (!INMS.get().hasTile(block.getType()))
return null;
if (useLegacy) {
var legacy = LegacyTileData.fromBukkit(block.getState());
if (legacy != null)
return legacy;
}
return new TileData().fromBukkit(block);
}
@@ -131,4 +136,9 @@ public class TileData implements Cloneable {
clone.properties = properties.copy(); //TODO make a deep copy
return clone;
}
@Override
public String toString() {
return material.getKey() + gson.toJson(properties);
}
}

View File

@@ -1,6 +1,5 @@
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.util.collection.KList;
@@ -13,5 +12,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListFunction {
Class<? extends ListFunction<IrisData, KList<String>>> value();
Class<? extends ListFunction<KList<String>>> value();
}

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