9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2026-01-04 15:41:30 +00:00
This commit is contained in:
RePixelatedMC
2024-09-28 18:03:07 +02:00
parent 34a67dc781
commit 85aefcd206
10 changed files with 307 additions and 168 deletions

View File

@@ -73,7 +73,6 @@ import static org.bukkit.Bukkit.getServer;
public class CommandIris implements DecreeExecutor {
private CommandStudio studio;
private CommandPregen pregen;
private CommandLazyPregen lazyPregen;
private CommandSettings settings;
private CommandObject object;
private CommandJigsaw jigsaw;

View File

@@ -1,121 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.gui.PregeneratorJob;
import com.volmit.iris.core.pregenerator.LazyPregenerator;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Position2;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.IOException;
@Decree(name = "lazypregen", aliases = "lazy", description = "Pregenerate your Iris worlds!")
public class CommandLazyPregen implements DecreeExecutor {
public String worldName;
@Decree(description = "Pregenerate a world")
public void start(
@Param(description = "The radius of the pregen in blocks", aliases = "size")
int radius,
@Param(description = "The world to pregen", contextual = true)
World world,
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
Vector center,
@Param(aliases = "maxcpm", description = "Limit the chunks per minute the pregen will generate", defaultValue = "999999999")
int cpm,
@Param(aliases = "silent", description = "Silent generation", defaultValue = "false")
boolean silent
) {
worldName = world.getName();
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
File lazyFile = new File(worldDirectory, "lazygen.json");
if (lazyFile.exists()) {
sender().sendMessage(C.BLUE + "Lazy pregen is already in progress");
Iris.info(C.YELLOW + "Lazy pregen is already in progress");
return;
}
try {
if (sender().isPlayer() && access() == null) {
sender().sendMessage(C.RED + "The engine access for this world is null!");
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
}
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
.world(worldName)
.healingPosition(0)
.healing(false)
.chunksPerMinute(cpm)
.radiusBlocks(radius)
.position(0)
.silent(silent)
.build();
File lazyGenFile = new File(worldDirectory, "lazygen.json");
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, lazyGenFile);
pregenerator.start();
String msg = C.GREEN + "LazyPregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
sender().sendMessage(msg);
Iris.info(msg);
} catch (Throwable e) {
sender().sendMessage(C.RED + "Epic fail. See console.");
Iris.reportError(e);
e.printStackTrace();
}
}
@Decree(description = "Stop the active pregeneration task", aliases = "x")
public void stop(
@Param(aliases = "world", description = "The world to pause")
World world
) throws IOException {
if (LazyPregenerator.getInstance() != null) {
LazyPregenerator.getInstance().shutdownInstance(world);
sender().sendMessage(C.LIGHT_PURPLE + "Closed lazygen instance for " + world.getName());
} else {
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
}
}
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
public void pause(
@Param(aliases = "world", description = "The world to pause")
World world
) {
if (LazyPregenerator.getInstance() != null) {
LazyPregenerator.getInstance().setPausedLazy(world);
sender().sendMessage(C.GREEN + "Paused/unpaused Lazy Pregen, now: " + (LazyPregenerator.getInstance().isPausedLazy(world) ? "Paused" : "Running") + ".");
} else {
sender().sendMessage(C.YELLOW + "No active Lazy Pregen tasks to pause/unpause.");
}
}
}

View File

@@ -18,6 +18,7 @@
package com.volmit.iris.core.nms;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.framework.Engine;
@@ -30,6 +31,7 @@ import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -125,4 +127,9 @@ public interface INMSBinding {
}
KList<String> getStructureKeys();
default BlockData getBlockData(CompoundTag tag) {
Iris.error("Unsupported version!");
return null;
};
}

View File

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

View File

