mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-07-23 23:31:00 +00:00
Dont ask
This commit is contained in:
@@ -201,6 +201,7 @@ def generateTemplates = tasks.register('generateTemplates', Copy) {
|
||||
logger.error('Git commit hash not found', failure)
|
||||
return 'unknown'
|
||||
},
|
||||
minecraftVersion: providers.gradleProperty('minecraftVersion'),
|
||||
])
|
||||
|
||||
from(templateSource)
|
||||
|
||||
@@ -7,7 +7,6 @@ art/arcane/iris/core/edit/DustRevealer.java
|
||||
art/arcane/iris/core/events/IrisEngineEvent.java
|
||||
art/arcane/iris/core/events/IrisEngineHotloadEvent.java
|
||||
art/arcane/iris/core/events/IrisLootEvent.java
|
||||
art/arcane/iris/core/gui/PregeneratorJob.java
|
||||
art/arcane/iris/core/lifecycle/BukkitPublicBackend.java
|
||||
art/arcane/iris/core/lifecycle/CapabilitySnapshot.java
|
||||
art/arcane/iris/core/lifecycle/PaperLibBootstrap.java
|
||||
@@ -36,16 +35,13 @@ art/arcane/iris/core/link/data/NexoDataProvider.java
|
||||
art/arcane/iris/core/nms/INMS.java
|
||||
art/arcane/iris/core/nms/INMSBinding.java
|
||||
art/arcane/iris/core/nms/MinecraftVersion.java
|
||||
art/arcane/iris/core/nms/datapack/v1206/DataFixerV1206.java
|
||||
art/arcane/iris/core/nms/v1X/NMSBinding1X.java
|
||||
art/arcane/iris/core/pack/IrisPack.java
|
||||
art/arcane/iris/core/pregenerator/DeepSearchPregenerator.java
|
||||
art/arcane/iris/core/pregenerator/methods/AsyncOrMedievalPregenMethod.java
|
||||
art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java
|
||||
art/arcane/iris/core/pregenerator/methods/HybridPregenMethod.java
|
||||
art/arcane/iris/core/pregenerator/methods/MedievalPregenMethod.java
|
||||
art/arcane/iris/core/project/IrisProject.java
|
||||
art/arcane/iris/core/project/SchemaBuilder.java
|
||||
art/arcane/iris/core/runtime/BukkitPublicRuntimeControlBackend.java
|
||||
art/arcane/iris/core/runtime/ChunkClearer.java
|
||||
art/arcane/iris/core/runtime/ChunkJobReporter.java
|
||||
@@ -78,25 +74,20 @@ art/arcane/iris/core/tools/IrisWorldCreator.java
|
||||
art/arcane/iris/core/tools/TreePlausibilizer.java
|
||||
art/arcane/iris/engine/IrisEngineEffects.java
|
||||
art/arcane/iris/engine/IrisWorldManager.java
|
||||
art/arcane/iris/engine/actuator/IrisBiomeActuator.java
|
||||
art/arcane/iris/engine/data/chunk/LinkedTerrainChunk.java
|
||||
art/arcane/iris/engine/data/chunk/TerrainChunk.java
|
||||
art/arcane/iris/engine/decorator/DecoratorCore.java
|
||||
art/arcane/iris/engine/framework/Engine.java
|
||||
art/arcane/iris/engine/framework/EngineAssignedWorldManager.java
|
||||
art/arcane/iris/engine/framework/EnginePlayer.java
|
||||
art/arcane/iris/engine/framework/EngineWorldManager.java
|
||||
art/arcane/iris/engine/framework/placer/WorldObjectPlacer.java
|
||||
art/arcane/iris/engine/mantle/MantleWriter.java
|
||||
art/arcane/iris/engine/modifier/IrisFloatingChildBiomeModifier.java
|
||||
art/arcane/iris/engine/object/BlockDataMergeSupport.java
|
||||
art/arcane/iris/engine/object/IPostBlockAccess.java
|
||||
art/arcane/iris/engine/object/IrisAttributeModifier.java
|
||||
art/arcane/iris/engine/object/IrisBiome.java
|
||||
art/arcane/iris/engine/object/IrisBiomeCustom.java
|
||||
art/arcane/iris/engine/object/IrisBiomeCustomParticle.java
|
||||
art/arcane/iris/engine/object/IrisBiomeCustomSpawn.java
|
||||
art/arcane/iris/engine/object/IrisBlockData.java
|
||||
art/arcane/iris/engine/object/IrisBlockDrops.java
|
||||
art/arcane/iris/engine/object/IrisCommandRegistry.java
|
||||
art/arcane/iris/engine/object/IrisCompat.java
|
||||
|
||||
@@ -73,6 +73,7 @@ public class IrisSettings {
|
||||
try {
|
||||
String ss = IO.readAll(s);
|
||||
settings = new Gson().fromJson(ss, IrisSettings.class);
|
||||
migrateLegacyKeys(ss);
|
||||
try {
|
||||
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
|
||||
} catch (IOException e) {
|
||||
@@ -87,6 +88,17 @@ public class IrisSettings {
|
||||
return settings;
|
||||
}
|
||||
|
||||
private static void migrateLegacyKeys(String rawJson) {
|
||||
JSONObject root = new JSONObject(rawJson);
|
||||
JSONObject worldObject = root.optJSONObject("world");
|
||||
if (worldObject == null || !worldObject.has("anbientEntitySpawningSystem")) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings.getWorld().setAmbientEntitySpawningSystem(worldObject.optBoolean("anbientEntitySpawningSystem", settings.getWorld().isAmbientEntitySpawningSystem()));
|
||||
IrisLogging.info("Migrated legacy settings key world.anbientEntitySpawningSystem -> world.ambientEntitySpawningSystem");
|
||||
}
|
||||
|
||||
public static void invalidate() {
|
||||
synchronized (settings) {
|
||||
settings = null;
|
||||
@@ -115,7 +127,7 @@ public class IrisSettings {
|
||||
public static class IrisSettingsWorld {
|
||||
public boolean postLoadBlockUpdates = true;
|
||||
public boolean forcePersistEntities = true;
|
||||
public boolean anbientEntitySpawningSystem = true;
|
||||
public boolean ambientEntitySpawningSystem = true;
|
||||
public long asyncTickIntervalMS = 700;
|
||||
public double targetSpawnEntitiesPerChunk = 0.95;
|
||||
public boolean markerEntitySpawningSystem = true;
|
||||
|
||||
@@ -8,7 +8,10 @@ import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
package art.arcane.iris.core.gui;
|
||||
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.protocol.IrisProtocolServer;
|
||||
import art.arcane.iris.core.pregenerator.IrisPregenerator;
|
||||
import art.arcane.iris.core.pregenerator.PregenListener;
|
||||
import art.arcane.iris.core.pregenerator.PregenTask;
|
||||
@@ -345,6 +348,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
shouldGc();
|
||||
rgc++;
|
||||
broadcastRegionDelta(x, z, IrisMessage.PregenRegionDelta.STATE_DONE);
|
||||
}
|
||||
|
||||
private void shouldGc() {
|
||||
@@ -353,9 +357,17 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastRegionDelta(int regionX, int regionZ, int state) {
|
||||
IrisProtocolServer protocolServer = IrisServices.getOrNull(IrisProtocolServer.class);
|
||||
if (protocolServer == null) {
|
||||
return;
|
||||
}
|
||||
protocolServer.broadcastPregenRegionDelta(pregenerator.getJobId(), regionX, regionZ, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerating(int x, int z) {
|
||||
|
||||
broadcastRegionDelta(x, z, IrisMessage.PregenRegionDelta.STATE_GENERATING);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,8 @@ package art.arcane.iris.core.gui;
|
||||
import art.arcane.iris.engine.framework.render.IrisRenderer;
|
||||
import art.arcane.iris.engine.framework.render.RenderType;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.PreservationRegistry;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
@@ -154,6 +156,11 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
|
||||
});
|
||||
|
||||
public VisionGUI(JFrame frame) {
|
||||
PreservationRegistry preservation = IrisServices.getOrNull(PreservationRegistry.class);
|
||||
if (preservation != null) {
|
||||
preservation.register(e);
|
||||
preservation.register(eh);
|
||||
}
|
||||
m.set(8);
|
||||
rs.put(1);
|
||||
setBackground(BG);
|
||||
|
||||
@@ -22,7 +22,11 @@ import org.bukkit.event.EventHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
|
||||
package art.arcane.iris.core.loader;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.ExclusionStrategy;
|
||||
import com.google.gson.FieldAttributes;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.Strictness;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
@@ -27,7 +33,22 @@ import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisBlockData;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisEntity;
|
||||
import art.arcane.iris.engine.object.IrisExpression;
|
||||
import art.arcane.iris.engine.object.IrisGenerator;
|
||||
import art.arcane.iris.engine.object.IrisImage;
|
||||
import art.arcane.iris.engine.object.IrisJigsawPiece;
|
||||
import art.arcane.iris.engine.object.IrisJigsawPool;
|
||||
import art.arcane.iris.engine.object.IrisLootTable;
|
||||
import art.arcane.iris.engine.object.IrisMarker;
|
||||
import art.arcane.iris.engine.object.IrisMod;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisSpawner;
|
||||
import art.arcane.iris.engine.object.IrisStructure;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.engine.object.matter.IrisMatterObject;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
@@ -48,7 +69,11 @@ import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
|
||||
@@ -25,7 +25,7 @@ import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -46,13 +46,19 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
@@ -74,6 +80,7 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
return thread;
|
||||
});
|
||||
private static final Set<String> schemaBuildQueue = ConcurrentHashMap.newKeySet();
|
||||
private static final AtomicBoolean schemaBuildExecutorRegistered = new AtomicBoolean();
|
||||
protected final AtomicCache<KList<File>> folderCache;
|
||||
protected KSet<String> firstAccess;
|
||||
protected File root;
|
||||
@@ -101,6 +108,10 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getResourceLoaderCacheSize());
|
||||
IrisLogging.debug("Loader<" + C.GREEN + resourceTypeName + C.LIGHT_PURPLE + "> created in " + C.RED + "IDM/" + manager.getId() + C.LIGHT_PURPLE + " on " + C.GRAY + manager.getDataFolder().getPath());
|
||||
IrisServices.get(PreservationRegistry.class).registerCache(this);
|
||||
PreservationRegistry preservation = IrisServices.getOrNull(PreservationRegistry.class);
|
||||
if (preservation != null && schemaBuildExecutorRegistered.compareAndSet(false, true)) {
|
||||
preservation.register(schemaBuildExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject buildSchema() {
|
||||
|
||||
@@ -4,7 +4,13 @@ import art.arcane.volmlib.util.json.JSONArray;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class BlockProperty {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package art.arcane.iris.core.nms.datapack.v1192;
|
||||
|
||||
import static art.arcane.iris.engine.object.IrisDimensionTypeOptions.TriState.FALSE;
|
||||
import static art.arcane.iris.engine.object.IrisDimensionTypeOptions.TriState.TRUE;
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer;
|
||||
import art.arcane.iris.engine.object.IrisDimensionTypeOptions;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
@@ -7,7 +9,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static art.arcane.iris.engine.object.IrisDimensionTypeOptions.TriState.*;
|
||||
|
||||
public class DataFixerV1192 implements IDataFixer {
|
||||
private static final Map<Dimension, IrisDimensionTypeOptions> OPTIONS = Map.of(
|
||||
|
||||
@@ -32,7 +32,11 @@ import art.arcane.volmlib.util.math.Vector3d;
|
||||
import art.arcane.volmlib.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import art.arcane.volmlib.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import art.arcane.volmlib.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.pack;
|
||||
|
||||
import art.arcane.iris.spi.PlatformRegistries;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ContentKeyValidator {
|
||||
private static final int MAX_SUGGESTION_SCANS = 4096;
|
||||
private static final String DEFAULT_NAMESPACE = "minecraft";
|
||||
|
||||
private ContentKeyValidator() {
|
||||
}
|
||||
|
||||
public enum ContentRegistry {
|
||||
BLOCK,
|
||||
ITEM,
|
||||
ENTITY;
|
||||
|
||||
public String label() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
public record ContentKeyError(String key, ContentRegistry registry, boolean namespaceLoaded, String suggestion) {
|
||||
public String message() {
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append("Unknown ").append(registry.label()).append(" key '").append(key).append('\'');
|
||||
sb.append(" (missing from the ").append(registry.label()).append(" registry");
|
||||
if (!namespaceLoaded) {
|
||||
sb.append("; namespace '").append(namespaceOf(key)).append("' is not loaded on this server");
|
||||
}
|
||||
sb.append(')');
|
||||
if (suggestion != null) {
|
||||
sb.append(" - did you mean '").append(suggestion).append("'?");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ContentKeyError> validate(PlatformRegistries registries,
|
||||
Collection<String> referencedBlocks,
|
||||
Collection<String> referencedItems,
|
||||
Collection<String> referencedEntities) {
|
||||
if (registries == null) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<String> blockKeys = normalizeKeyList(registries.blockKeys());
|
||||
List<String> itemKeys = normalizeKeyList(registries.itemKeys());
|
||||
List<String> entityKeys = normalizeKeyList(registries.entityKeys());
|
||||
|
||||
Set<String> knownBlocks = new HashSet<>(blockKeys);
|
||||
Set<String> knownItems = new HashSet<>(itemKeys);
|
||||
Set<String> knownEntities = new HashSet<>(entityKeys);
|
||||
|
||||
Set<String> loadedNamespaces = new HashSet<>();
|
||||
addNamespaces(blockKeys, loadedNamespaces);
|
||||
addNamespaces(itemKeys, loadedNamespaces);
|
||||
addNamespaces(entityKeys, loadedNamespaces);
|
||||
|
||||
Map<String, ContentKeyError> errors = new LinkedHashMap<>();
|
||||
validateCategory(referencedBlocks, ContentRegistry.BLOCK, knownBlocks, blockKeys, loadedNamespaces, errors);
|
||||
validateCategory(referencedItems, ContentRegistry.ITEM, knownItems, itemKeys, loadedNamespaces, errors);
|
||||
validateCategory(referencedEntities, ContentRegistry.ENTITY, knownEntities, entityKeys, loadedNamespaces, errors);
|
||||
return List.copyOf(errors.values());
|
||||
}
|
||||
|
||||
static String namespaceOf(String key) {
|
||||
int colon = key.indexOf(':');
|
||||
return colon < 0 ? DEFAULT_NAMESPACE : key.substring(0, colon);
|
||||
}
|
||||
|
||||
private static void validateCategory(Collection<String> referenced,
|
||||
ContentRegistry registry,
|
||||
Set<String> known,
|
||||
List<String> candidatePool,
|
||||
Set<String> loadedNamespaces,
|
||||
Map<String, ContentKeyError> errors) {
|
||||
if (referenced == null || referenced.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (String raw : referenced) {
|
||||
String normalized = normalizeKey(raw);
|
||||
if (normalized == null || known.contains(normalized)) {
|
||||
continue;
|
||||
}
|
||||
String dedupKey = registry.name() + '|' + normalized;
|
||||
if (errors.containsKey(dedupKey)) {
|
||||
continue;
|
||||
}
|
||||
boolean namespaceLoaded = loadedNamespaces.contains(namespaceOf(normalized));
|
||||
String suggestion = nearestKey(normalized, candidatePool);
|
||||
errors.put(dedupKey, new ContentKeyError(normalized, registry, namespaceLoaded, suggestion));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> normalizeKeyList(List<String> keys) {
|
||||
if (keys == null || keys.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
List<String> out = new ArrayList<>(keys.size());
|
||||
for (String key : keys) {
|
||||
if (key == null || key.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String value = key.trim().toLowerCase(Locale.ROOT);
|
||||
if (!value.isEmpty()) {
|
||||
out.add(value.indexOf(':') < 0 ? DEFAULT_NAMESPACE + ':' + value : value);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void addNamespaces(List<String> keys, Set<String> namespaces) {
|
||||
for (String key : keys) {
|
||||
namespaces.add(namespaceOf(key));
|
||||
}
|
||||
}
|
||||
|
||||
private static String normalizeKey(String raw) {
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
String value = raw.trim().toLowerCase(Locale.ROOT);
|
||||
int bracket = value.indexOf('[');
|
||||
if (bracket >= 0) {
|
||||
value = value.substring(0, bracket).trim();
|
||||
}
|
||||
if (value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return value.indexOf(':') < 0 ? DEFAULT_NAMESPACE + ':' + value : value;
|
||||
}
|
||||
|
||||
private static String nearestKey(String key, List<String> candidatePool) {
|
||||
String path = pathOf(key);
|
||||
int maxDistance = Math.max(2, path.length() / 3);
|
||||
int bestDistance = Integer.MAX_VALUE;
|
||||
String best = null;
|
||||
int scans = 0;
|
||||
|
||||
for (String candidate : candidatePool) {
|
||||
String candidatePath = pathOf(candidate);
|
||||
if (Math.abs(candidatePath.length() - path.length()) > maxDistance) {
|
||||
continue;
|
||||
}
|
||||
if (scans++ >= MAX_SUGGESTION_SCANS) {
|
||||
break;
|
||||
}
|
||||
int distance = boundedLevenshtein(path, candidatePath, maxDistance);
|
||||
if (distance < bestDistance) {
|
||||
bestDistance = distance;
|
||||
best = candidate;
|
||||
if (distance <= 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestDistance <= maxDistance ? best : null;
|
||||
}
|
||||
|
||||
private static String pathOf(String key) {
|
||||
int colon = key.indexOf(':');
|
||||
return colon < 0 ? key : key.substring(colon + 1);
|
||||
}
|
||||
|
||||
private static int boundedLevenshtein(String a, String b, int max) {
|
||||
int la = a.length();
|
||||
int lb = b.length();
|
||||
if (Math.abs(la - lb) > max) {
|
||||
return max + 1;
|
||||
}
|
||||
int[] prev = new int[lb + 1];
|
||||
int[] curr = new int[lb + 1];
|
||||
for (int j = 0; j <= lb; j++) {
|
||||
prev[j] = j;
|
||||
}
|
||||
for (int i = 1; i <= la; i++) {
|
||||
curr[0] = i;
|
||||
int rowMin = curr[0];
|
||||
char ca = a.charAt(i - 1);
|
||||
for (int j = 1; j <= lb; j++) {
|
||||
int cost = ca == b.charAt(j - 1) ? 0 : 1;
|
||||
curr[j] = Math.min(Math.min(prev[j] + 1, curr[j - 1] + 1), prev[j - 1] + cost);
|
||||
if (curr[j] < rowMin) {
|
||||
rowMin = curr[j];
|
||||
}
|
||||
}
|
||||
if (rowMin > max) {
|
||||
return max + 1;
|
||||
}
|
||||
int[] tmp = prev;
|
||||
prev = curr;
|
||||
curr = tmp;
|
||||
}
|
||||
return prev[lb];
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@
|
||||
package art.arcane.iris.core.pack;
|
||||
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.spi.PlatformRegistries;
|
||||
import art.arcane.volmlib.util.json.JSONArray;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
|
||||
@@ -35,6 +37,7 @@ import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -98,9 +101,126 @@ public final class PackValidator {
|
||||
warnings.add("Unused-resource GC pass failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
runContentKeyValidation(packFolder, warnings);
|
||||
|
||||
return new PackValidationResult(packName, blockingErrors, warnings, removedUnusedFiles, validatedAt);
|
||||
}
|
||||
|
||||
private static void runContentKeyValidation(File packFolder, List<String> warnings) {
|
||||
try {
|
||||
if (!IrisPlatforms.isBound()) {
|
||||
return;
|
||||
}
|
||||
PlatformRegistries registries = IrisPlatforms.get().registries();
|
||||
if (registries == null) {
|
||||
return;
|
||||
}
|
||||
List<String> blockKeys = registries.blockKeys();
|
||||
List<String> itemKeys = registries.itemKeys();
|
||||
List<String> entityKeys = registries.entityKeys();
|
||||
if (blockKeys == null || blockKeys.isEmpty() || itemKeys == null || itemKeys.isEmpty() || entityKeys == null || entityKeys.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReferencedContentKeys referenced = collectReferencedContentKeys(packFolder);
|
||||
List<ContentKeyValidator.ContentKeyError> errors = ContentKeyValidator.validate(
|
||||
registries, referenced.blocks(), referenced.items(), referenced.entities());
|
||||
for (ContentKeyValidator.ContentKeyError error : errors) {
|
||||
warnings.add(error.message());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
IrisLogging.reportError("PackValidator content-key validation failed for pack '" + packFolder.getName() + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static ReferencedContentKeys collectReferencedContentKeys(File packFolder) {
|
||||
Set<String> blocks = new HashSet<>();
|
||||
Set<String> items = new HashSet<>();
|
||||
Set<String> entities = new HashSet<>();
|
||||
Set<String> customBlocks = deriveRegistrantKeys(new File(packFolder, "blocks"));
|
||||
|
||||
try (Stream<Path> stream = Files.walk(packFolder.toPath())) {
|
||||
List<Path> files = stream.filter(Files::isRegularFile)
|
||||
.filter(PackValidator::isScannableJsonPath)
|
||||
.toList();
|
||||
for (Path path : files) {
|
||||
String relative = packFolder.toPath().relativize(path).toString().replace(File.separatorChar, '/');
|
||||
boolean inLoot = relative.startsWith("loot/");
|
||||
boolean inEntities = relative.startsWith("entities/");
|
||||
JSONObject json;
|
||||
try {
|
||||
json = new JSONObject(Files.readString(path, StandardCharsets.UTF_8));
|
||||
} catch (Throwable ignored) {
|
||||
continue;
|
||||
}
|
||||
collectFromNode(json, blocks, inLoot ? items : null, inEntities ? entities : null, customBlocks);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
IrisLogging.reportError("PackValidator failed to walk pack for content-key extraction", e);
|
||||
}
|
||||
|
||||
return new ReferencedContentKeys(blocks, items, entities);
|
||||
}
|
||||
|
||||
private static void collectFromNode(Object node, Set<String> blocks, Set<String> items, Set<String> entities, Set<String> customBlocks) {
|
||||
if (node instanceof JSONObject obj) {
|
||||
for (String key : obj.keySet()) {
|
||||
Object value = obj.get(key);
|
||||
if (value instanceof String str) {
|
||||
if ("block".equals(key)) {
|
||||
addBlockRef(str, blocks, customBlocks);
|
||||
} else if (items != null && "type".equals(key)) {
|
||||
addSimpleRef(str, items);
|
||||
} else if (entities != null && "type".equals(key)) {
|
||||
addSimpleRef(str, entities);
|
||||
}
|
||||
} else {
|
||||
collectFromNode(value, blocks, items, entities, customBlocks);
|
||||
}
|
||||
}
|
||||
} else if (node instanceof JSONArray arr) {
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
collectFromNode(arr.get(i), blocks, items, entities, customBlocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addBlockRef(String raw, Set<String> blocks, Set<String> customBlocks) {
|
||||
String value = raw.trim().toLowerCase(Locale.ROOT);
|
||||
int bracket = value.indexOf('[');
|
||||
if (bracket >= 0) {
|
||||
value = value.substring(0, bracket).trim();
|
||||
}
|
||||
if (value.isEmpty() || customBlocks.contains(value)) {
|
||||
return;
|
||||
}
|
||||
blocks.add(value);
|
||||
}
|
||||
|
||||
private static void addSimpleRef(String raw, Set<String> target) {
|
||||
String value = raw.trim().toLowerCase(Locale.ROOT);
|
||||
if (!value.isEmpty()) {
|
||||
target.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> deriveRegistrantKeys(File folder) {
|
||||
Set<String> keys = new HashSet<>();
|
||||
if (!folder.isDirectory()) {
|
||||
return keys;
|
||||
}
|
||||
for (File file : listJsonRecursive(folder)) {
|
||||
String key = deriveKey(folder, file);
|
||||
if (key != null && !key.isBlank()) {
|
||||
keys.add(key.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
private record ReferencedContentKeys(Set<String> blocks, Set<String> items, Set<String> entities) {
|
||||
}
|
||||
|
||||
private static void validateDimensions(File packFolder, File[] dimensionFiles, List<String> blockingErrors, List<String> warnings) {
|
||||
File regionsFolder = new File(packFolder, "regions");
|
||||
File biomesFolder = new File(packFolder, "biomes");
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
package art.arcane.iris.core.pregenerator;
|
||||
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.core.protocol.IrisProtocolServer;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.tools.IrisPackBenchmarking;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
@@ -41,6 +44,8 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class IrisPregenerator {
|
||||
private static final double INVALID = 9223372036854775807d;
|
||||
private static final AtomicLong JOB_SEQUENCE = new AtomicLong(0L);
|
||||
private final long jobId;
|
||||
private final PregenTask task;
|
||||
private final PregeneratorMethod generator;
|
||||
private final PregenListener listener;
|
||||
@@ -72,6 +77,7 @@ public class IrisPregenerator {
|
||||
private final IrisPackBenchmarking benchmarking;
|
||||
|
||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||
this.jobId = JOB_SEQUENCE.incrementAndGet();
|
||||
benchmarking = IrisPackBenchmarking.getInstance();
|
||||
this.listener = listenify(listener);
|
||||
cl = new ChronoLatch(10000);
|
||||
@@ -138,6 +144,17 @@ public class IrisPregenerator {
|
||||
totalChunks.get() - generated.get(), eta, M.ms() - startTime.get(), currentGeneratorMethod.get(),
|
||||
cached);
|
||||
|
||||
IrisProtocolServer protocolServer = IrisServices.getOrNull(IrisProtocolServer.class);
|
||||
if (protocolServer != null) {
|
||||
protocolServer.broadcastPregenProgress(
|
||||
jobId,
|
||||
generated.get(),
|
||||
totalChunks.get(),
|
||||
cached ? cachedPerSecond.getAverage() : chunksPerSecond.getAverage(),
|
||||
eta,
|
||||
paused.get() ? IrisMessage.PregenProgress.STATE_PAUSED : IrisMessage.PregenProgress.STATE_RUNNING);
|
||||
}
|
||||
|
||||
if (cl.flip()) {
|
||||
double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100;
|
||||
|
||||
@@ -172,6 +189,10 @@ public class IrisPregenerator {
|
||||
}
|
||||
|
||||
|
||||
public long getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
shutdown.set(true);
|
||||
}
|
||||
@@ -219,6 +240,11 @@ public class IrisPregenerator {
|
||||
generator.close();
|
||||
ticker.interrupt();
|
||||
listener.onClose();
|
||||
IrisProtocolServer protocolServer = IrisServices.getOrNull(IrisProtocolServer.class);
|
||||
if (protocolServer != null) {
|
||||
long total = totalChunks.get();
|
||||
protocolServer.pregenEnd(jobId, total > 0 && generated.get() >= total);
|
||||
}
|
||||
Mantle mantle = getMantle();
|
||||
if (mantle != null) {
|
||||
reclaimTectonicPlates(mantle);
|
||||
|
||||
+8
@@ -1,6 +1,8 @@
|
||||
package art.arcane.iris.core.pregenerator.cache;
|
||||
|
||||
import art.arcane.iris.engine.framework.PreservationRegistry;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.volmlib.util.data.Varint;
|
||||
import art.arcane.volmlib.util.documentation.ChunkCoordinates;
|
||||
import art.arcane.volmlib.util.documentation.RegionCoordinates;
|
||||
@@ -23,9 +25,11 @@ import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class PregenCacheImpl implements PregenCache {
|
||||
private static final ExecutorService DISPATCHER = Executors.newFixedThreadPool(4);
|
||||
private static final AtomicBoolean DISPATCHER_REGISTERED = new AtomicBoolean();
|
||||
private static final short SIZE = 1024;
|
||||
|
||||
private final File directory;
|
||||
@@ -35,6 +39,10 @@ public class PregenCacheImpl implements PregenCache {
|
||||
public PregenCacheImpl(File directory, int maxSize) {
|
||||
this.directory = directory;
|
||||
this.maxSize = maxSize;
|
||||
PreservationRegistry preservation = IrisServices.getOrNull(PreservationRegistry.class);
|
||||
if (preservation != null && DISPATCHER_REGISTERED.compareAndSet(false, true)) {
|
||||
preservation.register(DISPATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,9 @@ import art.arcane.iris.core.pregenerator.PregenListener;
|
||||
import art.arcane.iris.core.pregenerator.PregeneratorMethod;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.PreservationRegistry;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.util.project.context.ChunkContext;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.mantle.runtime.Mantle;
|
||||
@@ -63,6 +65,10 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
this.prefetchDisabled = new AtomicBoolean(J.isFolia());
|
||||
int prefetchThreads = J.isFolia() ? 0 : Math.max(2, Math.min(16, configuredThreads));
|
||||
this.prefetchPool = prefetchThreads > 0 ? newPrefetchPool(prefetchThreads) : null;
|
||||
PreservationRegistry preservation = IrisServices.getOrNull(PreservationRegistry.class);
|
||||
if (preservation != null && prefetchPool != null) {
|
||||
preservation.register(prefetchPool);
|
||||
}
|
||||
}
|
||||
|
||||
private static ExecutorService newPrefetchPool(int threads) {
|
||||
|
||||
@@ -27,7 +27,16 @@ import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.core.loader.ResourceLoader;
|
||||
import art.arcane.iris.core.runtime.StudioOpenCoordinator;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisBlockData;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisEntity;
|
||||
import art.arcane.iris.engine.object.IrisGenerator;
|
||||
import art.arcane.iris.engine.object.IrisLootTable;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisObjectPlacement;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisSpawner;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.engine.platform.PlatformChunkGenerator;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
@@ -56,7 +65,8 @@ import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
|
||||
package art.arcane.iris.core.project;
|
||||
|
||||
import art.arcane.iris.platform.bukkit.BukkitBlockResolution;
|
||||
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.spi.PlatformBlockProperty;
|
||||
import art.arcane.iris.spi.PlatformNumericRange;
|
||||
import art.arcane.iris.core.link.Identifier;
|
||||
import art.arcane.iris.core.link.data.DataType;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
@@ -29,23 +30,37 @@ import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.core.loader.ResourceLoader;
|
||||
import art.arcane.iris.core.service.ExternalDataSVC;
|
||||
import art.arcane.iris.core.structure.StructureSchemaKeys;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
import art.arcane.iris.engine.framework.ListFunction;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListBlockType;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListEnchantment;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListEntityType;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListFont;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListFunction;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListItemType;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListPotionEffect;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListSpecialEntity;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListStructure;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListVanillaStructure;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListVanillaStructureSet;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryMapBlockState;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.json.JSONArray;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.iris.util.common.reflect.KeyedType;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -55,13 +70,14 @@ import java.util.function.Function;
|
||||
public class SchemaBuilder {
|
||||
private static final String SYMBOL_LIMIT__N = "*";
|
||||
private static final String SYMBOL_TYPE__N = "";
|
||||
private static final JSONArray POTION_TYPES = getPotionTypes();
|
||||
private static final JSONArray ENCHANT_TYPES = getEnchantTypes();
|
||||
private static final String MINECRAFT_NAMESPACE = "minecraft:";
|
||||
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
|
||||
private final KMap<String, JSONObject> definitions;
|
||||
private final Class<?> root;
|
||||
private final KList<String> warnings;
|
||||
private final IrisData data;
|
||||
private JSONArray potionTypes;
|
||||
private JSONArray enchantTypes;
|
||||
|
||||
public SchemaBuilder(Class<?> root, IrisData data) {
|
||||
this.data = data;
|
||||
@@ -70,30 +86,6 @@ public class SchemaBuilder {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
private static JSONArray getPotionTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
|
||||
for (PotionEffectType gg : Registry.EFFECT) {
|
||||
NamespacedKey key = KeyedType.getKey(gg);
|
||||
if (key != null) {
|
||||
a.put(key.getKey().toUpperCase(Locale.ROOT).replaceAll("\\Q \\E", "_"));
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
private static JSONArray getEnchantTypes() {
|
||||
JSONArray array = new JSONArray();
|
||||
for (Enchantment e : Registry.ENCHANTMENT) {
|
||||
NamespacedKey key = KeyedType.getKey(e);
|
||||
if (key != null) {
|
||||
array.put(key.getKey());
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public JSONObject construct() {
|
||||
JSONObject schema = new JSONObject();
|
||||
schema.put("$schema", "http://json-schema.org/draft-07/schema#");
|
||||
@@ -122,6 +114,52 @@ public class SchemaBuilder {
|
||||
return schema;
|
||||
}
|
||||
|
||||
private JSONArray potionTypes() {
|
||||
if (potionTypes == null) {
|
||||
JSONArray a = new JSONArray();
|
||||
for (String key : IrisPlatforms.get().registries().potionEffectKeys()) {
|
||||
a.put(stripNamespace(key).toUpperCase(Locale.ROOT).replace(" ", "_"));
|
||||
}
|
||||
potionTypes = a;
|
||||
}
|
||||
return potionTypes;
|
||||
}
|
||||
|
||||
private JSONArray enchantTypes() {
|
||||
if (enchantTypes == null) {
|
||||
JSONArray a = new JSONArray();
|
||||
for (String key : IrisPlatforms.get().registries().enchantmentKeys()) {
|
||||
a.put(stripNamespace(key));
|
||||
}
|
||||
enchantTypes = a;
|
||||
}
|
||||
return enchantTypes;
|
||||
}
|
||||
|
||||
private JSONArray itemTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
for (String key : IrisPlatforms.get().registries().itemKeys()) {
|
||||
a.put(key.startsWith(MINECRAFT_NAMESPACE) ? key.substring(MINECRAFT_NAMESPACE.length()) : key);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
private JSONArray blockTypes() {
|
||||
JSONArray a = new JSONArray();
|
||||
for (String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
a.put(i);
|
||||
}
|
||||
for (String i : IrisPlatforms.get().registries().blockTypeKeys()) {
|
||||
a.put(i);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
private static String stripNamespace(String key) {
|
||||
int idx = key.indexOf(':');
|
||||
return idx < 0 ? key : key.substring(idx + 1);
|
||||
}
|
||||
|
||||
private JSONObject buildProperties(Class<?> c) {
|
||||
JSONObject o = new JSONObject();
|
||||
JSONObject properties = new JSONObject();
|
||||
@@ -132,7 +170,7 @@ public class SchemaBuilder {
|
||||
JSONArray required = new JSONArray();
|
||||
JSONArray extended = new JSONArray();
|
||||
|
||||
var parent = c.getSuperclass();
|
||||
Class<?> parent = c.getSuperclass();
|
||||
while (parent != null && IrisRegistrant.class.isAssignableFrom(parent)) {
|
||||
buildProperties(properties, required, extended, parent);
|
||||
parent = parent.getSuperclass();
|
||||
@@ -255,7 +293,7 @@ public class SchemaBuilder {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", new JSONArray(StructureSchemaKeys.collect(
|
||||
INMS.get().getStructureKeys(),
|
||||
IrisPlatforms.get().registries().structureKeys(),
|
||||
Arrays.asList(data.getStructureLoader().getPossibleKeys()),
|
||||
Arrays.asList(data.getJigsawPieceLoader().getPossibleKeys())).toArray(new String[0])));
|
||||
definitions.put(key, j);
|
||||
@@ -270,17 +308,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for (String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
for (String i : BukkitBlockResolution.getBlockTypes()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
j.put("enum", ja);
|
||||
j.put("enum", blockTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -295,7 +323,7 @@ public class SchemaBuilder {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for (String i : INMS.get().getStructureKeys()) {
|
||||
for (String i : IrisPlatforms.get().registries().structureKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
@@ -314,7 +342,7 @@ public class SchemaBuilder {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for (String i : INMS.get().getStructureSetKeys()) {
|
||||
for (String i : IrisPlatforms.get().structureHooks().structureSetKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
@@ -331,7 +359,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", BukkitBlockResolution.getItemTypes());
|
||||
j.put("enum", itemTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -339,6 +367,25 @@ public class SchemaBuilder {
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if (k.isAnnotationPresent(RegistryListEntityType.class)) {
|
||||
String key = "enum-entity-type";
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for (String i : IrisPlatforms.get().registries().entityKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
j.put("enum", ja);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Entity Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Entity Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if (k.isAnnotationPresent(RegistryListSpecialEntity.class)) {
|
||||
String key = "enum-reg-specialentity";
|
||||
|
||||
@@ -374,7 +421,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ENCHANT_TYPES);
|
||||
j.put("enum", enchantTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -386,7 +433,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
j.put("enum", potionTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -394,9 +441,9 @@ public class SchemaBuilder {
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
} else if (k.isAnnotationPresent(RegistryListFunction.class)) {
|
||||
var functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||
Class<? extends ListFunction<KList<String>>> functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||
try {
|
||||
var instance = functionClass.getDeclaredConstructor().newInstance();
|
||||
ListFunction<KList<String>> instance = functionClass.getDeclaredConstructor().newInstance();
|
||||
String key = instance.key();
|
||||
fancyType = instance.fancyName();
|
||||
|
||||
@@ -411,27 +458,13 @@ public class SchemaBuilder {
|
||||
} catch (Throwable e) {
|
||||
IrisLogging.error("Could not execute apply method in " + functionClass.getName());
|
||||
}
|
||||
} else if (k.getType().equals(PotionEffectType.class)) {
|
||||
String key = "enum-potion-effect-type";
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
fancyType = "Potion Effect Type";
|
||||
prop.put("$ref", "#/definitions/" + key);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
|
||||
} else if (KeyedType.isKeyed(k.getType())) {
|
||||
fancyType = addEnum(k.getType(), prop, description, KeyedType.values(k.getType()), Function.identity());
|
||||
} else if (SchemaKeyedTypes.isKeyed(k.getType())) {
|
||||
fancyType = addEnum(k.getType(), prop, description, SchemaKeyedTypes.values(k.getType()), Function.identity());
|
||||
} else if (k.getType().isEnum()) {
|
||||
fancyType = addEnum(k.getType(), prop, description, k.getType().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||
}
|
||||
}
|
||||
case "object" -> {
|
||||
//TODO add back descriptions
|
||||
if (k.isAnnotationPresent(RegistryMapBlockState.class)) {
|
||||
String blockType = k.getDeclaredAnnotation(RegistryMapBlockState.class).value();
|
||||
fancyType = "Block State";
|
||||
@@ -439,10 +472,13 @@ public class SchemaBuilder {
|
||||
JSONArray any = new JSONArray();
|
||||
prop.put("anyOf", any);
|
||||
|
||||
BukkitBlockResolution.getBlockStates().forEach((blocks, properties) -> {
|
||||
if (blocks.isEmpty()) return;
|
||||
for (BlockStateGroup group : reconstructBlockStateGroups()) {
|
||||
List<String> blocks = group.blocks();
|
||||
if (blocks.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String raw = blocks.getFirst().replace(':', '_');
|
||||
String raw = blocks.get(0).replace(':', '_');
|
||||
String enumKey = "enum-block-state-" + raw;
|
||||
String propertiesKey = "obj-block-state-" + raw;
|
||||
|
||||
@@ -470,15 +506,15 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(propertiesKey)) {
|
||||
JSONObject props = new JSONObject();
|
||||
properties.forEach(property -> {
|
||||
props.put(property.name(), property.buildJson());
|
||||
});
|
||||
for (PlatformBlockProperty property : group.properties()) {
|
||||
props.put(property.name(), buildBlockPropertyJson(property));
|
||||
}
|
||||
|
||||
definitions.put(propertiesKey, new JSONObject()
|
||||
.put("type", "object")
|
||||
.put("properties", props));
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
|
||||
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
|
||||
@@ -549,7 +585,7 @@ public class SchemaBuilder {
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", new JSONArray(StructureSchemaKeys.collect(
|
||||
INMS.get().getStructureKeys(),
|
||||
IrisPlatforms.get().registries().structureKeys(),
|
||||
Arrays.asList(data.getStructureLoader().getPossibleKeys()),
|
||||
Arrays.asList(data.getJigsawPieceLoader().getPossibleKeys())).toArray(new String[0])));
|
||||
definitions.put(key, j);
|
||||
@@ -565,17 +601,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for (String i : data.getBlockLoader().getPossibleKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
for (String i : BukkitBlockResolution.getBlockTypes()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
j.put("enum", ja);
|
||||
j.put("enum", blockTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -589,7 +615,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", BukkitBlockResolution.getItemTypes());
|
||||
j.put("enum", itemTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -597,6 +623,26 @@ public class SchemaBuilder {
|
||||
items.put("$ref", "#/definitions/" + key);
|
||||
prop.put("items", items);
|
||||
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
|
||||
} else if (k.isAnnotationPresent(RegistryListEntityType.class)) {
|
||||
fancyType = "List of Entity Types";
|
||||
String key = "enum-entity-type";
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
JSONArray ja = new JSONArray();
|
||||
|
||||
for (String i : IrisPlatforms.get().registries().entityKeys()) {
|
||||
ja.put(i);
|
||||
}
|
||||
|
||||
j.put("enum", ja);
|
||||
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 Entity Type (use ctrl+space for auto complete!)");
|
||||
} else if (k.isAnnotationPresent(RegistryListFont.class)) {
|
||||
String key = "enum-font";
|
||||
fancyType = "List of Font Families";
|
||||
@@ -617,7 +663,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", ENCHANT_TYPES);
|
||||
j.put("enum", enchantTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -631,7 +677,7 @@ public class SchemaBuilder {
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
j.put("enum", potionTypes());
|
||||
definitions.put(key, j);
|
||||
}
|
||||
|
||||
@@ -640,9 +686,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 (k.isAnnotationPresent(RegistryListFunction.class)) {
|
||||
var functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||
Class<? extends ListFunction<KList<String>>> functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
|
||||
try {
|
||||
var instance = functionClass.getDeclaredConstructor().newInstance();
|
||||
ListFunction<KList<String>> instance = functionClass.getDeclaredConstructor().newInstance();
|
||||
String key = instance.key();
|
||||
fancyType = instance.fancyName();
|
||||
|
||||
@@ -659,22 +705,8 @@ public class SchemaBuilder {
|
||||
} catch (Throwable e) {
|
||||
IrisLogging.error("Could not execute apply method in " + functionClass.getName());
|
||||
}
|
||||
} else if (t.type().equals(PotionEffectType.class)) {
|
||||
fancyType = "List of Potion Effect Types";
|
||||
String key = "enum-potion-effect-type";
|
||||
|
||||
if (!definitions.containsKey(key)) {
|
||||
JSONObject j = new JSONObject();
|
||||
j.put("enum", POTION_TYPES);
|
||||
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 Potion Effect Type (use ctrl+space for auto complete!)");
|
||||
} else if (KeyedType.isKeyed(t.type())) {
|
||||
fancyType = addEnumList(prop, description, t, KeyedType.values(t.type()), Function.identity());
|
||||
} else if (SchemaKeyedTypes.isKeyed(t.type())) {
|
||||
fancyType = addEnumList(prop, description, t, SchemaKeyedTypes.values(t.type()), Function.identity());
|
||||
} else if (t.type().isEnum()) {
|
||||
fancyType = addEnumList(prop, description, t, t.type().getEnumConstants(), o -> ((Enum<?>) o).name());
|
||||
}
|
||||
@@ -719,7 +751,7 @@ public class SchemaBuilder {
|
||||
if (present) d.add(" ");
|
||||
if (value instanceof List) {
|
||||
d.add(SYMBOL_LIMIT__N + " Default Value is an empty list");
|
||||
} else if (!k.getType().isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(value instanceof Enum<?>) && !KeyedType.isKeyed(k.getType())) {
|
||||
} else if (!k.getType().isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(value instanceof Enum<?>) && !SchemaKeyedTypes.isKeyed(k.getType())) {
|
||||
d.add(SYMBOL_LIMIT__N + " Default Value is a default object (create this object to see default properties)");
|
||||
} else {
|
||||
d.add(SYMBOL_LIMIT__N + " Default Value is " + value);
|
||||
@@ -783,7 +815,7 @@ public class SchemaBuilder {
|
||||
@NotNull
|
||||
private <T> String addEnumList(JSONObject prop, KList<String> description, ArrayType t, T[] values, Function<T, String> function) {
|
||||
JSONObject items = new JSONObject();
|
||||
var s = addEnum(t.type(), items, description, values, function);
|
||||
String s = addEnum(t.type(), items, description, values, function);
|
||||
prop.put("items", items);
|
||||
|
||||
return "List of " + s + "s";
|
||||
@@ -826,6 +858,47 @@ public class SchemaBuilder {
|
||||
return type.getSimpleName().replaceAll("\\QIris\\E", "");
|
||||
}
|
||||
|
||||
private JSONObject buildBlockPropertyJson(PlatformBlockProperty property) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("type", property.jsonType());
|
||||
json.put("default", property.defaultValue());
|
||||
List<Object> allowed = property.allowedValues();
|
||||
if (!allowed.isEmpty()) {
|
||||
json.put("enum", new JSONArray(allowed));
|
||||
}
|
||||
if (property.hasNumericRange()) {
|
||||
PlatformNumericRange range = property.numericRange();
|
||||
if ("integer".equals(property.jsonType())) {
|
||||
json.put("minimum", (long) range.minimum());
|
||||
json.put("maximum", (long) range.maximum());
|
||||
} else {
|
||||
json.put("minimum", range.minimum());
|
||||
json.put("maximum", range.maximum());
|
||||
}
|
||||
json.put("exclusiveMinimum", range.exclusiveMinimum());
|
||||
json.put("exclusiveMaximum", range.exclusiveMaximum());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
private List<BlockStateGroup> reconstructBlockStateGroups() {
|
||||
List<BlockStateGroup> groups = new ArrayList<>();
|
||||
List<PlatformBlockProperty> currentProperties = null;
|
||||
List<String> currentBlocks = null;
|
||||
for (Map.Entry<String, List<PlatformBlockProperty>> entry : IrisPlatforms.get().registries().blockStateProperties().entrySet()) {
|
||||
List<PlatformBlockProperty> value = entry.getValue();
|
||||
if (currentProperties != null && value == currentProperties) {
|
||||
currentBlocks.add(entry.getKey());
|
||||
} else {
|
||||
currentBlocks = new ArrayList<>();
|
||||
currentBlocks.add(entry.getKey());
|
||||
currentProperties = value;
|
||||
groups.add(new BlockStateGroup(currentBlocks, value));
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
private String getType(Class<?> c) {
|
||||
if (c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class) || c.equals(Long.class)) {
|
||||
return "integer";
|
||||
@@ -839,7 +912,7 @@ public class SchemaBuilder {
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
if (c.equals(String.class) || c.isEnum() || KeyedType.isKeyed(c)) {
|
||||
if (c.equals(String.class) || c.isEnum() || SchemaKeyedTypes.isKeyed(c)) {
|
||||
return "string";
|
||||
}
|
||||
|
||||
@@ -864,11 +937,6 @@ public class SchemaBuilder {
|
||||
return r.getDeclaredAnnotation(Desc.class).value();
|
||||
}
|
||||
|
||||
// suppress warnings on bukkit classes
|
||||
if (r.getDeclaringClass().getName().startsWith("org.bukkit.")) {
|
||||
return "Bukkit package classes and enums have no descriptions";
|
||||
}
|
||||
|
||||
warnings.addIfMissing("Missing @Desc on field " + r.getName() + " (" + r.getType() + ") in " + r.getDeclaringClass().getCanonicalName());
|
||||
return "No Field Description";
|
||||
}
|
||||
@@ -883,4 +951,7 @@ public class SchemaBuilder {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private record BlockStateGroup(List<String> blocks, List<PlatformBlockProperty> properties) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.project;
|
||||
|
||||
import art.arcane.iris.util.common.reflect.KeyedType;
|
||||
|
||||
final class SchemaKeyedTypes {
|
||||
private SchemaKeyedTypes() {
|
||||
}
|
||||
|
||||
static boolean isKeyed(Class<?> type) {
|
||||
return KeyedType.isKeyed(type);
|
||||
}
|
||||
|
||||
static String[] values(Class<?> type) {
|
||||
return KeyedType.values(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface EngineResolver {
|
||||
Engine resolve(String sessionId);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
|
||||
public final class IrisCursorResolver {
|
||||
private IrisCursorResolver() {
|
||||
}
|
||||
|
||||
public static IrisMessage.CursorInfo resolve(Engine engine, int blockX, int blockZ) {
|
||||
IrisBiome surfaceBiome = engine.getSurfaceBiome(blockX, blockZ);
|
||||
IrisRegion region = engine.getRegion(blockX, blockZ);
|
||||
IrisBiome caveBiome = engine.getCaveBiome(blockX, blockZ);
|
||||
int height = engine.getHeight(blockX, blockZ);
|
||||
String biomeKey = keyOf(surfaceBiome == null ? null : surfaceBiome.getLoadKey());
|
||||
String regionKey = keyOf(region == null ? null : region.getLoadKey());
|
||||
String caveBiomeKey = keyOf(caveBiome == null ? null : caveBiome.getLoadKey());
|
||||
String dimensionKey = keyOf(engine.getDimension().getLoadKey());
|
||||
return new IrisMessage.CursorInfo(blockX, blockZ, biomeKey, regionKey, caveBiomeKey, height, dimensionKey);
|
||||
}
|
||||
|
||||
private static String keyOf(String value) {
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.spi.protocol.IrisMessageCodec;
|
||||
import art.arcane.iris.spi.protocol.IrisProtocol;
|
||||
import art.arcane.iris.spi.protocol.ProtocolException;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public final class IrisProtocolServer {
|
||||
private final IrisSessionRegistry registry;
|
||||
private final long serverCapabilities;
|
||||
private final String serverBrand;
|
||||
private final boolean irisActive;
|
||||
private final LongSupplier clock;
|
||||
private final AtomicLong droppedBeforeHello;
|
||||
private final AtomicLong rateLimitedFrames;
|
||||
private final AtomicLong rejectedFrames;
|
||||
private final AtomicLong versionMismatches;
|
||||
private final AtomicLong capabilityRejected;
|
||||
private final AtomicLong noEngineDrops;
|
||||
private final AtomicLong cursorInfoServed;
|
||||
private final AtomicLong visionTileForwarded;
|
||||
private final AtomicLong visionRateLimited;
|
||||
private final AtomicLong pregenRegionDeltasBroadcast;
|
||||
private final AtomicLong studioHotloadsBroadcast;
|
||||
private final AtomicLong toastsBroadcast;
|
||||
private final AtomicLong toastsSent;
|
||||
private volatile EngineResolver engineResolver;
|
||||
private volatile VisionTileRequestHandler visionTileHandler;
|
||||
|
||||
public IrisProtocolServer(IrisSessionRegistry registry, long serverCapabilities, String serverBrand, boolean irisActive) {
|
||||
this(registry, serverCapabilities, serverBrand, irisActive, System::currentTimeMillis);
|
||||
}
|
||||
|
||||
IrisProtocolServer(IrisSessionRegistry registry, long serverCapabilities, String serverBrand, boolean irisActive, LongSupplier clock) {
|
||||
this.registry = Objects.requireNonNull(registry, "session registry");
|
||||
this.serverCapabilities = serverCapabilities;
|
||||
this.serverBrand = Objects.requireNonNull(serverBrand, "server brand");
|
||||
this.irisActive = irisActive;
|
||||
this.clock = Objects.requireNonNull(clock, "clock");
|
||||
this.droppedBeforeHello = new AtomicLong(0L);
|
||||
this.rateLimitedFrames = new AtomicLong(0L);
|
||||
this.rejectedFrames = new AtomicLong(0L);
|
||||
this.versionMismatches = new AtomicLong(0L);
|
||||
this.capabilityRejected = new AtomicLong(0L);
|
||||
this.noEngineDrops = new AtomicLong(0L);
|
||||
this.cursorInfoServed = new AtomicLong(0L);
|
||||
this.visionTileForwarded = new AtomicLong(0L);
|
||||
this.visionRateLimited = new AtomicLong(0L);
|
||||
this.pregenRegionDeltasBroadcast = new AtomicLong(0L);
|
||||
this.studioHotloadsBroadcast = new AtomicLong(0L);
|
||||
this.toastsBroadcast = new AtomicLong(0L);
|
||||
this.toastsSent = new AtomicLong(0L);
|
||||
}
|
||||
|
||||
public IrisSessionRegistry registry() {
|
||||
return registry;
|
||||
}
|
||||
|
||||
public void setEngineResolver(EngineResolver engineResolver) {
|
||||
this.engineResolver = engineResolver;
|
||||
}
|
||||
|
||||
public void setVisionTileHandler(VisionTileRequestHandler visionTileHandler) {
|
||||
this.visionTileHandler = visionTileHandler;
|
||||
}
|
||||
|
||||
public void onClientFrame(String sessionId, byte[] frame) {
|
||||
IrisSession session = registry.get(sessionId);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
if (!session.allowInbound(clock.getAsLong())) {
|
||||
rateLimitedFrames.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
IrisMessage message;
|
||||
try {
|
||||
message = IrisMessageCodec.decode(frame);
|
||||
} catch (ProtocolException rejected) {
|
||||
rejectedFrames.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
dispatch(session, message);
|
||||
}
|
||||
|
||||
public void broadcastPregenProgress(long jobId, long chunksDone, long chunksTotal, double chunksPerSecond, long etaMillis, int state) {
|
||||
if (registry.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
byte[] frame = null;
|
||||
for (IrisSession session : registry.all()) {
|
||||
if (!session.isReady() || !session.hasCapability(IrisProtocol.CAPABILITY_PREGEN)) {
|
||||
continue;
|
||||
}
|
||||
if (frame == null) {
|
||||
frame = IrisMessageCodec.encode(new IrisMessage.PregenProgress(jobId, chunksDone, chunksTotal, chunksPerSecond, etaMillis, state));
|
||||
}
|
||||
session.sendRaw(frame);
|
||||
}
|
||||
}
|
||||
|
||||
public void pregenEnd(long jobId, boolean completed) {
|
||||
if (registry.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
byte[] frame = null;
|
||||
for (IrisSession session : registry.all()) {
|
||||
if (!session.isReady() || !session.hasCapability(IrisProtocol.CAPABILITY_PREGEN)) {
|
||||
continue;
|
||||
}
|
||||
if (frame == null) {
|
||||
frame = IrisMessageCodec.encode(new IrisMessage.PregenEnd(jobId, completed));
|
||||
}
|
||||
session.sendRaw(frame);
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastDimensionStatus(String dimensionKey, String packKey, long seed, int minY, int maxY, boolean irisWorld) {
|
||||
if (registry.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
byte[] frame = null;
|
||||
for (IrisSession session : registry.all()) {
|
||||
if (!session.isReady()) {
|
||||
continue;
|
||||
}
|
||||
if (frame == null) {
|
||||
frame = IrisMessageCodec.encode(new IrisMessage.DimensionStatus(dimensionKey, packKey, seed, minY, maxY, irisWorld));
|
||||
}
|
||||
session.sendRaw(frame);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendDimensionStatus(String sessionId, String dimensionKey, String packKey, long seed, int minY, int maxY, boolean irisWorld) {
|
||||
IrisSession session = registry.get(sessionId);
|
||||
if (session == null || !session.isReady()) {
|
||||
return;
|
||||
}
|
||||
session.send(new IrisMessage.DimensionStatus(dimensionKey, packKey, seed, minY, maxY, irisWorld));
|
||||
}
|
||||
|
||||
public void broadcastPregenRegionDelta(long jobId, int regionX, int regionZ, int state) {
|
||||
if (registry.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
byte[] frame = null;
|
||||
for (IrisSession session : registry.all()) {
|
||||
if (!session.isReady() || !session.hasCapability(IrisProtocol.CAPABILITY_PREGEN)) {
|
||||
continue;
|
||||
}
|
||||
if (frame == null) {
|
||||
frame = IrisMessageCodec.encode(new IrisMessage.PregenRegionDelta(jobId, regionX, regionZ, state));
|
||||
}
|
||||
session.sendRaw(frame);
|
||||
}
|
||||
if (frame != null) {
|
||||
pregenRegionDeltasBroadcast.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastStudioHotload(String packKey, int changedFiles, boolean failed, String message) {
|
||||
if (registry.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
byte[] frame = null;
|
||||
for (IrisSession session : registry.all()) {
|
||||
if (!session.isReady() || !session.hasCapability(IrisProtocol.CAPABILITY_STUDIO)) {
|
||||
continue;
|
||||
}
|
||||
if (frame == null) {
|
||||
frame = IrisMessageCodec.encode(new IrisMessage.StudioHotload(packKey, changedFiles, failed, message));
|
||||
}
|
||||
session.sendRaw(frame);
|
||||
}
|
||||
if (frame != null) {
|
||||
studioHotloadsBroadcast.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastToast(int kind, String title, String body) {
|
||||
if (registry.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
byte[] frame = null;
|
||||
for (IrisSession session : registry.all()) {
|
||||
if (!session.isReady() || !session.hasCapability(IrisProtocol.CAPABILITY_STUDIO)) {
|
||||
continue;
|
||||
}
|
||||
if (frame == null) {
|
||||
frame = IrisMessageCodec.encode(new IrisMessage.Toast(kind, title, body));
|
||||
}
|
||||
session.sendRaw(frame);
|
||||
}
|
||||
if (frame != null) {
|
||||
toastsBroadcast.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToast(String sessionId, int kind, String title, String body) {
|
||||
IrisSession session = registry.get(sessionId);
|
||||
if (session == null || !session.isReady() || !session.hasCapability(IrisProtocol.CAPABILITY_STUDIO)) {
|
||||
return;
|
||||
}
|
||||
session.send(new IrisMessage.Toast(kind, title, body));
|
||||
toastsSent.incrementAndGet();
|
||||
}
|
||||
|
||||
public long droppedBeforeHelloCount() {
|
||||
return droppedBeforeHello.get();
|
||||
}
|
||||
|
||||
public long rateLimitedFrameCount() {
|
||||
return rateLimitedFrames.get();
|
||||
}
|
||||
|
||||
public long rejectedFrameCount() {
|
||||
return rejectedFrames.get();
|
||||
}
|
||||
|
||||
public long versionMismatchCount() {
|
||||
return versionMismatches.get();
|
||||
}
|
||||
|
||||
public long capabilityRejectedCount() {
|
||||
return capabilityRejected.get();
|
||||
}
|
||||
|
||||
public long noEngineDropCount() {
|
||||
return noEngineDrops.get();
|
||||
}
|
||||
|
||||
public long cursorInfoServedCount() {
|
||||
return cursorInfoServed.get();
|
||||
}
|
||||
|
||||
public long visionTileForwardedCount() {
|
||||
return visionTileForwarded.get();
|
||||
}
|
||||
|
||||
public long visionRateLimitedCount() {
|
||||
return visionRateLimited.get();
|
||||
}
|
||||
|
||||
public long pregenRegionDeltasBroadcastCount() {
|
||||
return pregenRegionDeltasBroadcast.get();
|
||||
}
|
||||
|
||||
public long studioHotloadsBroadcastCount() {
|
||||
return studioHotloadsBroadcast.get();
|
||||
}
|
||||
|
||||
public long toastsBroadcastCount() {
|
||||
return toastsBroadcast.get();
|
||||
}
|
||||
|
||||
public long toastsSentCount() {
|
||||
return toastsSent.get();
|
||||
}
|
||||
|
||||
private void dispatch(IrisSession session, IrisMessage message) {
|
||||
if (session.state() == IrisSession.State.AWAITING_HELLO) {
|
||||
if (message instanceof IrisMessage.ClientHello clientHello) {
|
||||
onClientHello(session, clientHello);
|
||||
return;
|
||||
}
|
||||
droppedBeforeHello.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
switch (message) {
|
||||
case IrisMessage.CursorInfoRequest cursorInfoRequest -> onCursorInfoRequest(session, cursorInfoRequest);
|
||||
case IrisMessage.VisionTileRequest visionTileRequest -> onVisionTileRequest(session, visionTileRequest);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onClientHello(IrisSession session, IrisMessage.ClientHello clientHello) {
|
||||
if (clientHello.protocolVersion() != IrisProtocol.PROTOCOL_VERSION) {
|
||||
versionMismatches.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
session.markReady(clientHello.protocolVersion(), clientHello.capabilities());
|
||||
session.send(new IrisMessage.ServerHello(IrisProtocol.PROTOCOL_VERSION, serverCapabilities, serverBrand, irisActive));
|
||||
}
|
||||
|
||||
private void onCursorInfoRequest(IrisSession session, IrisMessage.CursorInfoRequest request) {
|
||||
if (!session.hasCapability(IrisProtocol.CAPABILITY_CURSOR)) {
|
||||
capabilityRejected.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
EngineResolver resolver = engineResolver;
|
||||
if (resolver == null) {
|
||||
noEngineDrops.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
Engine engine = resolver.resolve(session.id());
|
||||
if (engine == null) {
|
||||
noEngineDrops.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
session.send(IrisCursorResolver.resolve(engine, request.blockX(), request.blockZ()));
|
||||
cursorInfoServed.incrementAndGet();
|
||||
}
|
||||
|
||||
private void onVisionTileRequest(IrisSession session, IrisMessage.VisionTileRequest request) {
|
||||
if (!session.hasCapability(IrisProtocol.CAPABILITY_VISION)) {
|
||||
capabilityRejected.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
if (!session.allowVisionTile(clock.getAsLong())) {
|
||||
visionRateLimited.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
VisionTileRequestHandler handler = visionTileHandler;
|
||||
if (handler == null) {
|
||||
noEngineDrops.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
handler.handle(session.id(), request.tileX(), request.tileZ(), request.zoomLevel());
|
||||
visionTileForwarded.incrementAndGet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
public interface IrisServerTransport {
|
||||
void sendToClient(String sessionId, byte[] frame);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.spi.protocol.IrisMessageCodec;
|
||||
import art.arcane.iris.spi.protocol.IrisProtocol;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class IrisSession {
|
||||
private final String id;
|
||||
private final IrisServerTransport transport;
|
||||
private volatile State state;
|
||||
private volatile long capabilities;
|
||||
private volatile int remoteProtocolVersion;
|
||||
private long inboundWindowStartMillis;
|
||||
private int inboundFramesInWindow;
|
||||
private long visionTileWindowStartMillis;
|
||||
private int visionTileRequestsInWindow;
|
||||
|
||||
public IrisSession(String id, IrisServerTransport transport) {
|
||||
this.id = Objects.requireNonNull(id, "session id");
|
||||
this.transport = Objects.requireNonNull(transport, "session transport");
|
||||
this.state = State.AWAITING_HELLO;
|
||||
this.capabilities = 0L;
|
||||
this.remoteProtocolVersion = 0;
|
||||
this.inboundWindowStartMillis = 0L;
|
||||
this.inboundFramesInWindow = 0;
|
||||
this.visionTileWindowStartMillis = 0L;
|
||||
this.visionTileRequestsInWindow = 0;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public State state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public long capabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
public int remoteProtocolVersion() {
|
||||
return remoteProtocolVersion;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return state == State.READY;
|
||||
}
|
||||
|
||||
public boolean hasCapability(long capabilityMask) {
|
||||
return (capabilities & capabilityMask) != 0L;
|
||||
}
|
||||
|
||||
public void markReady(int protocolVersion, long negotiatedCapabilities) {
|
||||
this.remoteProtocolVersion = protocolVersion;
|
||||
this.capabilities = negotiatedCapabilities;
|
||||
this.state = State.READY;
|
||||
}
|
||||
|
||||
public synchronized boolean allowInbound(long nowMillis) {
|
||||
if (nowMillis - inboundWindowStartMillis >= 1000L) {
|
||||
inboundWindowStartMillis = nowMillis;
|
||||
inboundFramesInWindow = 0;
|
||||
}
|
||||
if (inboundFramesInWindow >= IrisProtocol.MAX_INBOUND_FRAMES_PER_SECOND) {
|
||||
return false;
|
||||
}
|
||||
inboundFramesInWindow++;
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized boolean allowVisionTile(long nowMillis) {
|
||||
if (nowMillis - visionTileWindowStartMillis >= 1000L) {
|
||||
visionTileWindowStartMillis = nowMillis;
|
||||
visionTileRequestsInWindow = 0;
|
||||
}
|
||||
if (visionTileRequestsInWindow >= IrisProtocol.MAX_VISION_TILE_REQUESTS_PER_SECOND) {
|
||||
return false;
|
||||
}
|
||||
visionTileRequestsInWindow++;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void send(IrisMessage message) {
|
||||
sendRaw(IrisMessageCodec.encode(message));
|
||||
}
|
||||
|
||||
public void sendRaw(byte[] frame) {
|
||||
transport.sendToClient(id, frame);
|
||||
}
|
||||
|
||||
public enum State {
|
||||
AWAITING_HELLO,
|
||||
READY
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class IrisSessionRegistry {
|
||||
private final ConcurrentHashMap<String, IrisSession> sessions;
|
||||
|
||||
public IrisSessionRegistry() {
|
||||
this.sessions = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public void register(IrisSession session) {
|
||||
sessions.put(session.id(), session);
|
||||
}
|
||||
|
||||
public IrisSession unregister(String sessionId) {
|
||||
return sessions.remove(sessionId);
|
||||
}
|
||||
|
||||
public IrisSession get(String sessionId) {
|
||||
return sessions.get(sessionId);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return sessions.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return sessions.size();
|
||||
}
|
||||
|
||||
public Iterable<IrisSession> all() {
|
||||
return sessions.values();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.render.IrisRenderer;
|
||||
import art.arcane.iris.engine.framework.render.RenderType;
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.spi.protocol.IrisProtocol;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
public final class IrisTileEncoder {
|
||||
public static final int TILE_PIXELS = 128;
|
||||
public static final int MAX_ZOOM_LEVEL = 8;
|
||||
public static final int MODE_RAW_RGB = 0;
|
||||
public static final int MODE_PALETTE = 1;
|
||||
private static final int MAX_PALETTE_COLORS = 256;
|
||||
private static final int RGB_MASK = 0xFFFFFF;
|
||||
|
||||
private IrisTileEncoder() {
|
||||
}
|
||||
|
||||
public static List<IrisMessage.VisionTile> encode(Engine engine, int tileX, int tileZ, int zoomLevel, int sequence) {
|
||||
int zoom = clampZoom(zoomLevel);
|
||||
int blocksPerPixel = 1 << zoom;
|
||||
double size = (double) TILE_PIXELS * blocksPerPixel;
|
||||
double sx = (double) tileX * size;
|
||||
double sz = (double) tileZ * size;
|
||||
BufferedImage image = new IrisRenderer(engine).render(sx, sz, size, TILE_PIXELS, RenderType.BIOME);
|
||||
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
|
||||
byte[] blob = encodePixels(pixels, TILE_PIXELS, TILE_PIXELS);
|
||||
return splitIntoChunks(blob, tileX, tileZ, zoom, sequence);
|
||||
}
|
||||
|
||||
public static byte[] encodePixels(int[] pixels, int width, int height) {
|
||||
Map<Integer, Integer> palette = buildPalette(pixels);
|
||||
ByteArrayOutputStream raw = new ByteArrayOutputStream(pixels.length);
|
||||
try (DataOutputStream out = new DataOutputStream(raw)) {
|
||||
out.writeInt(width);
|
||||
out.writeInt(height);
|
||||
if (palette != null) {
|
||||
out.writeByte(MODE_PALETTE);
|
||||
out.writeInt(palette.size());
|
||||
for (Integer color : palette.keySet()) {
|
||||
out.writeByte(color >> 16 & 0xFF);
|
||||
out.writeByte(color >> 8 & 0xFF);
|
||||
out.writeByte(color & 0xFF);
|
||||
}
|
||||
for (int pixel : pixels) {
|
||||
out.writeByte(palette.get(pixel & RGB_MASK));
|
||||
}
|
||||
} else {
|
||||
out.writeByte(MODE_RAW_RGB);
|
||||
for (int pixel : pixels) {
|
||||
out.writeByte(pixel >> 16 & 0xFF);
|
||||
out.writeByte(pixel >> 8 & 0xFF);
|
||||
out.writeByte(pixel & 0xFF);
|
||||
}
|
||||
}
|
||||
} catch (IOException failure) {
|
||||
throw new UncheckedIOException("vision tile pixel encode failed", failure);
|
||||
}
|
||||
return deflate(raw.toByteArray());
|
||||
}
|
||||
|
||||
public static List<IrisMessage.VisionTile> splitIntoChunks(byte[] blob, int tileX, int tileZ, int zoomLevel, int sequence) {
|
||||
int chunkBytes = IrisProtocol.VISION_TILE_MAX_CHUNK_BYTES;
|
||||
int chunkCount = Math.max(1, (blob.length + chunkBytes - 1) / chunkBytes);
|
||||
List<IrisMessage.VisionTile> chunks = new ArrayList<>(chunkCount);
|
||||
for (int index = 0; index < chunkCount; index++) {
|
||||
int start = index * chunkBytes;
|
||||
int end = Math.min(start + chunkBytes, blob.length);
|
||||
byte[] slice = new byte[end - start];
|
||||
System.arraycopy(blob, start, slice, 0, slice.length);
|
||||
chunks.add(new IrisMessage.VisionTile(tileX, tileZ, zoomLevel, sequence, index, chunkCount, slice));
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
private static Map<Integer, Integer> buildPalette(int[] pixels) {
|
||||
LinkedHashMap<Integer, Integer> palette = new LinkedHashMap<>();
|
||||
for (int pixel : pixels) {
|
||||
int color = pixel & RGB_MASK;
|
||||
if (!palette.containsKey(color)) {
|
||||
if (palette.size() >= MAX_PALETTE_COLORS) {
|
||||
return null;
|
||||
}
|
||||
palette.put(color, palette.size());
|
||||
}
|
||||
}
|
||||
return palette;
|
||||
}
|
||||
|
||||
private static byte[] deflate(byte[] input) {
|
||||
Deflater deflater = new Deflater(Deflater.BEST_SPEED);
|
||||
deflater.setInput(input);
|
||||
deflater.finish();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(64, input.length / 2));
|
||||
byte[] buffer = new byte[8192];
|
||||
while (!deflater.finished()) {
|
||||
int produced = deflater.deflate(buffer);
|
||||
out.write(buffer, 0, produced);
|
||||
}
|
||||
deflater.end();
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private static int clampZoom(int zoomLevel) {
|
||||
return Math.max(0, Math.min(zoomLevel, MAX_ZOOM_LEVEL));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.PreservationRegistry;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.spi.protocol.IrisProtocol;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public final class IrisVisionRequestService implements VisionTileRequestHandler {
|
||||
private static final int DEFAULT_MAX_PENDING = 64;
|
||||
|
||||
private final EngineResolver engineResolver;
|
||||
private final IrisSessionRegistry registry;
|
||||
private final Executor executor;
|
||||
private final int maxPending;
|
||||
private final ArrayDeque<PendingRequest> pending;
|
||||
private final ConcurrentHashMap<String, Integer> sequences;
|
||||
private final AtomicLong droppedSaturated;
|
||||
private final AtomicLong droppedNoEngine;
|
||||
private final AtomicLong droppedNoSession;
|
||||
private final AtomicLong tilesEncoded;
|
||||
|
||||
IrisVisionRequestService(EngineResolver engineResolver, IrisSessionRegistry registry, Executor executor, int maxPending) {
|
||||
this.engineResolver = Objects.requireNonNull(engineResolver, "engine resolver");
|
||||
this.registry = Objects.requireNonNull(registry, "session registry");
|
||||
this.executor = Objects.requireNonNull(executor, "executor");
|
||||
this.maxPending = Math.max(1, maxPending);
|
||||
this.pending = new ArrayDeque<>();
|
||||
this.sequences = new ConcurrentHashMap<>();
|
||||
this.droppedSaturated = new AtomicLong(0L);
|
||||
this.droppedNoEngine = new AtomicLong(0L);
|
||||
this.droppedNoSession = new AtomicLong(0L);
|
||||
this.tilesEncoded = new AtomicLong(0L);
|
||||
}
|
||||
|
||||
public static IrisVisionRequestService create(EngineResolver engineResolver, IrisSessionRegistry registry) {
|
||||
AtomicInteger threadIndex = new AtomicInteger(0);
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), runnable -> {
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.setName("Iris Vision Tile " + threadIndex.incrementAndGet());
|
||||
thread.setDaemon(true);
|
||||
thread.setPriority(Thread.MIN_PRIORITY);
|
||||
return thread;
|
||||
});
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
PreservationRegistry preservation = IrisServices.getOrNull(PreservationRegistry.class);
|
||||
if (preservation != null) {
|
||||
preservation.register(executor);
|
||||
}
|
||||
return new IrisVisionRequestService(engineResolver, registry, executor, DEFAULT_MAX_PENDING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(String sessionId, int tileX, int tileZ, int zoomLevel) {
|
||||
PendingRequest request = new PendingRequest(sessionId, tileX, tileZ, zoomLevel);
|
||||
synchronized (pending) {
|
||||
while (pending.size() >= maxPending) {
|
||||
pending.pollFirst();
|
||||
droppedSaturated.incrementAndGet();
|
||||
}
|
||||
pending.addLast(request);
|
||||
}
|
||||
executor.execute(this::drainOne);
|
||||
}
|
||||
|
||||
public long droppedSaturatedCount() {
|
||||
return droppedSaturated.get();
|
||||
}
|
||||
|
||||
public long droppedNoEngineCount() {
|
||||
return droppedNoEngine.get();
|
||||
}
|
||||
|
||||
public long droppedNoSessionCount() {
|
||||
return droppedNoSession.get();
|
||||
}
|
||||
|
||||
public long tilesEncodedCount() {
|
||||
return tilesEncoded.get();
|
||||
}
|
||||
|
||||
public int pendingSize() {
|
||||
synchronized (pending) {
|
||||
return pending.size();
|
||||
}
|
||||
}
|
||||
|
||||
private void drainOne() {
|
||||
PendingRequest request;
|
||||
synchronized (pending) {
|
||||
request = pending.pollFirst();
|
||||
}
|
||||
if (request == null) {
|
||||
return;
|
||||
}
|
||||
process(request);
|
||||
}
|
||||
|
||||
private void process(PendingRequest request) {
|
||||
IrisSession session = registry.get(request.sessionId());
|
||||
if (session == null || !session.isReady() || !session.hasCapability(IrisProtocol.CAPABILITY_VISION)) {
|
||||
droppedNoSession.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
Engine engine = engineResolver.resolve(request.sessionId());
|
||||
if (engine == null) {
|
||||
droppedNoEngine.incrementAndGet();
|
||||
return;
|
||||
}
|
||||
int sequence = nextSequence(request);
|
||||
List<IrisMessage.VisionTile> chunks = IrisTileEncoder.encode(engine, request.tileX(), request.tileZ(), request.zoomLevel(), sequence);
|
||||
for (IrisMessage.VisionTile chunk : chunks) {
|
||||
session.send(chunk);
|
||||
}
|
||||
tilesEncoded.incrementAndGet();
|
||||
}
|
||||
|
||||
private int nextSequence(PendingRequest request) {
|
||||
String key = request.sessionId() + ":" + request.tileX() + ":" + request.tileZ() + ":" + request.zoomLevel();
|
||||
return sequences.merge(key, 1, Integer::sum);
|
||||
}
|
||||
|
||||
private record PendingRequest(String sessionId, int tileX, int tileZ, int zoomLevel) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 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 art.arcane.iris.core.protocol;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface VisionTileRequestHandler {
|
||||
void handle(String sessionId, int tileX, int tileZ, int zoomLevel);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package art.arcane.iris.core.safeguard.task;
|
||||
|
||||
import art.arcane.iris.BuildConstants;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.core.IrisWorlds;
|
||||
import art.arcane.iris.core.nms.INMS;
|
||||
@@ -94,7 +95,7 @@ public final class Tasks {
|
||||
} else if (parts.length >= 2) {
|
||||
supportedVersions = parts[1];
|
||||
} else {
|
||||
supportedVersions = "26.2";
|
||||
supportedVersions = BuildConstants.MINECRAFT_VERSION;
|
||||
}
|
||||
|
||||
if (!(INMS.get() instanceof NMSBinding1X)) {
|
||||
|
||||
@@ -21,7 +21,8 @@ package art.arcane.iris.core.service;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.core.link.*;
|
||||
import art.arcane.iris.core.link.ExternalDataProvider;
|
||||
import art.arcane.iris.core.link.Identifier;
|
||||
import art.arcane.iris.core.link.data.DataType;
|
||||
import art.arcane.iris.core.nms.container.BlockProperty;
|
||||
import art.arcane.iris.core.nms.container.Pair;
|
||||
@@ -42,7 +43,11 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -23,7 +23,15 @@ import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IObjectPlacer;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisObjectPlacement;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisTreeModes;
|
||||
import art.arcane.iris.engine.object.IrisTreeSize;
|
||||
import art.arcane.iris.engine.object.TileData;
|
||||
import art.arcane.iris.engine.platform.PlatformChunkGenerator;
|
||||
import art.arcane.iris.platform.bukkit.BukkitBlockState;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
@@ -35,7 +43,12 @@ import art.arcane.volmlib.util.math.BlockPosition;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.common.plugin.IrisService;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.HeightMap;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@@ -2,13 +2,17 @@ package art.arcane.iris.core.tools;
|
||||
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.volmlib.util.data.Varint;
|
||||
import art.arcane.iris.util.common.format.C;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.nbt.io.NBTUtil;
|
||||
import art.arcane.volmlib.util.nbt.io.NamedTag;
|
||||
import art.arcane.volmlib.util.nbt.tag.*;
|
||||
import art.arcane.volmlib.util.nbt.tag.ByteArrayTag;
|
||||
import art.arcane.volmlib.util.nbt.tag.CompoundTag;
|
||||
import art.arcane.volmlib.util.nbt.tag.IntTag;
|
||||
import art.arcane.volmlib.util.nbt.tag.ShortTag;
|
||||
import art.arcane.volmlib.util.nbt.tag.Tag;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
|
||||
@@ -16,8 +20,13 @@ import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -44,7 +44,9 @@ import art.arcane.iris.util.common.scheduling.J;
|
||||
import art.arcane.volmlib.util.scheduling.FoliaScheduler;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
@@ -241,6 +243,7 @@ public class IrisCreator {
|
||||
} catch (Throwable e) {
|
||||
dx.set(true);
|
||||
cancelRepeatingTask(pregenProgressTask);
|
||||
IrisLogging.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -401,6 +404,7 @@ public class IrisCreator {
|
||||
IrisLogging.info("Registered \"" + name + "\" in bukkit.yml");
|
||||
} catch (IOException e) {
|
||||
IrisLogging.error("Failed to update bukkit.yml!");
|
||||
IrisLogging.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
package art.arcane.iris.core.tools;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisWorld;
|
||||
import art.arcane.iris.engine.platform.BukkitChunkGenerator;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
@@ -22,7 +22,14 @@ import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.Cache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.InferredType;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisDecorationPart;
|
||||
import art.arcane.iris.engine.object.IrisDecorator;
|
||||
import art.arcane.iris.engine.object.IrisGenerator;
|
||||
import art.arcane.iris.engine.object.IrisInterpolator;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisShapedGeneratorStyle;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.PlatformBiome;
|
||||
@@ -41,7 +48,13 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "data")
|
||||
|
||||
@@ -18,16 +18,40 @@
|
||||
|
||||
package art.arcane.iris.engine;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineEffects;
|
||||
import art.arcane.iris.engine.framework.EngineMetrics;
|
||||
import art.arcane.iris.engine.framework.EngineMode;
|
||||
import art.arcane.iris.engine.framework.EngineTarget;
|
||||
import art.arcane.iris.engine.framework.EngineWorldManager;
|
||||
import art.arcane.iris.engine.framework.EngineWorldManagerProvider;
|
||||
import art.arcane.iris.engine.framework.GenerationSessionException;
|
||||
import art.arcane.iris.engine.framework.GenerationSessionLease;
|
||||
import art.arcane.iris.engine.framework.GenerationSessionManager;
|
||||
import art.arcane.iris.engine.framework.PreservationRegistry;
|
||||
import art.arcane.iris.engine.framework.SeedManager;
|
||||
import art.arcane.iris.engine.framework.WrongEngineBroException;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisBiomePaletteLayer;
|
||||
import art.arcane.iris.engine.object.IrisDecorator;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisDimensionMode;
|
||||
import art.arcane.iris.engine.object.IrisDimensionModeType;
|
||||
import art.arcane.iris.engine.object.IrisEngineData;
|
||||
import art.arcane.iris.engine.object.IrisObjectPlacement;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import com.google.common.util.concurrent.AtomicDouble;
|
||||
import com.google.gson.Gson;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.core.ServerConfigurator;
|
||||
import art.arcane.iris.core.events.IrisEngineHotloadEvent;
|
||||
import art.arcane.iris.core.datapack.DatapackIngestService;
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.protocol.IrisProtocolServer;
|
||||
import art.arcane.iris.core.loader.ResourceLoader;
|
||||
import art.arcane.iris.core.nms.container.BlockPos;
|
||||
import art.arcane.iris.core.nms.container.Pair;
|
||||
@@ -35,9 +59,7 @@ import art.arcane.iris.core.project.IrisProject;
|
||||
import art.arcane.iris.core.structure.StructureIndexService;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.framework.*;
|
||||
import art.arcane.iris.engine.mantle.EngineMantle;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.util.common.data.B;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
import art.arcane.iris.spi.PlatformBiome;
|
||||
@@ -264,6 +286,7 @@ public class IrisEngine implements Engine {
|
||||
J.a(() -> DatapackIngestService.refreshWorkspace(getData()));
|
||||
} catch (Throwable e) {
|
||||
IrisLogging.error("FAILED TO SETUP ENGINE!");
|
||||
IrisLogging.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -403,20 +426,40 @@ public class IrisEngine implements Engine {
|
||||
}
|
||||
|
||||
public void hotloadSilently() {
|
||||
getData().dump();
|
||||
getData().clearLists();
|
||||
getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey()));
|
||||
prehotload();
|
||||
setupEngine();
|
||||
if (getWorld().hasRealWorld()) {
|
||||
J.a(() -> {
|
||||
synchronized (ServerConfigurator.class) {
|
||||
ServerConfigurator.installDataPacks(false);
|
||||
}
|
||||
});
|
||||
try {
|
||||
getData().dump();
|
||||
getData().clearLists();
|
||||
getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey()));
|
||||
prehotload();
|
||||
setupEngine();
|
||||
if (getWorld().hasRealWorld()) {
|
||||
J.a(() -> {
|
||||
synchronized (ServerConfigurator.class) {
|
||||
ServerConfigurator.installDataPacks(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
broadcastStudioHotload(false, "");
|
||||
} catch (RuntimeException | Error e) {
|
||||
broadcastStudioHotload(true, e.getClass().getSimpleName() + ": " + e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastStudioHotload(boolean failed, String message) {
|
||||
IrisProtocolServer protocolServer = IrisServices.getOrNull(IrisProtocolServer.class);
|
||||
if (protocolServer == null) {
|
||||
return;
|
||||
}
|
||||
IrisDimension dimension = getDimension();
|
||||
String packKey = dimension == null ? "" : dimension.getLoadKey();
|
||||
protocolServer.broadcastStudioHotload(packKey, 0, failed, message);
|
||||
protocolServer.broadcastToast(
|
||||
failed ? IrisMessage.Toast.KIND_ERROR : IrisMessage.Toast.KIND_SUCCESS,
|
||||
"Studio Hotload",
|
||||
failed ? packKey + " failed" : packKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisEngineData getEngineData() {
|
||||
return engineData.aquire(() -> {
|
||||
@@ -431,6 +474,7 @@ public class IrisEngine implements Engine {
|
||||
IrisLogging.error("Failed to read Engine Data! Corrupted File? recreating...");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
IrisLogging.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -448,6 +492,7 @@ public class IrisEngine implements Engine {
|
||||
try {
|
||||
IO.writeAll(f, new Gson().toJson(data));
|
||||
} catch (IOException e) {
|
||||
IrisLogging.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
@@ -724,6 +769,7 @@ public class IrisEngine implements Engine {
|
||||
IrisLogging.debug("Saved Engine Data");
|
||||
} catch (IOException e) {
|
||||
IrisLogging.error("Failed to save Engine Data");
|
||||
IrisLogging.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -755,6 +801,7 @@ public class IrisEngine implements Engine {
|
||||
public void fail(String error, Throwable e) {
|
||||
failing = true;
|
||||
IrisLogging.error(error);
|
||||
IrisLogging.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,11 @@ import art.arcane.volmlib.util.matter.MatterSlice;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.util.common.parallel.HyperLock;
|
||||
import art.arcane.iris.util.common.parallel.MultiBurst;
|
||||
import lombok.*;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -26,7 +26,14 @@ import art.arcane.iris.engine.data.cache.Cache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineAssignedWorldManager;
|
||||
import art.arcane.iris.engine.platform.EngineBukkitOps;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IRare;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisBlockDrops;
|
||||
import art.arcane.iris.engine.object.IrisEntitySpawn;
|
||||
import art.arcane.iris.engine.object.IrisMarker;
|
||||
import art.arcane.iris.engine.object.IrisPosition;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisSpawner;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
@@ -63,7 +70,14 @@ import org.bukkit.inventory.ItemStack;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -145,7 +159,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
engine.getEngineData().cleanup(getEngine());
|
||||
}
|
||||
|
||||
if (!IrisSettings.get().getWorld().isMarkerEntitySpawningSystem() && !IrisSettings.get().getWorld().isAnbientEntitySpawningSystem()) {
|
||||
if (!IrisSettings.get().getWorld().isMarkerEntitySpawningSystem() && !IrisSettings.get().getWorld().isAmbientEntitySpawningSystem()) {
|
||||
return 3000;
|
||||
}
|
||||
|
||||
@@ -576,7 +590,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
});
|
||||
}
|
||||
|
||||
if (!IrisSettings.get().getWorld().isAnbientEntitySpawningSystem()) {
|
||||
if (!IrisSettings.get().getWorld().isAmbientEntitySpawningSystem()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1018,6 +1032,9 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
public void close() {
|
||||
super.close();
|
||||
looper.interrupt();
|
||||
if (cleanupService != null) {
|
||||
cleanupService.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,7 +2,13 @@ package art.arcane.iris.engine;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.InferredType;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisGenerator;
|
||||
import art.arcane.iris.engine.object.IrisInterpolator;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisShapedGeneratorStyle;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.iris.util.common.data.DataProvider;
|
||||
@@ -13,7 +19,12 @@ import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.iris.util.project.stream.ProceduralStream;
|
||||
import art.arcane.iris.util.project.stream.interpolation.Interpolated;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class UpperDimensionContext implements DataProvider {
|
||||
private static final NoiseBounds ZERO_NOISE_BOUNDS = new NoiseBounds(0D, 0D);
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.actuator;
|
||||
|
||||
import art.arcane.iris.engine.decorator.*;
|
||||
import art.arcane.iris.engine.decorator.IrisCeilingDecorator;
|
||||
import art.arcane.iris.engine.decorator.IrisSeaFloorDecorator;
|
||||
import art.arcane.iris.engine.decorator.IrisSeaSurfaceDecorator;
|
||||
import art.arcane.iris.engine.decorator.IrisShoreLineDecorator;
|
||||
import art.arcane.iris.engine.decorator.IrisSurfaceDecorator;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineAssignedActuator;
|
||||
import art.arcane.iris.engine.framework.EngineDecorator;
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
package art.arcane.iris.engine.data.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
public interface Deserializer<T> {
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
package art.arcane.iris.engine.data.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface Serializer<T> {
|
||||
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
|
||||
package art.arcane.iris.engine.data.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
public interface StringDeserializer<T> extends Deserializer<T> {
|
||||
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
|
||||
package art.arcane.iris.engine.data.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
public interface StringSerializer<T> extends Serializer<T> {
|
||||
|
||||
|
||||
@@ -32,7 +32,19 @@ import art.arcane.iris.engine.IrisComplex;
|
||||
import art.arcane.iris.engine.UpperDimensionContext;
|
||||
import art.arcane.iris.engine.data.chunk.TerrainChunk;
|
||||
import art.arcane.iris.engine.mantle.EngineMantle;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisColor;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisDimensionCarvingEntry;
|
||||
import art.arcane.iris.engine.object.IrisDimensionCarvingResolver;
|
||||
import art.arcane.iris.engine.object.IrisEngineData;
|
||||
import art.arcane.iris.engine.object.IrisLootMode;
|
||||
import art.arcane.iris.engine.object.IrisLootReference;
|
||||
import art.arcane.iris.engine.object.IrisLootTable;
|
||||
import art.arcane.iris.engine.object.IrisObjectPlacement;
|
||||
import art.arcane.iris.engine.object.IrisPosition;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisWorld;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.PlatformBiome;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
|
||||
+1
-27
@@ -23,7 +23,7 @@ import art.arcane.iris.core.events.IrisEngineHotloadEvent;
|
||||
import art.arcane.iris.util.common.format.C;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
@@ -60,32 +60,6 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
|
||||
}
|
||||
}
|
||||
|
||||
// @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
// public void on(PlayerTeleportEvent e) {
|
||||
// if(ignoreTP.get()) {
|
||||
// System.out.println("IgTP1");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(!PaperLib.isPaper() || e.getTo() == null) {
|
||||
// System.out.println("IgTP2");
|
||||
//
|
||||
//// return;
|
||||
// }
|
||||
//
|
||||
//// try {
|
||||
//// System.out.println("IgTP3");
|
||||
////
|
||||
//// if(e.getTo().getWorld().equals(getTarget().getWorld().realWorld())) {
|
||||
//// System.out.println("IgTP4");
|
||||
////
|
||||
//// getEngine().getWorldManager().teleportAsync(e);
|
||||
//// }
|
||||
//// } catch(Throwable ex) {
|
||||
////
|
||||
//// }
|
||||
// }
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldSaveEvent e) {
|
||||
if (e.getWorld().equals(getTarget().getWorld().realWorld())) {
|
||||
|
||||
@@ -18,9 +18,13 @@
|
||||
|
||||
package art.arcane.iris.engine.framework;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public interface PreservationRegistry {
|
||||
void register(Thread thread);
|
||||
|
||||
void register(ExecutorService service);
|
||||
|
||||
void registerCache(MeteredCache cache);
|
||||
|
||||
void dereference();
|
||||
|
||||
@@ -23,7 +23,7 @@ import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisBiomeGeneratorLink;
|
||||
import art.arcane.iris.util.project.interpolation.IrisInterpolation;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
package art.arcane.iris.engine.framework.render;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Renderer {
|
||||
|
||||
@@ -51,7 +51,10 @@ import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.iris.util.common.data.B;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static art.arcane.iris.engine.mantle.EngineMantle.AIR;
|
||||
|
||||
|
||||
+19
-1
@@ -30,7 +30,25 @@ import art.arcane.iris.engine.mantle.IrisMantleComponent;
|
||||
import art.arcane.iris.engine.mantle.MantleWriter;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.CarvingMode;
|
||||
import art.arcane.iris.engine.object.DecayControlPlacer;
|
||||
import art.arcane.iris.engine.object.IObjectPlacer;
|
||||
import art.arcane.iris.engine.object.IrisAxisRotationClamp;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisCaveAnchorMode;
|
||||
import art.arcane.iris.engine.object.IrisCaveProfile;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisObjectPlacement;
|
||||
import art.arcane.iris.engine.object.IrisObjectRotation;
|
||||
import art.arcane.iris.engine.object.IrisObjectScale;
|
||||
import art.arcane.iris.engine.object.IrisObjectTranslate;
|
||||
import art.arcane.iris.engine.object.IrisObjectVacuum;
|
||||
import art.arcane.iris.engine.object.IrisProceduralObjects;
|
||||
import art.arcane.iris.engine.object.IrisProceduralPlacement;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.ObjectPlaceMode;
|
||||
import art.arcane.iris.engine.object.TileData;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
|
||||
@@ -26,7 +26,12 @@ import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineMode;
|
||||
import art.arcane.iris.engine.framework.EngineStage;
|
||||
import art.arcane.iris.engine.framework.IrisEngineMode;
|
||||
import art.arcane.iris.engine.modifier.*;
|
||||
import art.arcane.iris.engine.modifier.IrisCarveModifier;
|
||||
import art.arcane.iris.engine.modifier.IrisCustomModifier;
|
||||
import art.arcane.iris.engine.modifier.IrisDepositModifier;
|
||||
import art.arcane.iris.engine.modifier.IrisFloatingChildBiomeModifier;
|
||||
import art.arcane.iris.engine.modifier.IrisPerfectionModifier;
|
||||
import art.arcane.iris.engine.modifier.IrisPostModifier;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
|
||||
|
||||
@@ -20,7 +20,13 @@ package art.arcane.iris.engine.modifier;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineAssignedModifier;
|
||||
import art.arcane.iris.engine.object.*;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisDepositGenerator;
|
||||
import art.arcane.iris.engine.object.IrisDepositVariant;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisObject;
|
||||
import art.arcane.iris.engine.object.IrisProceduralBlocks;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.util.project.context.ChunkContext;
|
||||
import art.arcane.volmlib.util.data.HeightMap;
|
||||
import art.arcane.iris.util.project.hunk.Hunk;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -24,7 +24,13 @@ import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.engine.IrisComplex;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
@@ -46,7 +52,7 @@ import art.arcane.iris.spi.PlatformBlockState;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.util.EnumMap;
|
||||
|
||||
@Accessors(chain = true)
|
||||
|
||||
@@ -19,7 +19,13 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
@@ -30,7 +36,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.util.Locale;
|
||||
|
||||
@Snippet("custom-biome")
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.util.common.data.registry.RegistryUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.util.common.data.registry.RegistryUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -19,10 +19,18 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.util.common.data.DataProvider;
|
||||
import art.arcane.iris.util.project.interpolation.IrisInterpolation;
|
||||
import lombok.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Snippet("generator-layer")
|
||||
|
||||
@@ -20,7 +20,13 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.project.noise.CNG;
|
||||
|
||||
@@ -23,7 +23,12 @@ import art.arcane.iris.core.link.Identifier;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListBlockType;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryMapBlockState;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
|
||||
@@ -2,7 +2,11 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.util.common.math.IrisBlockVector;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.collection.KSet;
|
||||
import art.arcane.volmlib.util.math.M;
|
||||
|
||||
@@ -28,7 +28,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
|
||||
@Snippet("color")
|
||||
@Accessors(chain = true)
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.platform.bukkit.BukkitWorld;
|
||||
import art.arcane.iris.spi.PlatformWorld;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
|
||||
@@ -20,7 +20,13 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
|
||||
@@ -21,7 +21,12 @@ package art.arcane.iris.engine.object;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.util.common.math.IrisBlockVector;
|
||||
import art.arcane.iris.util.common.math.Vector3i;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
|
||||
@@ -28,7 +28,13 @@ import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer;
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer.Dimension;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListFunction;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.functions.ComponentFlagFunction;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.collection.KSet;
|
||||
@@ -48,7 +54,8 @@ import lombok.experimental.Accessors;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -3,10 +3,17 @@ package art.arcane.iris.engine.object;
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer;
|
||||
import art.arcane.volmlib.util.data.Varint;
|
||||
import art.arcane.volmlib.util.io.IO;
|
||||
import lombok.*;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import static art.arcane.iris.engine.object.IrisDimensionTypeOptions.TriState.DEFAULT;
|
||||
import static art.arcane.iris.engine.object.IrisDimensionTypeOptions.TriState.FALSE;
|
||||
import static art.arcane.iris.engine.object.IrisDimensionTypeOptions.TriState.TRUE;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.volmlib.util.data.Varint;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -14,7 +19,6 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static art.arcane.iris.engine.object.IrisDimensionTypeOptions.TriState.*;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
|
||||
@@ -20,7 +20,13 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.DependsOn;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListPotionEffect;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.volmlib.util.scheduling.ChronoLatch;
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListEnchantment;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@@ -25,8 +25,13 @@ import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.core.service.ExternalDataSVC;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.platform.EngineBukkitOps;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListEntityType;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListSpecialEntity;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.util.common.data.registry.RegistryUtil;
|
||||
import art.arcane.iris.platform.bukkit.BukkitWorld;
|
||||
import art.arcane.iris.spi.PlatformWorld;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
@@ -42,9 +47,18 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.attribute.Attributable;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.entity.Panda;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.entity.Panda.Gene;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@@ -55,6 +69,7 @@ import org.bukkit.loot.Lootable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -71,11 +86,12 @@ import static art.arcane.iris.util.common.data.registry.Particles.ITEM;
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IrisEntity extends IrisRegistrant {
|
||||
@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 = null;
|
||||
@RegistryListEntityType
|
||||
@Desc("The namespaced key of the entity type to spawn, such as minecraft:zombie or alexsmobs:grizzly_bear. To spawn a mob from another plugin or provider, set this type to unknown and define the special type.")
|
||||
private String type = null;
|
||||
|
||||
@Desc("The SpawnReason to spawn the entity with.")
|
||||
private CreatureSpawnEvent.SpawnReason reason = null;
|
||||
@Desc("The SpawnReason name to spawn the entity with, such as NATURAL or COMMAND.")
|
||||
private String reason = null;
|
||||
|
||||
@Desc("The custom name of this entity")
|
||||
private String customName = "";
|
||||
@@ -145,11 +161,11 @@ public class IrisEntity extends IrisRegistrant {
|
||||
@Desc("Simply moves the entity from below the surface slowly out of the ground as a spawn-in effect")
|
||||
private boolean spawnEffectRiseOutOfGround = false;
|
||||
|
||||
@Desc("The main gene for a panda if the entity type is a panda")
|
||||
private Gene pandaMainGene = null;
|
||||
@Desc("The main gene for a panda if the entity type is a panda. One of NORMAL, LAZY, WORRIED, PLAYFUL, BROWN, WEAK or AGGRESSIVE.")
|
||||
private String pandaMainGene = null;
|
||||
|
||||
@Desc("The hidden gene for a panda if the entity type is a panda")
|
||||
private Gene pandaHiddenGene = null;
|
||||
@Desc("The hidden gene for a panda if the entity type is a panda. One of NORMAL, LAZY, WORRIED, PLAYFUL, BROWN, WEAK or AGGRESSIVE.")
|
||||
private String pandaHiddenGene = null;
|
||||
|
||||
@Desc("The this entity is ageable, set it's baby status")
|
||||
private boolean baby = false;
|
||||
@@ -171,20 +187,51 @@ public class IrisEntity extends IrisRegistrant {
|
||||
@Desc("Run raw commands when this entity is spawned. Use {x}, {y}, and {z} for location. /summon pig {x} {y} {z}")
|
||||
private KList<IrisCommand> rawCommands = new KList<>();
|
||||
|
||||
public EntityType getType() {
|
||||
return type == null ? EntityType.UNKNOWN : type;
|
||||
public EntityType getBukkitType() {
|
||||
if (type == null || type.isBlank()) {
|
||||
return EntityType.UNKNOWN;
|
||||
}
|
||||
|
||||
NamespacedKey key = NamespacedKey.fromString(type.trim().toLowerCase(Locale.ROOT));
|
||||
|
||||
if (key == null) {
|
||||
return EntityType.UNKNOWN;
|
||||
}
|
||||
|
||||
EntityType entityType = RegistryUtil.lookup(EntityType.class).get(key);
|
||||
return entityType == null ? EntityType.UNKNOWN : entityType;
|
||||
}
|
||||
|
||||
public CreatureSpawnEvent.SpawnReason getReason() {
|
||||
return reason == null ? CreatureSpawnEvent.SpawnReason.NATURAL : reason;
|
||||
public CreatureSpawnEvent.SpawnReason getBukkitReason() {
|
||||
if (reason == null || reason.isBlank()) {
|
||||
return CreatureSpawnEvent.SpawnReason.NATURAL;
|
||||
}
|
||||
|
||||
try {
|
||||
return CreatureSpawnEvent.SpawnReason.valueOf(reason.trim().toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return CreatureSpawnEvent.SpawnReason.NATURAL;
|
||||
}
|
||||
}
|
||||
|
||||
public Gene getPandaMainGene() {
|
||||
return pandaMainGene == null ? Gene.NORMAL : pandaMainGene;
|
||||
public Gene getBukkitPandaMainGene() {
|
||||
return resolveGene(pandaMainGene);
|
||||
}
|
||||
|
||||
public Gene getPandaHiddenGene() {
|
||||
return pandaHiddenGene == null ? Gene.NORMAL : pandaHiddenGene;
|
||||
public Gene getBukkitPandaHiddenGene() {
|
||||
return resolveGene(pandaHiddenGene);
|
||||
}
|
||||
|
||||
private static Gene resolveGene(String gene) {
|
||||
if (gene == null || gene.isBlank()) {
|
||||
return Gene.NORMAL;
|
||||
}
|
||||
|
||||
try {
|
||||
return Gene.valueOf(gene.trim().toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Gene.NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
public Entity spawn(Engine gen, Location at) {
|
||||
@@ -307,8 +354,8 @@ public class IrisEntity extends IrisRegistrant {
|
||||
}
|
||||
|
||||
if (e instanceof Panda) {
|
||||
((Panda) e).setMainGene(getPandaMainGene());
|
||||
((Panda) e).setMainGene(getPandaHiddenGene());
|
||||
((Panda) e).setMainGene(getBukkitPandaMainGene());
|
||||
((Panda) e).setHiddenGene(getBukkitPandaHiddenGene());
|
||||
}
|
||||
|
||||
if (e instanceof Villager) {
|
||||
@@ -401,7 +448,7 @@ public class IrisEntity extends IrisRegistrant {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (EntityType.UNKNOWN.equals(getType()) && !isSpecialType()) {
|
||||
if (EntityType.UNKNOWN.equals(getBukkitType()) && !isSpecialType()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -435,7 +482,7 @@ public class IrisEntity extends IrisRegistrant {
|
||||
}
|
||||
|
||||
|
||||
return BukkitPlatform.spawnEntity(at, getType(), getReason());
|
||||
return BukkitPlatform.spawnEntity(at, getBukkitType(), getBukkitReason());
|
||||
}
|
||||
|
||||
public boolean isSpecialType() {
|
||||
|
||||
@@ -21,7 +21,11 @@ package art.arcane.iris.engine.object;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.util.common.format.C;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
@@ -177,7 +181,7 @@ public class IrisEntitySpawn implements IRare {
|
||||
return null;
|
||||
}
|
||||
|
||||
Vector3d boundingBox = BukkitPlatform.entityBoundingBox(irisEntity.getType());
|
||||
Vector3d boundingBox = BukkitPlatform.entityBoundingBox(irisEntity.getBukkitType());
|
||||
if (!ignoreSurfaces && boundingBox != null) {
|
||||
boolean isClearForSpawn = isAreaClearForSpawn(at, boundingBox);
|
||||
if (!isClearForSpawn) {
|
||||
|
||||
@@ -10,7 +10,14 @@ import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import lombok.*;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -27,7 +27,13 @@ import art.arcane.volmlib.util.collection.KMap;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.project.noise.CNG;
|
||||
import art.arcane.iris.util.project.stream.ProceduralStream;
|
||||
import lombok.*;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Snippet("expression-load")
|
||||
|
||||
@@ -20,7 +20,11 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.iris.util.project.interpolation.IrisInterpolation;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
|
||||
@@ -20,7 +20,11 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.project.noise.CNG;
|
||||
|
||||
@@ -24,7 +24,7 @@ import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.function.NoiseProvider3;
|
||||
import art.arcane.iris.util.project.interpolation.InterpolationMethod3D;
|
||||
import art.arcane.iris.util.project.interpolation.IrisInterpolation;
|
||||
|
||||
@@ -21,7 +21,11 @@ package art.arcane.iris.engine.object;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.mantle.MantleWriter;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -24,7 +24,13 @@ import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.core.link.Identifier;
|
||||
import art.arcane.iris.core.service.ExternalDataSVC;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListItemType;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
@@ -49,7 +55,7 @@ import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.components.CustomModelDataComponent;
|
||||
import org.bukkit.material.Colorable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.iris.util.common.data.DataProvider;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@@ -20,7 +20,11 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.project.noise.CNG;
|
||||
|
||||
@@ -19,7 +19,12 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
+5
-1
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
+5
-1
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -20,7 +20,12 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.project.interpolation.IrisInterpolation;
|
||||
|
||||
@@ -39,7 +39,10 @@ import art.arcane.volmlib.util.json.JSONObject;
|
||||
import art.arcane.volmlib.util.math.BlockPosition;
|
||||
import art.arcane.volmlib.util.math.Position2;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.common.math.*;
|
||||
import art.arcane.iris.util.common.math.AxisAlignedBB;
|
||||
import art.arcane.iris.util.common.math.IrisBlockVector;
|
||||
import art.arcane.iris.util.common.math.IrisVector;
|
||||
import art.arcane.iris.util.common.math.Vector3i;
|
||||
import art.arcane.volmlib.util.matter.MatterMarker;
|
||||
import art.arcane.iris.util.common.parallel.BurstExecutor;
|
||||
import art.arcane.iris.util.common.parallel.MultiBurst;
|
||||
@@ -56,8 +59,19 @@ import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -502,7 +516,10 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {}
|
||||
} catch (InterruptedException interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("Interrupted while writing object", interrupted);
|
||||
}
|
||||
if (ref.get() != null)
|
||||
throw ref.get();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.util.common.data.B;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@@ -20,7 +20,13 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -23,7 +23,13 @@ import art.arcane.iris.platform.bukkit.BukkitBlockResolution;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.RegistryListResource;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
|
||||
@@ -20,7 +20,12 @@ package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.data.cache.AtomicCache;
|
||||
import art.arcane.iris.engine.object.annotations.*;
|
||||
import art.arcane.iris.engine.object.annotations.ArrayType;
|
||||
import art.arcane.iris.engine.object.annotations.Desc;
|
||||
import art.arcane.iris.engine.object.annotations.MaxNumber;
|
||||
import art.arcane.iris.engine.object.annotations.MinNumber;
|
||||
import art.arcane.iris.engine.object.annotations.Required;
|
||||
import art.arcane.iris.engine.object.annotations.Snippet;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.iris.util.project.noise.CNG;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user