From 44358c122fa821f807a95e1ddbe74752d7d7803f Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Mon, 2 Nov 2020 12:29:55 -0500 Subject: [PATCH] Block Updates (not yet working) --- .../volmit/iris/object/IrisLootReference.java | 3 +- .../volmit/iris/v2/generator/IrisEngine.java | 195 +++++++++++++++++- .../iris/v2/generator/IrisEngineCompound.java | 27 ++- .../iris/v2/scaffold/engine/Engine.java | 4 + .../engine/EngineCompositeGenerator.java | 20 +- .../v2/scaffold/engine/EngineCompound.java | 4 + .../volmit/iris/v2/scaffold/hunk/Hunk.java | 5 + .../v2/scaffold/hunk/view/ListeningHunk.java | 54 +++++ 8 files changed, 298 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/volmit/iris/v2/scaffold/hunk/view/ListeningHunk.java diff --git a/src/main/java/com/volmit/iris/object/IrisLootReference.java b/src/main/java/com/volmit/iris/object/IrisLootReference.java index c488a3e38..f1ebeef52 100644 --- a/src/main/java/com/volmit/iris/object/IrisLootReference.java +++ b/src/main/java/com/volmit/iris/object/IrisLootReference.java @@ -9,6 +9,7 @@ import com.volmit.iris.util.KList; import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.RegistryListLoot; +import com.volmit.iris.v2.scaffold.data.DataProvider; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -39,7 +40,7 @@ public class IrisLootReference private final transient AtomicCache> tt = new AtomicCache<>(); - public KList getLootTables(DimensionalTerrainProvider g) + public KList getLootTables(DataProvider g) { return tt.aquire(() -> { diff --git a/src/main/java/com/volmit/iris/v2/generator/IrisEngine.java b/src/main/java/com/volmit/iris/v2/generator/IrisEngine.java index b57ad2506..9962ed12f 100644 --- a/src/main/java/com/volmit/iris/v2/generator/IrisEngine.java +++ b/src/main/java/com/volmit/iris/v2/generator/IrisEngine.java @@ -1,22 +1,35 @@ package com.volmit.iris.v2.generator; import com.volmit.iris.Iris; -import com.volmit.iris.util.J; -import com.volmit.iris.util.M; +import com.volmit.iris.object.*; +import com.volmit.iris.util.*; +import com.volmit.iris.v2.scaffold.cache.Cache; import com.volmit.iris.v2.scaffold.engine.Engine; import com.volmit.iris.v2.scaffold.engine.EngineFramework; import com.volmit.iris.v2.scaffold.engine.EngineTarget; import com.volmit.iris.v2.scaffold.hunk.Hunk; import com.volmit.iris.v2.scaffold.parallel.MultiBurst; +import io.papermc.lib.PaperLib; import lombok.Getter; import lombok.Setter; import net.minecraft.server.v1_16_R2.*; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Biome; +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 org.jetbrains.annotations.NotNull; +import java.util.Arrays; import java.util.Iterator; +import java.util.Random; -public class IrisEngine implements Engine +public class IrisEngine extends BlockPopulator implements Engine { @Getter private final EngineTarget target; @@ -28,15 +41,21 @@ public class IrisEngine implements Engine @Getter private volatile int parallelism; + @Setter + @Getter + private volatile int minHeight; + public IrisEngine(EngineTarget target) { Iris.info("Initializing Engine: " + target.getWorld().getName() + "/" + target.getDimension().getLoadKey() + " (" + target.getHeight() + " height)"); this.target = target; this.framework = new IrisEngineFramework(this); + minHeight = 0; } @Override - public void generate(int x, int z, Hunk blocks, Hunk biomes) { + public void generate(int x, int z, Hunk vblocks, Hunk biomes) { + Hunk blocks = vblocks.listen(this::catchBlockUpdates); getFramework().getEngineParallax().generateParallaxArea(x, z); getFramework().getBiomeActuator().actuate(x, z, biomes); getFramework().getTerrainActuator().actuate(x, z, blocks); @@ -47,4 +66,172 @@ public class IrisEngine implements Engine getFramework().getEngineParallax().insertParallax(x, z, blocks); getFramework().recycle(); } + + private void catchBlockUpdates(int x, int y, int z, BlockData data) { + if(B.isUpdatable(data)) + { + getParallax().updateBlock(x,y,z); + } + } + + @Override + public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk c) + { + RNG rx = new RNG(Cache.key(c.getX(), c.getZ())); + getParallax().getUpdatesR(c.getX(), c.getZ()).iterate(0, (x,y,z) -> update(x, getMinHeight() + y, z, c, rx)); + } + + private void update(int x, int y, int z, Chunk c, RNG rf) + { + Block block = c.getBlock(x,y,z); + BlockData data = block.getBlockData(); + + if(B.isStorage(data)) + { + RNG rx = rf.nextParallelRNG(x).nextParallelRNG(z).nextParallelRNG(y); + block.setType(Material.AIR, false); + block.setBlockData(data, true); + InventorySlotType slot = null; + + if(B.isStorageChest(data)) + { + slot = InventorySlotType.STORAGE; + } + + if(slot != null) + { + KList tables = getLootTables(rx.nextParallelRNG(4568111), block); + InventorySlotType slott = slot; + + try + { + InventoryHolder m = (InventoryHolder) block.getState(); + addItems(false, m.getInventory(), rx, tables, slott, x, y, z, 15); + } + + catch(Throwable ignored) + { + + } + } + } + + else if(B.isLit(data)) + { + block.setType(Material.AIR, false); + block.setBlockData(data, true); + } + } + + + + public void scramble(Inventory inventory, RNG rng) + { + org.bukkit.inventory.ItemStack[] items = inventory.getContents(); + org.bukkit.inventory.ItemStack[] nitems = new org.bukkit.inventory.ItemStack[inventory.getSize()]; + System.arraycopy(items, 0, nitems, 0, items.length); + boolean packedFull = false; + + splitting: for(int i = 0; i < nitems.length; i++) + { + ItemStack is = nitems[i]; + + if(is != null && is.getAmount() > 1 && !packedFull) + { + for(int j = 0; j < nitems.length; j++) + { + if(nitems[j] == null) + { + int take = rng.nextInt(is.getAmount()); + take = take == 0 ? 1 : take; + is.setAmount(is.getAmount() - take); + nitems[j] = is.clone(); + nitems[j].setAmount(take); + continue splitting; + } + } + + packedFull = true; + } + } + + for(int i = 0; i < 4; i++) + { + try + { + Arrays.parallelSort(nitems, (a, b) -> rng.nextInt()); + break; + } + + catch(Throwable e) + { + + } + } + + inventory.setContents(nitems); + } + + public void injectTables(KList list, IrisLootReference r) + { + if(r.getMode().equals(LootMode.CLEAR) || r.getMode().equals(LootMode.REPLACE)) + { + list.clear(); + } + + list.addAll(r.getLootTables(getFramework().getComplex())); + } + + public KList getLootTables(RNG rng, Block b) + { + int rx = b.getX(); + int rz = b.getZ(); + double he = getFramework().getComplex().getHeightStream().get(rx, rz); + IrisRegion region = getFramework().getComplex().getRegionStream().get(rx, rz); + IrisBiome biomeSurface = getFramework().getComplex().getTrueBiomeStream().get(rx, rz); + IrisBiome biomeUnder = b.getY() < he ? getFramework().getComplex().getCaveBiomeStream().get(rx, rz) : biomeSurface; + KList tables = new KList<>(); + double multiplier = 1D * getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier(); + injectTables(tables, getDimension().getLoot()); + injectTables(tables, region.getLoot()); + injectTables(tables, biomeSurface.getLoot()); + injectTables(tables, biomeUnder.getLoot()); + + if(tables.isNotEmpty()) + { + int target = (int) Math.round(tables.size() * multiplier); + + while(tables.size() < target && tables.isNotEmpty()) + { + tables.add(tables.get(rng.i(tables.size() - 1))); + } + + while(tables.size() > target && tables.isNotEmpty()) + { + tables.remove(rng.i(tables.size() - 1)); + } + } + + return tables; + } + + public void addItems(boolean debug, Inventory inv, RNG rng, KList tables, InventorySlotType slot, int x, int y, int z, int mgf) + { + KList items = new KList<>(); + + int b = 4; + for(IrisLootTable i : tables) + { + b++; + items.addAll(i.getLoot(debug, items.isEmpty(), rng.nextParallelRNG(345911), slot, x, y, z, b + b, mgf + b)); + } + + for(ItemStack i : items) + { + inv.addItem(i); + } + + scramble(inv, rng); + } + } diff --git a/src/main/java/com/volmit/iris/v2/generator/IrisEngineCompound.java b/src/main/java/com/volmit/iris/v2/generator/IrisEngineCompound.java index 49d1f03d5..caca6e827 100644 --- a/src/main/java/com/volmit/iris/v2/generator/IrisEngineCompound.java +++ b/src/main/java/com/volmit/iris/v2/generator/IrisEngineCompound.java @@ -20,6 +20,7 @@ import org.bukkit.block.data.BlockData; import org.bukkit.craftbukkit.v1_16_R2.generator.CraftChunkData; import org.bukkit.event.EventHandler; import org.bukkit.event.world.WorldSaveEvent; +import org.bukkit.generator.BlockPopulator; import java.io.File; import java.util.concurrent.atomic.AtomicInteger; @@ -37,15 +38,20 @@ public class IrisEngineCompound implements EngineCompound { @Getter private final MultiBurst burster; - private IrisDimension root; + @Getter + private final KList populators; + + @Getter + private final IrisDimension rootDimension; public IrisEngineCompound(World world, IrisDimension rootDimension, IrisDataManager data, int maximumThreads) { - this.root = rootDimension; + this.rootDimension = rootDimension; Iris.info("Initializing Engine Composite for " + world.getName()); this.world = world; engineMetadata = EngineData.load(getEngineMetadataFile()); saveEngineMetadata(); + populators = new KList<>(); if(rootDimension.getDimensionalComposite().isEmpty()) { @@ -70,11 +76,23 @@ public class IrisEngineCompound implements EngineCompound { totalWeight += i.getWeight(); } + int buf = 0; + for(int i = 0; i < engines.length; i++) { IrisDimensionIndex index = rootDimension.getDimensionalComposite().get(i); IrisDimension dimension = data.getDimensionLoader().load(index.getDimension()); engines[i] = new IrisEngine(new EngineTarget(world, dimension, data.copy().preferFolder(rootDimension.getLoadKey()), (int)Math.floor(256D * (index.getWeight() / totalWeight)), index.isInverted(), threadDist)); + engines[i].setMinHeight(buf); + buf += engines[i].getHeight(); + } + } + + for(Engine i : engines) + { + if(i instanceof BlockPopulator) + { + populators.add((BlockPopulator) i); } } @@ -94,11 +112,6 @@ public class IrisEngineCompound implements EngineCompound { return new File(world.getWorldFolder(), "iris/engine-metadata.json"); } - @Override - public IrisDimension getRootDimension() { - return root; - } - @Override public void generate(int x, int z, Hunk blocks, Hunk biomes) { diff --git a/src/main/java/com/volmit/iris/v2/scaffold/engine/Engine.java b/src/main/java/com/volmit/iris/v2/scaffold/engine/Engine.java index f32b8977e..9a01b771a 100644 --- a/src/main/java/com/volmit/iris/v2/scaffold/engine/Engine.java +++ b/src/main/java/com/volmit/iris/v2/scaffold/engine/Engine.java @@ -19,6 +19,10 @@ public interface Engine public EngineFramework getFramework(); + public void setMinHeight(int min); + + public int getMinHeight(); + default void save() { getParallax().saveAll(); diff --git a/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompositeGenerator.java b/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompositeGenerator.java index 4eed9477b..f54a7ee97 100644 --- a/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompositeGenerator.java +++ b/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompositeGenerator.java @@ -6,9 +6,10 @@ import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; import com.volmit.iris.gen.scaffold.TerrainChunk; +import com.volmit.iris.util.KList; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.WorldCreator; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; import org.bukkit.generator.BlockPopulator; @@ -29,6 +30,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements Hotloada private final AtomicBoolean initialized; private final String dimensionHint; private final boolean production; + private final KList populators; public EngineCompositeGenerator() { this(null, true); @@ -39,6 +41,18 @@ public class EngineCompositeGenerator extends ChunkGenerator implements Hotloada this.production = production; this.dimensionHint = hint; initialized = new AtomicBoolean(false); + populators = new KList().qadd(new BlockPopulator() { + @Override + public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) { + if(compound != null) + { + for(BlockPopulator i : compound.getPopulators()) + { + i.populate(world, random, chunk); + } + } + } + }); } public void hotload() @@ -106,6 +120,8 @@ public class EngineCompositeGenerator extends ChunkGenerator implements Hotloada data.preferFolder(dim.getLoadKey()); compound = new IrisEngineCompound(world, dim, data, Iris.getThreadCount()); initialized.set(true); + populators.clear(); + populators.addAll(compound.getPopulators()); } private File getDataFolder(World world) { @@ -138,7 +154,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements Hotloada @NotNull @Override public List getDefaultPopulators(@NotNull World world) { - return super.getDefaultPopulators(world); + return populators; } @Nullable diff --git a/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompound.java b/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompound.java index 55242c46a..ad0626b29 100644 --- a/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompound.java +++ b/src/main/java/com/volmit/iris/v2/scaffold/engine/EngineCompound.java @@ -1,6 +1,7 @@ package com.volmit.iris.v2.scaffold.engine; import com.volmit.iris.object.IrisDimension; +import com.volmit.iris.util.KList; import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; @@ -8,6 +9,7 @@ import org.bukkit.event.Listener; import com.volmit.iris.v2.scaffold.hunk.Hunk; import com.volmit.iris.v2.scaffold.parallel.MultiBurst; +import org.bukkit.generator.BlockPopulator; public interface EngineCompound extends Listener { @@ -27,6 +29,8 @@ public interface EngineCompound extends Listener public void saveEngineMetadata(); + public KList getPopulators(); + default Engine getEngineForHeight(int height) { if(getSize() == 1) diff --git a/src/main/java/com/volmit/iris/v2/scaffold/hunk/Hunk.java b/src/main/java/com/volmit/iris/v2/scaffold/hunk/Hunk.java index 1d2189b57..78ffd72f9 100644 --- a/src/main/java/com/volmit/iris/v2/scaffold/hunk/Hunk.java +++ b/src/main/java/com/volmit/iris/v2/scaffold/hunk/Hunk.java @@ -68,6 +68,11 @@ public interface Hunk return newCombinedArrayHunk(hunks); } + default Hunk listen(Consumer4 l) + { + return new ListeningHunk<>(this, l); + } + public static Hunk newArrayHunk(int w, int h, int d) { return new ArrayHunk<>(w, h, d); diff --git a/src/main/java/com/volmit/iris/v2/scaffold/hunk/view/ListeningHunk.java b/src/main/java/com/volmit/iris/v2/scaffold/hunk/view/ListeningHunk.java new file mode 100644 index 000000000..c08eb53db --- /dev/null +++ b/src/main/java/com/volmit/iris/v2/scaffold/hunk/view/ListeningHunk.java @@ -0,0 +1,54 @@ +package com.volmit.iris.v2.scaffold.hunk.view; + +import com.volmit.iris.util.B; +import com.volmit.iris.util.Consumer4; +import com.volmit.iris.v2.scaffold.hunk.Hunk; +import org.checkerframework.checker.units.qual.A; + +public class ListeningHunk implements Hunk { + private final Hunk src; + private final Consumer4 listener; + + public ListeningHunk(Hunk src, Consumer4 listener) + { + this.src = src; + this.listener = listener; + } + + @Override + public void setRaw(int x, int y, int z, T t) + { + listener.accept(x,y,z,t); + src.setRaw(x,y,z,t); + } + + @Override + public T getRaw(int x, int y, int z) + { + return src.getRaw(x, y, z); + } + + @Override + public int getWidth() + { + return src.getWidth(); + } + + @Override + public int getHeight() + { + return src.getHeight(); + } + + @Override + public int getDepth() + { + return src.getDepth(); + } + + @Override + public Hunk getSource() + { + return src; + } +}