diff --git a/src/main/java/com/volmit/iris/IrisDataManager.java b/src/main/java/com/volmit/iris/IrisDataManager.java index 352c0bacc..e3890f066 100644 --- a/src/main/java/com/volmit/iris/IrisDataManager.java +++ b/src/main/java/com/volmit/iris/IrisDataManager.java @@ -10,6 +10,7 @@ import com.volmit.iris.object.IrisBiome; import com.volmit.iris.object.IrisBiomeDecorator; import com.volmit.iris.object.IrisDimension; import com.volmit.iris.object.IrisGenerator; +import com.volmit.iris.object.IrisLootTable; import com.volmit.iris.object.IrisNoiseGenerator; import com.volmit.iris.object.IrisObjectPlacement; import com.volmit.iris.object.IrisRegion; @@ -28,6 +29,7 @@ public class IrisDataManager private File packs; private boolean prod; private ResourceLoader biomeLoader; + private ResourceLoader lootLoader; private ResourceLoader regionLoader; private ResourceLoader dimensionLoader; private ResourceLoader generatorLoader; @@ -43,14 +45,14 @@ public class IrisDataManager File packs = this.packs.getName().equals("packs") ? this.packs : dataFolder; packs.mkdirs(); - + this.lootLoader = new ResourceLoader<>(packs, "loot", "Loot", IrisLootTable.class); this.regionLoader = new ResourceLoader<>(packs, "regions", "Region", IrisRegion.class); this.biomeLoader = new ResourceLoader<>(packs, "biomes", "Biome", IrisBiome.class); this.dimensionLoader = new ResourceLoader<>(packs, "dimensions", "Dimension", IrisDimension.class); this.structureLoader = new ResourceLoader<>(packs, "structures", "Structure", IrisStructure.class); this.generatorLoader = new ResourceLoader<>(packs, "generators", "Generator", IrisGenerator.class); this.objectLoader = new ObjectResourceLoader(packs, "objects", "Object"); - + if(packs.getName().equals("packs")) { writeExamples(); @@ -78,6 +80,7 @@ public class IrisDataManager public void dump() { biomeLoader.clearCache(); + lootLoader.clearCache(); regionLoader.clearCache(); dimensionLoader.clearCache(); generatorLoader.clearCache(); @@ -161,6 +164,7 @@ public class IrisDataManager public void preferFolder(String name) { biomeLoader.preferFolder(name); + lootLoader.preferFolder(name); regionLoader.preferFolder(name); dimensionLoader.preferFolder(name); generatorLoader.preferFolder(name); @@ -169,6 +173,7 @@ public class IrisDataManager public void clearLists() { + lootLoader.clearList(); biomeLoader.clearList(); regionLoader.clearList(); dimensionLoader.clearList(); diff --git a/src/main/java/com/volmit/iris/IrisMetrics.java b/src/main/java/com/volmit/iris/IrisMetrics.java index 3d0c59f9f..89628736c 100644 --- a/src/main/java/com/volmit/iris/IrisMetrics.java +++ b/src/main/java/com/volmit/iris/IrisMetrics.java @@ -10,6 +10,7 @@ public class IrisMetrics private final RollingSequence parallax; private final RollingSequence terrain; private final RollingSequence post; + private final RollingSequence update; private final RollingSequence total; private final RollingSequence perSecond; public int generators = 0; @@ -20,6 +21,7 @@ public class IrisMetrics parallax = new RollingSequence(memory); terrain = new RollingSequence(memory); post = new RollingSequence(memory); + update = new RollingSequence(memory); total = new RollingSequence(memory); perSecond = new RollingSequence(5); } diff --git a/src/main/java/com/volmit/iris/ProjectManager.java b/src/main/java/com/volmit/iris/ProjectManager.java index 289be98df..95bfa421c 100644 --- a/src/main/java/com/volmit/iris/ProjectManager.java +++ b/src/main/java/com/volmit/iris/ProjectManager.java @@ -31,6 +31,7 @@ import com.volmit.iris.object.IrisBiomeGeneratorLink; import com.volmit.iris.object.IrisBiomeMutation; import com.volmit.iris.object.IrisDimension; import com.volmit.iris.object.IrisGenerator; +import com.volmit.iris.object.IrisLootTable; import com.volmit.iris.object.IrisNoiseGenerator; import com.volmit.iris.object.IrisObjectPlacement; import com.volmit.iris.object.IrisRegion; @@ -60,6 +61,7 @@ import com.volmit.iris.util.O; import com.volmit.iris.util.RegistryListBiome; import com.volmit.iris.util.RegistryListDimension; import com.volmit.iris.util.RegistryListGenerator; +import com.volmit.iris.util.RegistryListLoot; import com.volmit.iris.util.RegistryListObject; import com.volmit.iris.util.RegistryListRegion; import com.volmit.iris.util.RegistryListStructure; @@ -635,6 +637,7 @@ public class ProjectManager g.queue(() -> ex(schemas, IrisRegion.class, dat, "/regions/*.json")); g.queue(() -> ex(schemas, IrisGenerator.class, dat, "/generators/*.json")); g.queue(() -> ex(schemas, IrisStructure.class, dat, "/structures/*.json")); + g.queue(() -> ex(schemas, IrisLootTable.class, dat, "/loot/*.json")); g.execute(); return schemas; @@ -756,6 +759,11 @@ public class ProjectManager prop.put("enum", new JSONArray(getBiomeList(dat))); } + if(k.isAnnotationPresent(RegistryListLoot.class)) + { + prop.put("enum", new JSONArray(getLootList(dat))); + } + if(k.isAnnotationPresent(RegistryListDimension.class)) { prop.put("enum", new JSONArray(getDimensionList(dat))); @@ -894,6 +902,26 @@ public class ProjectManager continue; } + if(k.isAnnotationPresent(RegistryListLoot.class)) + { + String name = "enloot" + t.type().getSimpleName().toLowerCase(); + if(!def.containsKey(name)) + { + JSONObject deff = new JSONObject(); + deff.put("type", tx); + deff.put("enum", new JSONArray(getLootList(dat))); + def.put(name, deff); + } + + JSONObject items = new JSONObject(); + items.put("$ref", "#/definitions/" + name); + prop.put("items", items); + prop.put("description", k.getAnnotation(Desc.class).value()); + prop.put("type", tp); + properties.put(k.getName(), prop); + continue; + } + if(k.isAnnotationPresent(RegistryListDimension.class)) { String name = "endim" + t.type().getSimpleName().toLowerCase(); @@ -1100,6 +1128,11 @@ public class ProjectManager return data.getBiomeLoader().getPossibleKeys(); } + private String[] getLootList(IrisDataManager data) + { + return data.getLootLoader().getPossibleKeys(); + } + private String[] getDimensionList(IrisDataManager data) { return data.getDimensionLoader().getPossibleKeys(); diff --git a/src/main/java/com/volmit/iris/command/CommandIrisLoot.java b/src/main/java/com/volmit/iris/command/CommandIrisLoot.java new file mode 100644 index 000000000..b003bcc11 --- /dev/null +++ b/src/main/java/com/volmit/iris/command/CommandIrisLoot.java @@ -0,0 +1,99 @@ +package com.volmit.iris.command; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import com.volmit.iris.Iris; +import com.volmit.iris.object.InventorySlotType; +import com.volmit.iris.object.IrisLootTable; +import com.volmit.iris.util.KList; +import com.volmit.iris.util.KMap; +import com.volmit.iris.util.KSet; +import com.volmit.iris.util.MortarCommand; +import com.volmit.iris.util.MortarSender; +import com.volmit.iris.util.O; +import com.volmit.iris.util.RNG; + +public class CommandIrisLoot extends MortarCommand +{ + public CommandIrisLoot() + { + super("loot"); + setDescription("Show loot if a chest were right here"); + requiresPermission(Iris.perm.studio); + setCategory("Loot"); + } + + @Override + public boolean handle(MortarSender sender, String[] args) + { + if(sender.isPlayer()) + { + Player p = sender.player(); + KSet tables = Iris.proj.getCurrentProject().getGlUpdate().getLootTables(p.getLocation().getBlock()); + Inventory inv = Bukkit.createInventory(null, 27 * 2); + Iris.proj.getCurrentProject().getGlUpdate().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ()); + p.openInventory(inv); + + for(IrisLootTable i : tables) + { + sender.sendMessage("- " + i.getName()); + } + + boolean ffast = false; + boolean fadd = false; + + for(String i : args) + { + if(i.equals("--fast")) + { + ffast = true; + } + + if(i.equals("--add")) + { + fadd = true; + } + } + + boolean fast = ffast; + boolean add = fadd; + O ta = new O(); + ta.set(-1); + + ta.set(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () -> + { + if(!p.getOpenInventory().getType().equals(InventoryType.CHEST)) + { + Bukkit.getScheduler().cancelTask(ta.get()); + return; + } + + if(!add) + { + inv.clear(); + } + + Iris.proj.getCurrentProject().getGlUpdate().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ()); + }, 0, fast ? 5 : 35)); + + return true; + } + + else + { + sender.sendMessage("Players only."); + } + + return true; + } + + @Override + protected String getArgsUsage() + { + return "[width]"; + } +} diff --git a/src/main/java/com/volmit/iris/command/CommandIrisMetrics.java b/src/main/java/com/volmit/iris/command/CommandIrisMetrics.java index 658b4f3de..e243343be 100644 --- a/src/main/java/com/volmit/iris/command/CommandIrisMetrics.java +++ b/src/main/java/com/volmit/iris/command/CommandIrisMetrics.java @@ -35,6 +35,7 @@ public class CommandIrisMetrics extends MortarCommand sender.sendMessage(" Terrain : " + ChatColor.BOLD + "" + ChatColor.WHITE + Form.duration(m.getTerrain().getAverage(), 2)); sender.sendMessage(" Parallax: " + ChatColor.BOLD + "" + ChatColor.WHITE + Form.duration(m.getParallax().getAverage(), 2)); sender.sendMessage(" Post : " + ChatColor.BOLD + "" + ChatColor.WHITE + Form.duration(m.getPost().getAverage(), 2)); + sender.sendMessage("Updates : " + ChatColor.BOLD + "" + ChatColor.WHITE + Form.duration(m.getUpdate().getAverage(), 2)); return true; } diff --git a/src/main/java/com/volmit/iris/command/CommandIrisWorld.java b/src/main/java/com/volmit/iris/command/CommandIrisWorld.java index a97898545..2e06ddbde 100644 --- a/src/main/java/com/volmit/iris/command/CommandIrisWorld.java +++ b/src/main/java/com/volmit/iris/command/CommandIrisWorld.java @@ -25,6 +25,9 @@ public class CommandIrisWorld extends MortarCommand @Command private CommandIrisTC tc; + @Command + private CommandIrisLoot loot; + public CommandIrisWorld() { super("world", "wrld", "w"); diff --git a/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java b/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java index effe61814..dc36b244b 100644 --- a/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java +++ b/src/main/java/com/volmit/iris/gen/ParallaxChunkGenerator.java @@ -1,14 +1,17 @@ package com.volmit.iris.gen; import java.io.IOException; +import java.util.List; import org.bukkit.World; import org.bukkit.block.data.BlockData; +import org.bukkit.generator.BlockPopulator; import com.volmit.iris.gen.atomics.AtomicSliver; import com.volmit.iris.gen.atomics.AtomicSliverMap; import com.volmit.iris.gen.atomics.AtomicWorldData; import com.volmit.iris.gen.atomics.MasterLock; +import com.volmit.iris.gen.layer.GenLayerUpdate; import com.volmit.iris.object.IrisBiome; import com.volmit.iris.object.IrisBiomeMutation; import com.volmit.iris.object.IrisObjectPlacement; @@ -40,6 +43,7 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple private MasterLock masterLock; private IrisLock lock = new IrisLock("ParallaxLock"); private IrisLock lockq = new IrisLock("ParallaxQueueLock"); + private GenLayerUpdate glUpdate; private int sliverBuffer; public ParallaxChunkGenerator(String dimensionName, int threads) @@ -82,6 +86,12 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple return getHighest(x, z, false); } + @Override + public void onHotload() + { + super.onHotload(); + } + @Override public int getHighest(int x, int z, boolean ignoreFluid) { @@ -163,6 +173,20 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple return new AtomicSliverMap(); } + @Override + public List getDefaultPopulators(World world) + { + List g = super.getDefaultPopulators(world); + + if(glUpdate == null) + { + glUpdate = new GenLayerUpdate(this, world); + } + + g.add(glUpdate); + return g; + } + @Override protected void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map) { @@ -178,11 +202,13 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple { onGenerateParallax(random, x, z); getParallaxChunk(x, z).inject(data); - setSliverBuffer(getSliverCache().size()); - getParallaxChunk(x, z).setWorldGenerated(true); - getMasterLock().clear(); } + getParallaxChunk(x, z).injectUpdates(map); + setSliverBuffer(getSliverCache().size()); + getParallaxChunk(x, z).setWorldGenerated(true); + getMasterLock().clear(); + p.end(); getMetrics().getParallax().put(p.getMilliseconds()); super.onPostParallaxPostGenerate(random, x, z, data, grid, height, biomeMap, map); diff --git a/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java b/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java index 4b46f672d..9880deae4 100644 --- a/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java +++ b/src/main/java/com/volmit/iris/gen/atomics/AtomicSliver.java @@ -101,7 +101,7 @@ public class AtomicSliver modified = true; block.put(h, d); - if(B.isLit(d)) + if(B.isUpdatable(d)) { update(h); } @@ -293,4 +293,9 @@ public class AtomicSliver { return M.ms() - last > m; } + + public void inject(KSet updatables) + { + update.addAll(updatables); + } } diff --git a/src/main/java/com/volmit/iris/gen/atomics/AtomicSliverMap.java b/src/main/java/com/volmit/iris/gen/atomics/AtomicSliverMap.java index 970b995ec..7ee88ee3f 100644 --- a/src/main/java/com/volmit/iris/gen/atomics/AtomicSliverMap.java +++ b/src/main/java/com/volmit/iris/gen/atomics/AtomicSliverMap.java @@ -114,4 +114,15 @@ public class AtomicSliverMap return false; } + + public void injectUpdates(AtomicSliverMap map) + { + for(int i = 0; i < 16; i++) + { + for(int j = 0; j < 16; j++) + { + getSliver(i, j).inject(map.getSliver(i, j).getUpdatables()); + } + } + } } diff --git a/src/main/java/com/volmit/iris/gen/layer/GenLayerUpdate.java b/src/main/java/com/volmit/iris/gen/layer/GenLayerUpdate.java new file mode 100644 index 000000000..a3530543c --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/layer/GenLayerUpdate.java @@ -0,0 +1,164 @@ +package com.volmit.iris.gen.layer; + +import java.util.Random; + +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; + +import com.volmit.iris.Iris; +import com.volmit.iris.gen.ParallaxChunkGenerator; +import com.volmit.iris.gen.atomics.AtomicSliverMap; +import com.volmit.iris.object.InventorySlotType; +import com.volmit.iris.object.IrisBiome; +import com.volmit.iris.object.IrisLootReference; +import com.volmit.iris.object.IrisLootTable; +import com.volmit.iris.object.IrisRegion; +import com.volmit.iris.object.LootMode; +import com.volmit.iris.util.B; +import com.volmit.iris.util.IrisStructureResult; +import com.volmit.iris.util.KList; +import com.volmit.iris.util.KSet; +import com.volmit.iris.util.PrecisionStopwatch; +import com.volmit.iris.util.RNG; + +public class GenLayerUpdate extends BlockPopulator +{ + private ParallaxChunkGenerator gen; + private RNG rng; + + public GenLayerUpdate(ParallaxChunkGenerator gen, World w) + { + this.gen = gen; + this.rng = new RNG(w.getSeed() + 4996788).nextParallelRNG(-98618289); + } + + @Override + public void populate(World w, Random r, Chunk c) + { + PrecisionStopwatch p = PrecisionStopwatch.start(); + AtomicSliverMap map = gen.getParallaxChunk(c.getX(), c.getZ()); + RNG rx = rng.nextParallelRNG(c.getX()).nextParallelRNG(c.getZ()); + + for(int i = 0; i < 16; i++) + { + for(int j = 0; j < 16; j++) + { + for(int k : map.getSliver(i, j).getUpdatables()) + { + if(k > 255 || k < 0) + { + continue; + } + + update(c, i, k, j, i + (c.getX() << 4), i + (c.getZ() << 4), rx); + } + } + } + p.end(); + gen.getMetrics().getUpdate().put(p.getMilliseconds()); + } + + public void update(Chunk c, int x, int y, int z, int rx, int rz, RNG rng) + { + Block b = c.getBlock(x, y, z); + BlockData d = b.getBlockData(); + + if(B.isLit(d.getMaterial())) + { + updateLight(b, d); + } + + else if(B.isStorage(d.getMaterial())) + { + updateStorage(b, d, rx, rz, rng); + } + } + + public void injectTables(KSet list, IrisLootReference r) + { + if(r.getMode().equals(LootMode.CLEAR) || r.getMode().equals(LootMode.REPLACE)) + { + list.clear(); + } + + list.addAll(r.getLootTables(gen)); + } + + public KSet getLootTables(Block b) + { + int rx = b.getX(); + int rz = b.getZ(); + IrisRegion region = gen.sampleRegion(rx, rz); + IrisBiome biomeSurface = gen.sampleTrueBiome(rx, rz).getBiome(); + IrisBiome biomeUnder = gen.sampleTrueBiome(rx, b.getY(), rz).getBiome(); + KSet tables = new KSet<>(); + IrisStructureResult structure = gen.getStructure(rx, b.getY(), rz); + injectTables(tables, gen.getDimension().getLoot()); + injectTables(tables, region.getLoot()); + injectTables(tables, biomeSurface.getLoot()); + injectTables(tables, biomeUnder.getLoot()); + + if(structure != null && structure.getTile() != null) + { + injectTables(tables, structure.getStructure().getLoot()); + injectTables(tables, structure.getTile().getLoot()); + } + + return tables; + } + + public void addItems(boolean debug, Inventory inv, RNG rng, KSet tables, InventorySlotType slot, int x, int y, int z) + { + KList items = new KList<>(); + + for(IrisLootTable i : tables) + { + items.addAll(i.getLoot(debug, rng, slot, x, y, z)); + } + + for(ItemStack i : items) + { + inv.addItem(i); + } + } + + public void updateStorage(Block b, BlockData data, int rx, int rz, RNG rng) + { + InventorySlotType slot = null; + + if(B.isStorageChest(data.getMaterial())) + { + slot = InventorySlotType.STORAGE; + } + + if(slot != null) + { + KSet tables = getLootTables(b); + + try + { + InventoryHolder m = (InventoryHolder) b.getState(); + addItems(false, m.getInventory(), rng, tables, slot, rx, b.getY(), rz); + } + + catch(Throwable e) + { + Iris.error("NOT INVENTORY: " + data.getMaterial().name()); + } + + } + } + + public void updateLight(Block b, BlockData data) + { + b.setType(Material.AIR, false); + b.setBlockData(data, false); + } +} diff --git a/src/main/java/com/volmit/iris/object/InventorySlotType.java b/src/main/java/com/volmit/iris/object/InventorySlotType.java new file mode 100644 index 000000000..a83d79be1 --- /dev/null +++ b/src/main/java/com/volmit/iris/object/InventorySlotType.java @@ -0,0 +1,21 @@ +package com.volmit.iris.object; + +import com.volmit.iris.util.DontObfuscate; + +public enum InventorySlotType +{ + @DontObfuscate + STORAGE, + + @DontObfuscate + FUEL, + + @DontObfuscate + FURNACE, + + @DontObfuscate + BLAST_FURNACE, + + @DontObfuscate + SMOKER, +} diff --git a/src/main/java/com/volmit/iris/object/IrisBiome.java b/src/main/java/com/volmit/iris/object/IrisBiome.java index 7850518d3..5e469df89 100644 --- a/src/main/java/com/volmit/iris/object/IrisBiome.java +++ b/src/main/java/com/volmit/iris/object/IrisBiome.java @@ -45,6 +45,10 @@ public class IrisBiome extends IrisRegistrant implements IRare @Desc("This changes the dispersion of the biome colors if multiple derivatives are chosen.") private IrisGeneratorStyle biomeStyle = NoiseStyle.SIMPLEX.style(); + @DontObfuscate + @Desc("Reference loot tables in this area") + private IrisLootReference loot = new IrisLootReference(); + @MinNumber(0.0001) @DontObfuscate @DependsOn({"biomeStyle", "biomeZoom", "biomeScatter"}) diff --git a/src/main/java/com/volmit/iris/object/IrisBiomeDecorator.java b/src/main/java/com/volmit/iris/object/IrisBiomeDecorator.java index 3c329db36..3684587c0 100644 --- a/src/main/java/com/volmit/iris/object/IrisBiomeDecorator.java +++ b/src/main/java/com/volmit/iris/object/IrisBiomeDecorator.java @@ -174,21 +174,14 @@ public class IrisBiomeDecorator return getBlockData().get(0); } - return getVarianceGenerator( - - rng.nextParallelRNG(44) - - ) - - .fit( - - getBlockData() - - , - - xx, - - zz); + CNG v = getVarianceGenerator(rng.nextParallelRNG(44)); + + if(v == null) + { + getBlockData().get(0); + } + + v.fit(getBlockData(), xx, zz); } return null; diff --git a/src/main/java/com/volmit/iris/object/IrisDimension.java b/src/main/java/com/volmit/iris/object/IrisDimension.java index 9fcc22e0c..00eef859a 100644 --- a/src/main/java/com/volmit/iris/object/IrisDimension.java +++ b/src/main/java/com/volmit/iris/object/IrisDimension.java @@ -42,6 +42,10 @@ public class IrisDimension extends IrisRegistrant @Desc("The human readable name of this dimension") private String name = "A Dimension"; + @DontObfuscate + @Desc("Reference loot tables in this area") + private IrisLootReference loot = new IrisLootReference(); + @Required @MinNumber(0) @DontObfuscate diff --git a/src/main/java/com/volmit/iris/object/IrisLoot.java b/src/main/java/com/volmit/iris/object/IrisLoot.java new file mode 100644 index 000000000..02232bdc1 --- /dev/null +++ b/src/main/java/com/volmit/iris/object/IrisLoot.java @@ -0,0 +1,115 @@ +package com.volmit.iris.object; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; + +import com.volmit.iris.Iris; +import com.volmit.iris.gen.atomics.AtomicCache; +import com.volmit.iris.noise.CNG; +import com.volmit.iris.util.B; +import com.volmit.iris.util.Desc; +import com.volmit.iris.util.DontObfuscate; +import com.volmit.iris.util.Form; +import com.volmit.iris.util.KList; +import com.volmit.iris.util.MaxNumber; +import com.volmit.iris.util.MinNumber; +import com.volmit.iris.util.RNG; +import com.volmit.iris.util.Required; + +import lombok.Data; +import net.md_5.bungee.api.ChatColor; + +@Desc("Represents a loot entry") +@Data +public class IrisLoot +{ + @DontObfuscate + @Desc("The target inventory slot types to fill this loot with") + private InventorySlotType slotTypes = InventorySlotType.STORAGE; + + @MinNumber(1) + @DontObfuscate + @Desc("The sub rarity of this loot. Calculated after this loot table has been picked.") + private int rarity = 1; + + @MinNumber(1) + @DontObfuscate + @Desc("Minimum amount of this loot") + private int minAmount = 1; + + @MinNumber(1) + @DontObfuscate + @Desc("Maximum amount of this loot") + private int maxAmount = 1; + + @MinNumber(0) + @MaxNumber(1) + @DontObfuscate + @Desc("Minimum durability percent") + private double minDurability = 0; + + @MinNumber(0) + @MaxNumber(1) + @DontObfuscate + @Desc("Maximum durability percent") + private double maxDurability = 1; + + @Required + @Desc("This is the item or block type. Does not accept minecraft:*. Only materials such as DIAMOND_SWORD or DIRT.") + private String type = ""; + + private transient AtomicCache chance = new AtomicCache<>(); + + public IrisLoot() + { + + } + + public Material getType() + { + return B.getMaterial(type); + } + + public ItemStack get(boolean debug, IrisLootTable table, RNG rng, int x, int y, int z) + { + if(debug) + { + chance.reset(); + } + + if(chance.aquire(() -> NoiseStyle.STATIC.create(rng)).fit(1, rarity * table.getRarity(), x, y, z) == 1) + { + if(getType() == null) + { + Iris.warn("Cant find item type " + type); + return null; + } + + ItemStack is = new ItemStack(getType(), Math.max(1, rng.i(getMinAmount(), getMaxAmount()))); + ItemMeta m = is.getItemMeta(); + + if(getType().getMaxDurability() > 0 && m instanceof Damageable) + { + Damageable d = (Damageable) m; + int max = getType().getMaxDurability(); + d.setDamage((int) Math.round(Math.max(0, Math.min(max, rng.d(getMinDurability(), getMaxDurability()) * max)))); + } + + KList lore = new KList<>(); + + if(debug) + { + lore.add("From Table: " + table.getName() + " (" + Form.pc(1D / table.getRarity(), 5) + ")"); + lore.add(ChatColor.GRAY + "1 in " + (table.getRarity() * getRarity()) + " Chance (" + Form.pc(1D / (table.getRarity() * getRarity()), 5) + ")"); + } + + m.setLore(lore); + is.setItemMeta(m); + return is; + } + + return null; + } +} diff --git a/src/main/java/com/volmit/iris/object/IrisLootReference.java b/src/main/java/com/volmit/iris/object/IrisLootReference.java new file mode 100644 index 000000000..5971c9e36 --- /dev/null +++ b/src/main/java/com/volmit/iris/object/IrisLootReference.java @@ -0,0 +1,48 @@ +package com.volmit.iris.object; + +import com.volmit.iris.gen.DimensionChunkGenerator; +import com.volmit.iris.gen.atomics.AtomicCache; +import com.volmit.iris.util.ArrayType; +import com.volmit.iris.util.Desc; +import com.volmit.iris.util.DontObfuscate; +import com.volmit.iris.util.KList; +import com.volmit.iris.util.RegistryListLoot; + +import lombok.Data; + +@Desc("Represents a loot entry") +@Data +public class IrisLootReference +{ + @DontObfuscate + @Desc("Add = add on top of parent tables, Replace = clear first then add these. Clear = Remove all and dont add loot from this or parent.") + private LootMode mode = LootMode.ADD; + + @DontObfuscate + @RegistryListLoot + @ArrayType(min = 1, type = String.class) + @Desc("Add loot table registries here") + private KList tables = new KList<>(); + + private transient AtomicCache> tt = new AtomicCache<>(); + + public IrisLootReference() + { + + } + + public KList getLootTables(DimensionChunkGenerator g) + { + return tt.aquire(() -> + { + KList t = new KList<>(); + + for(String i : tables) + { + t.add(g.getData().getLootLoader().load(i)); + } + + return t; + }); + } +} diff --git a/src/main/java/com/volmit/iris/object/IrisLootTable.java b/src/main/java/com/volmit/iris/object/IrisLootTable.java new file mode 100644 index 000000000..fb5004ddf --- /dev/null +++ b/src/main/java/com/volmit/iris/object/IrisLootTable.java @@ -0,0 +1,63 @@ +package com.volmit.iris.object; + +import org.bukkit.inventory.ItemStack; + +import com.volmit.iris.util.ArrayType; +import com.volmit.iris.util.Desc; +import com.volmit.iris.util.DontObfuscate; +import com.volmit.iris.util.KList; +import com.volmit.iris.util.MinNumber; +import com.volmit.iris.util.RNG; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Desc("Represents a loot table. Biomes, Regions & Objects can add or replace the virtual table with these loot tables") +@Data +@EqualsAndHashCode(callSuper = false) +public class IrisLootTable extends IrisRegistrant +{ + @Desc("The name of this loot table") + @DontObfuscate + @MinNumber(2) + private String name; + + @MinNumber(1) + @DontObfuscate + @Desc("The rarity as in 1 in X chance") + private int rarity = 1; + + @DontObfuscate + @Desc("The loot in this table") + @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) + { + KList lootf = new KList<>(); + + int m = 0; + + for(IrisLoot i : loot) + { + if(i.getSlotTypes().equals(slot)) + { + ItemStack item = i.get(debug, this, rng.nextParallelRNG(294788 + x + y - z * z + (m * -4125)), x, y, z); + + if(item != null) + { + lootf.add(item); + } + } + + m++; + } + + return lootf; + } + + public IrisLootTable() + { + + } +} diff --git a/src/main/java/com/volmit/iris/object/IrisObject.java b/src/main/java/com/volmit/iris/object/IrisObject.java index 8fc0fa01f..3f7b97d5f 100644 --- a/src/main/java/com/volmit/iris/object/IrisObject.java +++ b/src/main/java/com/volmit/iris/object/IrisObject.java @@ -309,7 +309,7 @@ public class IrisObject extends IrisRegistrant int yy = y + (int) Math.round(i.getY()); int zz = z + (int) Math.round(i.getZ()); - if(config.getMode().equals(ObjectPlaceMode.PAINT)) + if(config.getMode().equals(ObjectPlaceMode.PAINT) && paintmap != null) { yy = (int) Math.round(i.getY()) + Math.floorDiv(h, 2) + paintmap.compute(new ChunkPosition(xx, zz), (k, v) -> { diff --git a/src/main/java/com/volmit/iris/object/IrisRegion.java b/src/main/java/com/volmit/iris/object/IrisRegion.java index 0e17f211a..06268832c 100644 --- a/src/main/java/com/volmit/iris/object/IrisRegion.java +++ b/src/main/java/com/volmit/iris/object/IrisRegion.java @@ -52,6 +52,10 @@ public class IrisRegion extends IrisRegistrant implements IRare @Desc("The min shore height") private double shoreHeightMin = 1.2; + @DontObfuscate + @Desc("Reference loot tables in this area") + private IrisLootReference loot = new IrisLootReference(); + @MinNumber(0) @DontObfuscate @Desc("The the max shore height") diff --git a/src/main/java/com/volmit/iris/object/IrisStructure.java b/src/main/java/com/volmit/iris/object/IrisStructure.java index 91e568061..fe474d1a3 100644 --- a/src/main/java/com/volmit/iris/object/IrisStructure.java +++ b/src/main/java/com/volmit/iris/object/IrisStructure.java @@ -38,6 +38,10 @@ public class IrisStructure extends IrisRegistrant @Desc("This is the x and z size of each grid cell") private int gridSize = 11; + @DontObfuscate + @Desc("Reference loot tables in this area") + private IrisLootReference loot = new IrisLootReference(); + @Required @MinNumber(1) @MaxNumber(255) diff --git a/src/main/java/com/volmit/iris/object/IrisStructureTile.java b/src/main/java/com/volmit/iris/object/IrisStructureTile.java index d297dc39a..c660ff3a8 100644 --- a/src/main/java/com/volmit/iris/object/IrisStructureTile.java +++ b/src/main/java/com/volmit/iris/object/IrisStructureTile.java @@ -17,6 +17,10 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = false) public class IrisStructureTile { + @DontObfuscate + @Desc("Reference loot tables in this area") + private IrisLootReference loot = new IrisLootReference(); + @Required @DontObfuscate @Desc("Is this structure allowed to place if there is supposed to be a ceiling?") diff --git a/src/main/java/com/volmit/iris/object/LootMode.java b/src/main/java/com/volmit/iris/object/LootMode.java new file mode 100644 index 000000000..e3b140c75 --- /dev/null +++ b/src/main/java/com/volmit/iris/object/LootMode.java @@ -0,0 +1,15 @@ +package com.volmit.iris.object; + +import com.volmit.iris.util.DontObfuscate; + +public enum LootMode +{ + @DontObfuscate + ADD, + + @DontObfuscate + CLEAR, + + @DontObfuscate + REPLACE; +} diff --git a/src/main/java/com/volmit/iris/util/B.java b/src/main/java/com/volmit/iris/util/B.java index 67a6faf14..63991d327 100644 --- a/src/main/java/com/volmit/iris/util/B.java +++ b/src/main/java/com/volmit/iris/util/B.java @@ -14,12 +14,36 @@ public class B private static final KList nulls = new KList<>(); private static final IrisDimension defaultCompat = new IrisDimension(); private static final KMap solid = new KMap<>(); + private static final KMap types = new KMap<>(); public static BlockData get(String bd) { return getBlockData(bd); } + public static Material getMaterial(String bd) + { + return types.compute(bd, (k, v) -> + { + if(k != null && v != null) + { + return v; + } + + try + { + return Material.valueOf(k); + } + + catch(Throwable e) + { + + } + + return null; + }); + } + public static boolean isSolid(Material mat) { if(!solid.containsKey(mat)) @@ -114,19 +138,101 @@ public class B return AIR; } - public static boolean isLit(BlockData mat) + public static boolean isUpdatable(BlockData mat) { - return isLit(mat.getMaterial()); + return isUpdatable(mat.getMaterial()); + } + + public static boolean isStorage(Material mat) + { + //@builder + return mat.equals(B.mat("CHEST")) + || mat.equals(B.mat("TRAPPED_CHEST")) + || mat.equals(B.mat("SHULKER_BOX")) + || mat.equals(B.mat("WHITE_SHULKER_BOX")) + || mat.equals(B.mat("ORANGE_SHULKER_BOX")) + || mat.equals(B.mat("MAGENTA_SHULKER_BOX")) + || mat.equals(B.mat("LIGHT_BLUE_SHULKER_BOX")) + || mat.equals(B.mat("YELLOW_SHULKER_BOX")) + || mat.equals(B.mat("LIME_SHULKER_BOX")) + || mat.equals(B.mat("PINK_SHULKER_BOX")) + || mat.equals(B.mat("GRAY_SHULKER_BOX")) + || mat.equals(B.mat("LIGHT_GRAY_SHULKER_BOX")) + || mat.equals(B.mat("CYAN_SHULKER_BOX")) + || mat.equals(B.mat("PURPLE_SHULKER_BOX")) + || mat.equals(B.mat("BLUE_SHULKER_BOX")) + || mat.equals(B.mat("BROWN_SHULKER_BOX")) + || mat.equals(B.mat("GREEN_SHULKER_BOX")) + || mat.equals(B.mat("RED_SHULKER_BOX")) + || mat.equals(B.mat("BLACK_SHULKER_BOX")) + || mat.equals(B.mat("BARREL")) + || mat.equals(B.mat("DISPENSER")) + || mat.equals(B.mat("DROPPER")) + || mat.equals(B.mat("HOPPER")) + || mat.equals(B.mat("FURNACE")) + || mat.equals(B.mat("BLAST_FURNACE")) + || mat.equals(B.mat("SMOKER")); + //@done + } + + public static boolean isStorageChest(Material mat) + { + //@builder + return mat.equals(B.mat("CHEST")) + || mat.equals(B.mat("TRAPPED_CHEST")) + || mat.equals(B.mat("SHULKER_BOX")) + || mat.equals(B.mat("WHITE_SHULKER_BOX")) + || mat.equals(B.mat("ORANGE_SHULKER_BOX")) + || mat.equals(B.mat("MAGENTA_SHULKER_BOX")) + || mat.equals(B.mat("LIGHT_BLUE_SHULKER_BOX")) + || mat.equals(B.mat("YELLOW_SHULKER_BOX")) + || mat.equals(B.mat("LIME_SHULKER_BOX")) + || mat.equals(B.mat("PINK_SHULKER_BOX")) + || mat.equals(B.mat("GRAY_SHULKER_BOX")) + || mat.equals(B.mat("LIGHT_GRAY_SHULKER_BOX")) + || mat.equals(B.mat("CYAN_SHULKER_BOX")) + || mat.equals(B.mat("PURPLE_SHULKER_BOX")) + || mat.equals(B.mat("BLUE_SHULKER_BOX")) + || mat.equals(B.mat("BROWN_SHULKER_BOX")) + || mat.equals(B.mat("GREEN_SHULKER_BOX")) + || mat.equals(B.mat("RED_SHULKER_BOX")) + || mat.equals(B.mat("BLACK_SHULKER_BOX")) + || mat.equals(B.mat("BARREL")) + || mat.equals(B.mat("DISPENSER")) + || mat.equals(B.mat("DROPPER")) + || mat.equals(B.mat("HOPPER")); + //@done } public static boolean isLit(Material mat) { - if(mat.equals(B.mat("GLOWSTONE")) || mat.equals(B.mat("TORCH")) || mat.equals(Material.REDSTONE_TORCH) || mat.equals(B.mat("SOUL_TORCH")) || mat.equals(Material.REDSTONE_WALL_TORCH) || mat.equals(Material.WALL_TORCH) || mat.equals(B.mat("SOUL_WALL_TORCH")) || mat.equals(B.mat("LANTERN")) || mat.equals(Material.JACK_O_LANTERN) || mat.equals(Material.REDSTONE_LAMP) || mat.equals(Material.MAGMA_BLOCK) || mat.equals(B.mat("SEA_LANTERN")) || mat.equals(B.mat("SOUL_LANTERN")) || mat.equals(Material.FIRE) || mat.equals(B.mat("SOUL_FIRE")) || mat.equals(B.mat("SEA_PICKLE")) || mat.equals(Material.BREWING_STAND) || mat.equals(Material.REDSTONE_ORE)) - { - return true; - } + //@builder + return mat.equals(B.mat("GLOWSTONE")) + || mat.equals(B.mat("END_ROD")) + || mat.equals(B.mat("SOUL_SAND")) + || mat.equals(B.mat("TORCH")) + || mat.equals(Material.REDSTONE_TORCH) + || mat.equals(B.mat("SOUL_TORCH")) + || mat.equals(Material.REDSTONE_WALL_TORCH) + || mat.equals(Material.WALL_TORCH) + || mat.equals(B.mat("SOUL_WALL_TORCH")) + || mat.equals(B.mat("LANTERN")) + || mat.equals(Material.JACK_O_LANTERN) + || mat.equals(Material.REDSTONE_LAMP) + || mat.equals(Material.MAGMA_BLOCK) + || mat.equals(B.mat("SEA_LANTERN")) + || mat.equals(B.mat("SOUL_LANTERN")) + || mat.equals(Material.FIRE) + || mat.equals(B.mat("SOUL_FIRE")) + || mat.equals(B.mat("SEA_PICKLE")) + || mat.equals(Material.BREWING_STAND) + || mat.equals(Material.REDSTONE_ORE); + //@done + } - return false; + public static boolean isUpdatable(Material mat) + { + return isLit(mat) || isStorage(mat); } public static boolean canPlaceOnto(Material mat, Material onto) diff --git a/src/main/java/com/volmit/iris/util/RegistryListLoot.java b/src/main/java/com/volmit/iris/util/RegistryListLoot.java new file mode 100644 index 000000000..a62b8f874 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/RegistryListLoot.java @@ -0,0 +1,14 @@ +package com.volmit.iris.util; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target({PARAMETER, TYPE, FIELD}) +public @interface RegistryListLoot +{ + +}