diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 7547126e4..43aff0686 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -62,10 +62,7 @@ import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.stream.ProceduralStream; import io.papermc.lib.PaperLib; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; +import org.bukkit.*; import org.bukkit.block.Biome; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -77,6 +74,7 @@ import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import java.awt.*; +import java.awt.Color; import java.util.Arrays; import java.util.Set; import java.util.UUID; @@ -497,7 +495,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat } @Override - default void addItems(boolean debug, Inventory inv, RNG rng, KList tables, InventorySlotType slot, int x, int y, int z, int mgf) { + default void addItems(boolean debug, Inventory inv, RNG rng, KList tables, InventorySlotType slot, World world, int x, int y, int z, int mgf) { KList items = new KList<>(); int b = 4; @@ -505,7 +503,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat if (i == null) continue; b++; - items.addAll(i.getLoot(debug, rng, slot, x, y, z)); + items.addAll(i.getLoot(debug, rng, slot, world, x, y, z)); } if (PaperLib.isPaper() && getWorld().hasRealWorld()) { 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 a018e6319..040ab9f3c 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 @@ -68,8 +68,7 @@ public class IrisLootEvent extends Event { * allowing other plugins to modify or cancel the loot generation. */ private Inventory triggerBukkitLootEvent() { - if (block.getState() instanceof InventoryHolder) { - InventoryHolder holder = (InventoryHolder) block.getState(); + if (block.getState() instanceof InventoryHolder holder) { Inventory inventory = holder.getInventory(); inventory.clear(); @@ -78,11 +77,11 @@ public class IrisLootEvent extends Event { int x = block.getX(), y = block.getY(), z = block.getZ(); for (IrisLootTable table : tables) - loot.addAll(table.getLoot(false, rng, slot, x, y, z)); + loot.addAll(table.getLoot(false, rng, slot, block.getWorld(), x, y, z)); LootContext context = new LootContext.Builder(block.getLocation()).build(); - LootTable lootTable = Bukkit.getLootTable(LootTables.EMPTY.getKey()); // todo: Correct structure + LootTable lootTable = LootTables.EMPTY.getLootTable(); // todo: Correct structure LootGenerateEvent bukkitEvent = new LootGenerateEvent(engine.getWorld().realWorld(), null, holder, lootTable, context, loot, true); // todo: Use the iris loottable Bukkit.getServer().getPluginManager().callEvent(bukkitEvent); diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java index 6f732f449..0ce3a08e0 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java @@ -271,7 +271,7 @@ public class IrisEntity extends IrisRegistrant { for (String fi : getLoot().getTables()) { IrisLootTable i = gen.getData().getLootLoader().load(fi); - items.addAll(i.getLoot(gen.isStudio(), rng.nextParallelRNG(345911), InventorySlotType.STORAGE, finalAt.getBlockX(), finalAt.getBlockY(), finalAt.getBlockZ())); + items.addAll(i.getLoot(gen.isStudio(), rng.nextParallelRNG(345911), InventorySlotType.STORAGE, finalAt.getWorld(), finalAt.getBlockX(), finalAt.getBlockY(), finalAt.getBlockZ())); } return items; diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisLootTable.java b/core/src/main/java/com/volmit/iris/engine/object/IrisLootTable.java index 38964c72a..07e13e875 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisLootTable.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisLootTable.java @@ -33,6 +33,7 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.inventory.ItemStack; @Accessors(chain = true) @@ -67,7 +68,7 @@ public class IrisLootTable extends IrisRegistrant { @ArrayType(min = 1, type = IrisLoot.class) private KList loot = new KList<>(); - public KList getLoot(boolean debug, RNG rng, InventorySlotType slot, int x, int y, int z) { + public KList getLoot(boolean debug, RNG rng, InventorySlotType slot, World world, int x, int y, int z) { KList lootf = new KList<>(); int m = 0; diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java b/core/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java index d03248e87..14dcc0a3e 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java @@ -34,9 +34,15 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; +import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.TreeType; import org.bukkit.block.data.BlockData; +import org.bukkit.loot.LootTable; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; @Snippet("object-placer") @EqualsAndHashCode() @@ -123,6 +129,8 @@ public class IrisObjectPlacement { @ArrayType(min = 1, type = IrisObjectLoot.class) @Desc("The loot tables to apply to these objects") private KList loot = new KList<>(); + @Desc("The vanilla loot tables to apply to these objects") + private KList vanillaLoot = new KList<>(); @Desc("Whether the given loot tables override any and all other loot tables available in the dimension, region or biome.") private boolean overrideGlobalLoot = false; @Desc("This object / these objects override the following trees when they grow...") @@ -138,7 +146,8 @@ public class IrisObjectPlacement { private KList forbiddenCollisions = new KList<>(); @Desc("Ignore any placement restrictions for this object") private boolean forcePlace = false; - private transient AtomicCache cache = new AtomicCache<>(); + private transient AtomicCache> cache = new AtomicCache<>(); + private transient AtomicCache> vanillaCache = new AtomicCache<>(); public IrisObjectPlacement toPlacement(String... place) { IrisObjectPlacement p = new IrisObjectPlacement(); @@ -209,48 +218,62 @@ public class IrisObjectPlacement { return (int) Math.round(densityStyle.get(rng, x, z, data)); } - private TableCache getCache(IrisData manager) { - return cache.aquire(() -> { - TableCache tc = new TableCache(); + private TableCache getCache(IrisData manager) { + return cache.aquire(() -> getCache(manager, manager.getLootLoader()::load)); + } - for (IrisObjectLoot loot : getLoot()) { - if (loot == null) - continue; - IrisLootTable table = manager.getLootLoader().load(loot.getName()); - if (table == null) { - Iris.warn("Couldn't find loot table " + loot.getName()); - continue; + private TableCache getVanillaCache(IrisData manager) { + return vanillaCache.aquire(() -> getCache(manager, IrisObjectPlacement::getVanillaTable)); + } + + private TableCache getCache(IrisData manager, Function loader) { + TableCache tc = new TableCache<>(); + + for (IrisObjectLoot loot : getLoot()) { + if (loot == null) + continue; + T table = loader.apply(loot.getName()); + if (table == null) { + Iris.warn("Couldn't find loot table " + loot.getName()); + continue; + } + + if (loot.getFilter().isEmpty()) //Table applies to all containers + { + tc.global.put(table, loot.getWeight()); + } else if (!loot.isExact()) //Table is meant to be by type + { + for (BlockData filterData : loot.getFilter(manager)) { + if (!tc.basic.containsKey(filterData.getMaterial())) { + tc.basic.put(filterData.getMaterial(), new WeightedRandom<>()); + } + + tc.basic.get(filterData.getMaterial()).put(table, loot.getWeight()); } - - if (loot.getFilter().isEmpty()) //Table applies to all containers - { - tc.global.put(table, loot.getWeight()); - } else if (!loot.isExact()) //Table is meant to be by type - { - for (BlockData filterData : loot.getFilter(manager)) { - if (!tc.basic.containsKey(filterData.getMaterial())) { - tc.basic.put(filterData.getMaterial(), new WeightedRandom<>()); - } - - tc.basic.get(filterData.getMaterial()).put(table, loot.getWeight()); + } else //Filter is exact + { + for (BlockData filterData : loot.getFilter(manager)) { + if (!tc.exact.containsKey(filterData.getMaterial())) { + tc.exact.put(filterData.getMaterial(), new KMap<>()); } - } else //Filter is exact - { - for (BlockData filterData : loot.getFilter(manager)) { - if (!tc.exact.containsKey(filterData.getMaterial())) { - tc.exact.put(filterData.getMaterial(), new KMap<>()); - } - if (!tc.exact.get(filterData.getMaterial()).containsKey(filterData)) { - tc.exact.get(filterData.getMaterial()).put(filterData, new WeightedRandom<>()); - } - - tc.exact.get(filterData.getMaterial()).get(filterData).put(table, loot.getWeight()); + if (!tc.exact.get(filterData.getMaterial()).containsKey(filterData)) { + tc.exact.get(filterData.getMaterial()).put(filterData, new WeightedRandom<>()); } + + tc.exact.get(filterData.getMaterial()).get(filterData).put(table, loot.getWeight()); } } - return tc; - }); + } + return tc; + } + + @Nullable + private static IrisVanillaLootTable getVanillaTable(String name) { + NamespacedKey key = NamespacedKey.fromString(name); + if (key == null) + return null; + return new IrisVanillaLootTable(Bukkit.getLootTable(key)); } /** @@ -261,10 +284,16 @@ public class IrisObjectPlacement { * @return The loot table it should use. */ public IrisLootTable getTable(BlockData data, IrisData dataManager) { - TableCache cache = getCache(dataManager); + IrisLootTable table = pickTable(data, getVanillaCache(dataManager)); + if (table == null) { + table = pickTable(data, getCache(dataManager)); + } + return table; + } + private T pickTable(BlockData data, TableCache cache) { if (B.isStorageChest(data)) { - IrisLootTable picked = null; + T picked = null; if (cache.exact.containsKey(data.getMaterial()) && cache.exact.get(data.getMaterial()).containsKey(data)) { picked = cache.exact.get(data.getMaterial()).get(data).pullRandom(); } else if (cache.basic.containsKey(data.getMaterial())) { @@ -279,9 +308,9 @@ public class IrisObjectPlacement { return null; } - private static class TableCache { - final transient WeightedRandom global = new WeightedRandom<>(); - final transient KMap> basic = new KMap<>(); - final transient KMap>> exact = new KMap<>(); + private static class TableCache { + final transient WeightedRandom global = new WeightedRandom<>(); + final transient KMap> basic = new KMap<>(); + final transient KMap>> exact = new KMap<>(); } } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisObjectVanillaLoot.java b/core/src/main/java/com/volmit/iris/engine/object/IrisObjectVanillaLoot.java new file mode 100644 index 000000000..ea14b8274 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisObjectVanillaLoot.java @@ -0,0 +1,48 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.engine.data.cache.AtomicCache; +import com.volmit.iris.engine.object.annotations.*; +import com.volmit.iris.util.collection.KList; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +import org.bukkit.block.data.BlockData; + +@Snippet("object-vanilla-loot") +@Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor +@Desc("Represents vanilla loot within this object or jigsaw piece") +@Data +public class IrisObjectVanillaLoot { + private final transient AtomicCache> filterCache = new AtomicCache<>(); + @ArrayType(min = 1, type = IrisBlockData.class) + @Desc("The list of blocks this loot table should apply to") + private KList filter = new KList<>(); + @Desc("Exactly match the block data or not") + private boolean exact = false; + @Desc("The vanilla loot table key") + @Required + private String name; + @Desc("The weight of this loot table being chosen") + private int weight = 1; + + public KList getFilter(IrisData rdata) { + return filterCache.aquire(() -> + { + KList b = new KList<>(); + + for (IrisBlockData i : filter) { + BlockData bx = i.getBlockData(rdata); + + if (bx != null) { + b.add(bx); + } + } + + return b; + }); + } +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisVanillaLootTable.java b/core/src/main/java/com/volmit/iris/engine/object/IrisVanillaLootTable.java new file mode 100644 index 000000000..dab5af06b --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisVanillaLootTable.java @@ -0,0 +1,84 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.math.RNG; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.inventory.ItemStack; +import org.bukkit.loot.LootContext; +import org.bukkit.loot.LootTable; + +import java.io.File; + +@Data +@EqualsAndHashCode(callSuper = false) +public class IrisVanillaLootTable extends IrisLootTable { + private final LootTable lootTable; + + public KList getLoot(RNG rng, World world, int x, int y, int z) { + return new KList<>(lootTable.populateLoot(rng, new LootContext.Builder(new Location(world, x, y, z)).build())); + } + + @Override + public String getName() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public int getRarity() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public int getMaxPicked() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public int getMinPicked() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public int getMaxTries() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public KList getLoot() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public KList getLoot(boolean debug, RNG rng, InventorySlotType slot, World world, int x, int y, int z) { + return new KList<>(lootTable.populateLoot(rng, new LootContext.Builder(new Location(world, x, y, z)).build())); + } + + @Override + public String getFolderName() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public String getTypeName() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public File getLoadFile() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public IrisData getLoader() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } + + @Override + public KList getPreprocessors() { + throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); + } +}