From 85aefcd206c28544a9c972054349ce93fa0d6d22 Mon Sep 17 00:00:00 2001 From: RePixelatedMC <107539181+RePixelatedMC@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:03:07 +0200 Subject: [PATCH] mid save --- build.gradle | 2 +- .../iris/core/commands/CommandIris.java | 1 - .../iris/core/commands/CommandLazyPregen.java | 121 ----------------- .../com/volmit/iris/core/nms/INMSBinding.java | 7 + .../iris/core/service/ConversionSVC.java | 37 +++++- .../iris/core/tools/IrisBiomeFixer.java | 125 +++++++++++++++--- .../volmit/iris/core/tools/IrisConverter.java | 70 +++++++--- .../iris/engine/framework/IrisLootEvent.java | 80 ++++++++++- .../framework/placer/WorldObjectPlacer.java | 3 + .../iris/core/nms/v1_20_R3/NMSBinding.java | 29 ++++ 10 files changed, 307 insertions(+), 168 deletions(-) delete mode 100644 core/src/main/java/com/volmit/iris/core/commands/CommandLazyPregen.java diff --git a/build.gradle b/build.gradle index 81d90ce2e..b66784e55 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ registerCustomOutputTask('Coco', 'D://mcsm/plugins') registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins') registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins') registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins') -registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.4 - Development/plugins') +registerCustomOutputTask('Pixel', 'D://Iris Dimension Engine/1.20.4 - Development/plugins') // ========================== UNIX ============================== registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins') registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins') diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java index 5154ea4af..18559fbd0 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java @@ -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; diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandLazyPregen.java b/core/src/main/java/com/volmit/iris/core/commands/CommandLazyPregen.java deleted file mode 100644 index a3d4c622c..000000000 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandLazyPregen.java +++ /dev/null @@ -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 . - */ - -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."); - - } - } -} diff --git a/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java b/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java index d75c87672..fda64fe1f 100644 --- a/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java +++ b/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java @@ -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 getStructureKeys(); + + default BlockData getBlockData(CompoundTag tag) { + Iris.error("Unsupported version!"); + return null; + }; } diff --git a/core/src/main/java/com/volmit/iris/core/service/ConversionSVC.java b/core/src/main/java/com/volmit/iris/core/service/ConversionSVC.java index 7786e5aed..76b4a8d75 100644 --- a/core/src/main/java/com/volmit/iris/core/service/ConversionSVC.java +++ b/core/src/main/java/com/volmit/iris/core/service/ConversionSVC.java @@ -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 converters; @@ -122,7 +128,7 @@ public class ConversionSVC implements IrisService { @SuppressWarnings("unchecked") ListTag paletteList = (ListTag) 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 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(); diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisBiomeFixer.java b/core/src/main/java/com/volmit/iris/core/tools/IrisBiomeFixer.java index 029adbe30..c5c50c59f 100644 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisBiomeFixer.java +++ b/core/src/main/java/com/volmit/iris/core/tools/IrisBiomeFixer.java @@ -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); } } - diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisConverter.java b/core/src/main/java/com/volmit/iris/core/tools/IrisConverter.java index f1dcc7884..ae8168743 100644 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisConverter.java +++ b/core/src/main/java/com/volmit/iris/core/tools/IrisConverter.java @@ -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 pools = new KMap<>(); + KList 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 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); + } } - - } } diff --git a/core/src/main/java/com/volmit/iris/engine/framework/IrisLootEvent.java b/core/src/main/java/com/volmit/iris/engine/framework/IrisLootEvent.java index 057763893..a018e6319 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/IrisLootEvent.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/IrisLootEvent.java @@ -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 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 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 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; } -} +} \ No newline at end of file diff --git a/core/src/main/java/com/volmit/iris/engine/framework/placer/WorldObjectPlacer.java b/core/src/main/java/com/volmit/iris/engine/framework/placer/WorldObjectPlacer.java index 9cec98218..974f1c4ec 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/placer/WorldObjectPlacer.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/placer/WorldObjectPlacer.java @@ -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 tables = engine.getLootTables(rx, block); + Inventory inventory = null; + try { Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables)); diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java index c69d2a66e..693fe2e6b 100644 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java +++ b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java @@ -16,6 +16,7 @@ import java.util.concurrent.atomic.AtomicInteger; import com.mojang.datafixers.util.Pair; import com.volmit.iris.core.nms.container.BiomeColor; +import com.volmit.iris.util.data.B; import com.volmit.iris.util.scheduling.J; import net.minecraft.nbt.*; import net.minecraft.nbt.Tag; @@ -631,4 +632,32 @@ public class NMSBinding implements INMSBinding { public static Holder biomeToBiomeBase(Registry registry, Biome biome) { return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey()))); } + + @Override + public BlockData getBlockData(CompoundTag tag) { + if (tag == null) { + return B.getAir(); + } + + StringBuilder p = new StringBuilder(tag.getString("Name")); + + if (tag.containsKey("Properties")) { + CompoundTag props = tag.getCompoundTag("Properties"); + p.append('['); + + for (String i : props.keySet()) { + p.append(i).append('=').append(props.getString(i)).append(','); + } + + p.deleteCharAt(p.length() - 1).append(']'); + } + + BlockData b = B.get(String.valueOf(p)); + + if (b == null) { + return B.getAir(); + } + + return b; + } }