@@ -10,14 +10,19 @@ import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import java.io.File;
import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.plugin.Plugin;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -41,6 +46,12 @@ public class IrisBiomeFixer {
private AtomicInteger totalChunks = new AtomicInteger(0);
private ChronoLatch progressLatch = new ChronoLatch(5000); // Update every 5 seconds
// File to store unregistered biome IDs
private File unregisteredBiomesFile;
// Reference to your plugin instance (Assuming you have one)
private Plugin plugin;
public IrisBiomeFixer(World world) {
if (!IrisToolbelt.isIrisWorld(world)) {
Iris.info("This is not an Iris world!");
@@ -53,6 +64,10 @@ public class IrisBiomeFixer {
this.world = world;
this.latch = new ChronoLatch(3000);
this.engine = IrisToolbelt.access(world).getEngine();
this.plugin = Iris.instance;
// Initialize the file for storing unregistered biome IDs
this.unregisteredBiomesFile = new File(world.getWorldFolder(), "unregistered_biomes.txt");
}
public void fixBiomes() {
@@ -75,7 +90,7 @@ public class IrisBiomeFixer {
continue;
}
totalChunks.addAndGet(1024); // Each region has 32x32 chunks = 1024
totalChunks.addAndGet(1024);
}
for (File regionFile : regionFiles) {
@@ -112,27 +127,36 @@ public class IrisBiomeFixer {
Block block = chunk.getBlock(x, y, z);
Biome bukkitBiome;
IrisBiome irisBiome = engine.getBiome(x, y, z);
IrisBiomeCustom custom;
try {
// Try to get the custom biome
IrisBiomeCustom custom = irisBiome.getCustomBiome(rng, x, y, z);
if (custom != null) {
bukkitBiome = Biome.valueOf(custom.getId().toUpperCase());
} else {
// Fallback to derivative biome if custom biome is null
bukkitBiome = irisBiome.getDerivative();
}
} catch (NullPointerException e) {
// So else will fail. But this works lol
bukkitBiome = irisBiome.getDerivative();
custom = irisBiome.getCustomBiome(rng, x, y, z);
} catch (Exception e) {
custom = null;
}
if (bukkitBiome == null) {
// This should be impossible
bukkitBiome = Biome.CUSTOM;
Iris.warn("Biome NULL! using plains as fallback!");
if (custom != null) {
// Attempt to get the Biome enum constant
try {
bukkitBiome = Biome.valueOf(custom.getId().toUpperCase());
world.setBiome(block.getX(), block.getY(), block.getZ(), bukkitBiome);
} catch (IllegalArgumentException ex) {
// Custom biome not found in Biome enum
// Attempt to set custom biome via NMS
try {
setCustomBiome(block, custom.getId());
} catch (Exception e) {
// Log unregistered or failed to set custom biome
logUnregisteredBiome(custom.getId());
// Fallback to derivative biome
bukkitBiome = irisBiome.getDerivative();
world.setBiome(block.getX(), block.getY(), block.getZ(), bukkitBiome);
}
}
} else {
// Use derivative biome if custom biome is null
bukkitBiome = irisBiome.getDerivative();
world.setBiome(block.getX(), block.getY(), block.getZ(), bukkitBiome);
}
world.setBiome(block.getX(), block.getY(), block.getZ(), bukkitBiome);
}
}
}
@@ -169,6 +193,64 @@ public class IrisBiomeFixer {
Iris.info(String.format("Biome Fixing Completed: %d/%d chunks processed.", generated.get(), totalChunks.get()));
}
/**
* Sets a custom biome using NMS (Minecraft's internal classes).
*
* @param block The block whose biome is to be set.
* @param biomeId The NamespacedKey of the custom biome (e.g., "custom:my_biome").
* @throws Exception If reflection or NMS interaction fails.
*/
private void setCustomBiome(Block block, String biomeId) throws Exception {
// Parse the NamespacedKey
NamespacedKey key = NamespacedKey.fromString(biomeId);
if (key == null) {
throw new IllegalArgumentException("Invalid biome ID: " + biomeId);
}
// Access NMS classes using reflection
// Adjust the version string as needed (e.g., "v1_20_R1")
String nmsVersion = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
Class<?> worldClass = Class.forName("org.bukkit.craftbukkit." + nmsVersion + ".CraftWorld");
Object nmsWorld = worldClass.cast(world).getClass().getMethod("getHandle").invoke(world);
Class<?> chunkClass = Class.forName("net.minecraft.world.level.chunk.Chunk");
Object nmsChunk = chunkClass.cast(nmsWorld.getClass().getMethod("getChunk", int.class, int.class, boolean.class)
.invoke(nmsWorld, block.getChunk().getX(), block.getChunk().getZ(), false));
// Get the biome registry
Class<?> registryKeyClass = Class.forName("net.minecraft.resources.ResourceKey");
Class<?> biomeClass = Class.forName("net.minecraft.world.level.biome.Biome");
Class<?> registryClass = Class.forName("net.minecraft.core.Registry");
Method biomeRegistryMethod = registryClass.getMethod("a", Class.class, Object.class);
Object biomeRegistry = biomeRegistryMethod.invoke(null, biomeClass, null); // Replace null with actual registry if needed
// Get the biome by key
Method getBiomeMethod = biomeClass.getMethod("a", registryKeyClass);
Object customBiome = getBiomeMethod.invoke(null, key.getNamespace() + ":" + key.getKey());
if (customBiome == null) {
throw new IllegalArgumentException("Custom biome not found: " + biomeId);
}
// Set the biome in the chunk
Method setBiomeMethod = chunkClass.getMethod("setBiome", int.class, int.class, biomeClass);
setBiomeMethod.invoke(nmsChunk, block.getX() & 15, block.getZ() & 15, customBiome);
}
/**
* Logs unregistered or failed to set custom biomes to a file.
*
* @param biomeId The ID of the biome that failed to register.
*/
private void logUnregisteredBiome(String biomeId) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(unregisteredBiomesFile, true))) {
writer.write(biomeId);
writer.newLine();
} catch (IOException e) {
Iris.error("Failed to log unregistered biome: " + biomeId, e);
}
}
private long computeETA(int cps) {
if (chunksPerSecond.size() < chunksPerSecond.getMax()) {
if (cps == 0) return Long.MAX_VALUE;
@@ -194,4 +276,3 @@ public class IrisBiomeFixer {
return String.format("%02dh:%02dm:%02ds", hours, minutes, seconds);
}
}

View File

@@ -2,8 +2,11 @@ package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.Consumer2;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.io.NamedTag;
@@ -141,28 +144,61 @@ public class IrisConverter {
*
* @param sender
*/
public static void convertJigsaw(VolmitSender sender) {
File folder = Iris.instance.getDataFolder("convert");
public static void convertJigsawStructure(File in, File out, VolmitSender sender) {
File dataFolder = Iris.instance.getDataFolder("convert");
try {
KMap<String, IrisJigsawPool> pools = new KMap<>();
KList<File> roots = new KList<>();
AtomicInteger total = new AtomicInteger(0);
AtomicInteger at = new AtomicInteger(0);
File destPools = new File(out.getAbsolutePath() + "/jigsaw-pools");
destPools.mkdirs();
findAllNBT(in, (folder, file) -> {
total.getAndIncrement();
if (roots.addIfMissing(folder)) {
String b = in.toURI().relativize(folder.toURI()).getPath();
if (b.startsWith("/")) {
b = b.substring(1);
}
FilenameFilter filter = (dir, name) -> name.endsWith(".nbt");
File[] fileList = folder.listFiles(filter);
if (fileList == null) {
sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath());
if (b.endsWith("/")) {
b = b.substring(0, b.length() - 1);
}
pools.put(b, new IrisJigsawPool());
}
});
} catch (Exception e) {
Iris.error(C.RED + "Failed to convert: " + in.getPath());
e.printStackTrace();
}
}
private static void findAllNBT(File path, Consumer2<File, File> inFile) {
if (path == null) {
return;
}
for (File nbt : fileList) {
try {
NamedTag tag = NBTUtil.read(nbt);
CompoundTag compound = (CompoundTag) tag.getTag();
} catch (Exception e) {
Iris.error(C.RED + "Failed to convert: " + nbt.getName());
e.printStackTrace();
}
if (path.isFile() && path.getName().endsWith(".nbt")) {
inFile.accept(path.getParentFile(), path);
return;
}
for (File i : path.listFiles()) {
if (i.isDirectory()) {
findAllNBT(i, inFile);
} else if (i.isFile() && i.getName().endsWith(".nbt")) {
inFile.accept(path, i);
}
}
}
}

View File

@@ -3,30 +3,108 @@ package com.volmit.iris.engine.framework;
import com.volmit.iris.engine.object.InventorySlotType;
import com.volmit.iris.engine.object.IrisLootTable;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.RNG;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.world.LootGenerateEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootContext;
import org.bukkit.loot.LootTable;
import org.bukkit.loot.LootTables;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Getter
public class IrisLootEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final Engine engine;
private final Block block;
private final InventorySlotType slot;
private final KList<IrisLootTable> tables;
private final Mode mode; // New field to represent the mode
// Define the different modes for the event
public enum Mode {
NORMAL,
BUKKIT_LOOT
}
/**
* Constructor for IrisLootEvent with mode selection.
*
* @param engine The engine instance.
* @param block The block associated with the event.
* @param slot The inventory slot type.
* @param tables The list of IrisLootTables. (mutable*)
*/
public IrisLootEvent(Engine engine, Block block, InventorySlotType slot, KList<IrisLootTable> tables) {
this.engine = engine;
this.block = block;
this.slot = slot;
this.tables = tables;
this.mode = Mode.BUKKIT_LOOT;
if (this.mode == Mode.BUKKIT_LOOT) {
triggerBukkitLootEvent();
}
}
/**
* Triggers the corresponding Bukkit loot event.
* This method integrates your custom IrisLootTables with Bukkit's LootGenerateEvent,
* allowing other plugins to modify or cancel the loot generation.
*/
private Inventory triggerBukkitLootEvent() {
if (block.getState() instanceof InventoryHolder) {
InventoryHolder holder = (InventoryHolder) block.getState();
Inventory inventory = holder.getInventory();
inventory.clear();
List<ItemStack> loot = new ArrayList<>();
RNG rng = new RNG();
int x = block.getX(), y = block.getY(), z = block.getZ();
for (IrisLootTable table : tables)
loot.addAll(table.getLoot(false, rng, slot, x, y, z));
LootContext context = new LootContext.Builder(block.getLocation()).build();
LootTable lootTable = Bukkit.getLootTable(LootTables.EMPTY.getKey()); // todo: Correct structure
LootGenerateEvent bukkitEvent = new LootGenerateEvent(engine.getWorld().realWorld(), null, holder, lootTable, context, loot, true); // todo: Use the iris loottable
Bukkit.getServer().getPluginManager().callEvent(bukkitEvent);
if (!bukkitEvent.isCancelled())
inventory.setContents(bukkitEvent.getLoot().toArray(new ItemStack[0]));
return inventory;
}
return null;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
/**
* Required method to get the HandlerList for this event.
*
* @return The HandlerList.
*/
public static HandlerList getHandlerList() {
return handlers;
}
}
}

View File

@@ -23,6 +23,7 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
@Getter
@@ -64,6 +65,8 @@ public class WorldObjectPlacer implements IObjectPlacer {
RNG rx = new RNG(Cache.key(x, z));
KList<IrisLootTable> tables = engine.getLootTables(rx, block);
Inventory inventory = null;
try {
Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables));