diff --git a/build.gradle b/build.gradle index 2f0920924..1e24647ea 100644 --- a/build.gradle +++ b/build.gradle @@ -87,7 +87,6 @@ shadowJar { dependsOn(":nms:${it.key}:remap") from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}-mapped.jar") } - NMS_BINDINGS.each {dependsOn(":nms:${it.key}:build")} //dependsOn(':com.volmit.gui:build') //minimize() @@ -137,9 +136,9 @@ allprojects { // Shaded implementation 'com.dfsek:Paralithic:0.4.0' implementation 'io.papermc:paperlib:1.0.5' - implementation "net.kyori:adventure-text-minimessage:4.13.1" + implementation "net.kyori:adventure-text-minimessage:4.17.0" implementation 'net.kyori:adventure-platform-bukkit:4.3.4' - implementation 'net.kyori:adventure-api:4.13.1' + implementation 'net.kyori:adventure-api:4.17.0' //implementation 'org.bytedeco:javacpp:1.5.10' //implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10' //implementation "org.deeplearning4j:deeplearning4j-core:1.0.0-M2.1" diff --git a/core/src/main/java/com/volmit/iris/core/IrisSettings.java b/core/src/main/java/com/volmit/iris/core/IrisSettings.java index f3cd720dd..46f088854 100644 --- a/core/src/main/java/com/volmit/iris/core/IrisSettings.java +++ b/core/src/main/java/com/volmit/iris/core/IrisSettings.java @@ -181,6 +181,7 @@ public class IrisSettings { public static class IrisSettingsGUI { public boolean useServerLaunchedGuis = true; public boolean maximumPregenGuiFPS = false; + public boolean colorMode = true; } @Data diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java index 7207af562..59e50ae70 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java @@ -19,7 +19,6 @@ package com.volmit.iris.core.commands; import com.volmit.iris.Iris; -import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.tools.IrisPackBenchmarking; import com.volmit.iris.core.tools.IrisToolbelt; @@ -35,8 +34,6 @@ import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.io.IO; import com.volmit.iris.util.mantle.TectonicPlate; -import com.volmit.iris.util.nbt.mca.MCAFile; -import com.volmit.iris.util.nbt.mca.MCAUtil; import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.plugin.VolmitSender; import net.jpountz.lz4.LZ4BlockInputStream; diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java b/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java index 98343d02d..8587f594a 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandObject.java @@ -24,6 +24,7 @@ import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.service.ObjectSVC; import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.WandSVC; +import com.volmit.iris.core.tools.IrisConverter; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.object.*; import com.volmit.iris.util.data.Cuboid; @@ -211,6 +212,16 @@ public class CommandObject implements DecreeExecutor { } } + @Decree(description = "Convert .schem files in the 'convert' folder to .iob files.") + public void convert () { + try { + IrisConverter.convertSchematics(sender()); + } catch (Exception e) { + e.printStackTrace(); + } + + } + @Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d") public void dust() { player().getInventory().addItem(WandSVC.createDust()); @@ -382,7 +393,7 @@ public class CommandObject implements DecreeExecutor { return; } try { - o.write(file); + o.write(file, sender()); } catch (IOException e) { sender().sendMessage(C.RED + "Failed to save object because of an IOException: " + e.getMessage()); Iris.reportError(e); diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java index be61b0462..53051bccb 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java @@ -50,6 +50,7 @@ import com.volmit.iris.util.math.Spiraler; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.plugin.VolmitSender; +import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.O; import com.volmit.iris.util.scheduling.jobs.QueueJob; @@ -57,6 +58,7 @@ import io.papermc.lib.PaperLib; import org.bukkit.*; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.BlockVector; import org.bukkit.util.Vector; @@ -71,6 +73,7 @@ import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.Date; import java.util.Objects; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.Supplier; @@ -328,7 +331,7 @@ public class CommandStudio implements DecreeExecutor { @Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER) - public void distances(@Param(description = "The radius") int radius) { + public void distances(@Param(description = "The radius in chunks") int radius) { var engine = engine(); if (engine == null) { sender().sendMessage(C.RED + "Only works in an Iris world!"); @@ -342,15 +345,24 @@ public class CommandStudio implements DecreeExecutor { sender.sendMessage(C.GRAY + "Generating data..."); var loc = player().getLocation(); + int totalTasks = d * d; + AtomicInteger completedTasks = new AtomicInteger(0); + int c = J.ar(() -> { + sender.sendProgress((double) completedTasks.get() / totalTasks, "Finding structures"); + }, 0); + new Spiraler(d, d, (x, z) -> executor.queue(() -> { var struct = engine.getStructureAt(x, z); if (struct != null) { data.computeIfAbsent(struct.getLoadKey(), (k) -> new KList<>()).add(new Position2(x, z)); } + completedTasks.incrementAndGet(); })).setOffset(loc.getBlockX(), loc.getBlockZ()).drain(); executor.complete(); multiBurst.close(); + J.car(c); + for (var key : data.keySet()) { var list = data.get(key); KList distances = new KList<>(list.size() - 1); @@ -383,6 +395,7 @@ public class CommandStudio implements DecreeExecutor { } } + @Decree(description = "Render a world map (External GUI)", aliases = "render") public void map() { if (noGUI()) return; diff --git a/core/src/main/java/com/volmit/iris/core/gui/NoiseExplorerGUI.java b/core/src/main/java/com/volmit/iris/core/gui/NoiseExplorerGUI.java index 1e3035cc6..017f7e42d 100644 --- a/core/src/main/java/com/volmit/iris/core/gui/NoiseExplorerGUI.java +++ b/core/src/main/java/com/volmit/iris/core/gui/NoiseExplorerGUI.java @@ -19,6 +19,7 @@ package com.volmit.iris.core.gui; import com.volmit.iris.Iris; +import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.events.IrisEngineHotloadEvent; import com.volmit.iris.engine.object.NoiseStyle; import com.volmit.iris.util.collection.KList; @@ -61,7 +62,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List @SuppressWarnings("CanBeFinal") RollingSequence r = new RollingSequence(20); @SuppressWarnings("CanBeFinal") - boolean colorMode = true; + boolean colorMode = IrisSettings.get().getGui().colorMode; double scale = 1; CNG cng = NoiseStyle.STATIC.create(new RNG(RNG.r.nextLong())); @SuppressWarnings("CanBeFinal") @@ -274,7 +275,10 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener, List n = n > 1 ? 1 : n < 0 ? 0 : n; try { - Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n); + //Color color = colorMode ? Color.getHSBColor((float) (n), 1f - (float) (n * n * n * n * n * n), 1f - (float) n) : Color.getHSBColor(0f, 0f, (float) n); + //Color color = colorMode ? Color.getHSBColor((float) (n), (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n); + Color color = colorMode ? Color.getHSBColor((float) n, (float) (n * n * n * n * n * n), (float) n) : Color.getHSBColor(0f, 0f, (float) n); + int rgb = color.getRGB(); img.setRGB(xx, z, rgb); } catch (Throwable ignored) { diff --git a/core/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java b/core/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java index b7e961e52..ef2a8359e 100644 --- a/core/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java +++ b/core/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java @@ -92,7 +92,12 @@ public class PregeneratorJob implements PregenListener { open(); } - J.a(this.pregenerator::start, 20); + var t = new Thread(() -> { + J.sleep(1000); + this.pregenerator.start(); + }, "Iris Pregenerator"); + t.setPriority(Thread.MIN_PRIORITY); + t.start(); } diff --git a/core/src/main/java/com/volmit/iris/core/link/MMOItemsDataProvider.java b/core/src/main/java/com/volmit/iris/core/link/MMOItemsDataProvider.java index 2e4f8c52a..8cbcab37e 100644 --- a/core/src/main/java/com/volmit/iris/core/link/MMOItemsDataProvider.java +++ b/core/src/main/java/com/volmit/iris/core/link/MMOItemsDataProvider.java @@ -23,6 +23,7 @@ import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.scheduling.J; import net.Indyuce.mmoitems.MMOItems; +import net.Indyuce.mmoitems.api.ItemTier; import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.block.CustomBlock; import org.bukkit.Bukkit; @@ -66,8 +67,13 @@ public class MMOItemsDataProvider extends ExternalDataProvider { Runnable run = () -> { try { var type = api().getTypes().get(parts[1]); - int level = customNbt.containsKey("level") ? (int) customNbt.get("level") : -1; - var tier = api().getTiers().get(String.valueOf(customNbt.get("tier"))); + int level = -1; + ItemTier tier = null; + + if (customNbt != null) { + level = (int) customNbt.getOrDefault("level", -1); + tier = api().getTiers().get(String.valueOf(customNbt.get("tier"))); + } ItemStack itemStack; if (type == null) { diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java index b6cb55102..b5bbb4305 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java @@ -22,7 +22,6 @@ import com.volmit.iris.Iris; import com.volmit.iris.core.pregenerator.PregenListener; import com.volmit.iris.core.pregenerator.PregeneratorMethod; import com.volmit.iris.core.tools.IrisToolbelt; -import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.mantle.Mantle; @@ -35,14 +34,11 @@ import org.bukkit.World; import java.util.ArrayList; import java.util.Map; -import java.util.Objects; import java.util.concurrent.Future; public class AsyncPregenMethod implements PregeneratorMethod { private final World world; - private final Engine engine; private final MultiBurst burst; - private final KList> future; private final Map lastUse; @@ -51,9 +47,8 @@ public class AsyncPregenMethod implements PregeneratorMethod { throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!"); } this.world = world; - this.engine = IrisToolbelt.access(world).getEngine(); - burst = new MultiBurst("AsyncPregen", 8 ); - future = new KList<>(1024); + burst = new MultiBurst("Iris Async Pregen", Thread.MIN_PRIORITY); + future = new KList<>(256); this.lastUse = new KMap<>(); } @@ -81,22 +76,18 @@ public class AsyncPregenMethod implements PregeneratorMethod { private void completeChunk(int x, int z, PregenListener listener) { try { - future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> { - if (i == null) return 0; + PaperLib.getChunkAtAsync(world, x, z, true).thenAccept((i) -> { lastUse.put(i, M.ms()); listener.onChunkGenerated(x, z); listener.onChunkCleaned(x, z); - return 0; - })); - + }).get(); + } catch (InterruptedException ignored) { } catch (Throwable e) { e.printStackTrace(); } } private void waitForChunksPartial(int maxWaiting) { - future.removeWhere(Objects::isNull); - while (future.size() > maxWaiting) { try { Future i = future.remove(0); @@ -125,8 +116,6 @@ public class AsyncPregenMethod implements PregeneratorMethod { e.printStackTrace(); } } - - future.removeWhere(Objects::isNull); } @Override @@ -143,6 +132,7 @@ public class AsyncPregenMethod implements PregeneratorMethod { public void close() { waitForChunks(); unloadAndSaveAllChunks(); + burst.close(); } @Override diff --git a/core/src/main/java/com/volmit/iris/core/service/WandSVC.java b/core/src/main/java/com/volmit/iris/core/service/WandSVC.java index b1ba81544..68eca93ee 100644 --- a/core/src/main/java/com/volmit/iris/core/service/WandSVC.java +++ b/core/src/main/java/com/volmit/iris/core/service/WandSVC.java @@ -35,8 +35,8 @@ import com.volmit.iris.util.plugin.IrisService; import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.SR; +import com.volmit.iris.util.scheduling.jobs.Job; import org.bukkit.*; -import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -57,8 +57,8 @@ import java.util.concurrent.CountDownLatch; public class WandSVC implements IrisService { private static final Particle CRIT_MAGIC = E.getOrDefault(Particle.class, "CRIT_MAGIC", "CRIT"); - private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST"); - private static final int BLOCKS_PER_TICK = Integer.parseInt(System.getProperty("iris.blocks_per_tick", "1000")); + private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST"); + private static final int MS_PER_TICK = Integer.parseInt(System.getProperty("iris.ms_per_tick", "30")); private static ItemStack dust; private static ItemStack wand; @@ -83,28 +83,80 @@ public class WandSVC implements IrisService { Cuboid c = new Cuboid(f[0], f[1]); IrisObject s = new IrisObject(c.getSizeX(), c.getSizeY(), c.getSizeZ()); - var it = c.iterator(); + var it = c.chunkedIterator(); + + int total = c.getSizeX() * c.getSizeY() * c.getSizeZ(); var latch = new CountDownLatch(1); - new SR() { + new Job() { + private int i; + private Chunk chunk; + @Override - public void run() { - for (int i = 0; i < BLOCKS_PER_TICK; i++) { - if (!it.hasNext()) { - cancel(); - latch.countDown(); - return; - } - - var b = it.next(); - if (b.getType().equals(Material.AIR)) - continue; - - BlockVector bv = b.getLocation().subtract(c.getLowerNE().toVector()).toVector().toBlockVector(); - s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b); - } + public String getName() { + return "Scanning Selection"; } - }; - latch.await(); + + @Override + public void execute() { + new SR() { + @Override + public void run() { + var time = M.ms() + MS_PER_TICK; + while (time > M.ms()) { + if (!it.hasNext()) { + if (chunk != null) { + chunk.removePluginChunkTicket(Iris.instance); + chunk = null; + } + + cancel(); + latch.countDown(); + return; + } + + try { + var b = it.next(); + var bChunk = b.getChunk(); + if (chunk == null) { + chunk = bChunk; + chunk.addPluginChunkTicket(Iris.instance); + } else if (chunk != bChunk) { + chunk.removePluginChunkTicket(Iris.instance); + chunk = bChunk; + } + + if (b.getType().equals(Material.AIR)) + continue; + + BlockVector bv = b.getLocation().subtract(c.getLowerNE().toVector()).toVector().toBlockVector(); + s.setUnsigned(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), b); + } finally { + i++; + } + } + } + }; + try { + latch.await(); + } catch (InterruptedException ignored) {} + } + + @Override + public void completeWork() {} + + @Override + public int getTotalWork() { + return total; + } + + @Override + public int getWorkCompleted() { + return i; + } + }.execute(new VolmitSender(p), true, () -> {}); + try { + latch.await(); + } catch (InterruptedException ignored) {} return s; } catch (Throwable e) { 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 1bba33d17..de896c764 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 @@ -19,7 +19,7 @@ package com.volmit.iris.core.tools; import com.volmit.iris.Iris; -import com.volmit.iris.engine.object.IrisObject; +import com.volmit.iris.engine.object.*; import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.nbt.io.NBTUtil; @@ -28,15 +28,14 @@ import com.volmit.iris.util.nbt.tag.*; import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.PrecisionStopwatch; +import org.apache.commons.io.FileUtils; import org.bukkit.Bukkit; import org.bukkit.block.data.BlockData; -import org.bukkit.util.Vector; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -48,11 +47,15 @@ public class IrisConverter { FilenameFilter filter = (dir, name) -> name.endsWith(".schem"); File[] fileList = folder.listFiles(filter); + if (fileList == null) { + sender.sendMessage("No schematic files to convert found in " + folder.getAbsolutePath()); + return; + } ExecutorService executorService = Executors.newFixedThreadPool(1); executorService.submit(() -> { - for (File schem : fileList) { - try { - PrecisionStopwatch p = new PrecisionStopwatch(); + for (File schem : fileList) { + try { + PrecisionStopwatch p = PrecisionStopwatch.start(); boolean largeObject = false; NamedTag tag = null; try { @@ -63,346 +66,84 @@ public class IrisConverter { } CompoundTag compound = (CompoundTag) tag.getTag(); - if (compound.containsKey("Palette") && compound.containsKey("Width") && compound.containsKey("Height") && compound.containsKey("Length")) { - int objW = ((ShortTag) compound.get("Width")).getValue(); - int objH = ((ShortTag) compound.get("Height")).getValue(); - int objD = ((ShortTag) compound.get("Length")).getValue(); - int mv = objW * objH * objD; - AtomicInteger v = new AtomicInteger(0); - AtomicInteger fv = new AtomicInteger(0); - if (mv > 500_000) { - largeObject = true; - Iris.info(C.GRAY + "Converting.. " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob")); - Iris.info(C.GRAY + "- It may take a while"); - if (sender.isPlayer()) { - J.a(() -> { -// while (v.get() != mv) { -// double pr = ((double) v.get() / (double ) mv); -// sender.sendProgress(pr, "Converting"); -// J.sleep(16); -// } - }); - } - } - - CompoundTag paletteTag = (CompoundTag) compound.get("Palette"); - Map blockmap = new HashMap<>(paletteTag.size(), 0.9f); - for (Map.Entry> entry : paletteTag.getValue().entrySet()) { - String blockName = entry.getKey(); - BlockData bd = Bukkit.createBlockData(blockName); - Tag blockTag = entry.getValue(); - int blockId = ((IntTag) blockTag).getValue(); - blockmap.put(blockId, bd); - } - - ByteArrayTag byteArray = (ByteArrayTag) compound.get("BlockData"); - byte[] originalBlockArray = byteArray.getValue(); - int b = 0; - int a = 0; - Map y = new HashMap<>(); - Map x = new HashMap<>(); - Map z = new HashMap<>(); - - // Height adjustments - for (int h = 0; h < objH; h++) { - if (b == 0) { - y.put(h, (byte) 0); - } - if (b > 0) { - y.put(h, (byte) 1); - } - a = 0; - b = 0; - for (int d = 0; d < objD; d++) { - for (int w = 0; w < objW; w++) { - BlockData db = blockmap.get((int) originalBlockArray[fv.get()]); - if (db.getAsString().contains("minecraft:air")) { - a++; - } else { - b++; - } - fv.getAndAdd(1); - } - } - } - fv.set(0); - - // Width adjustments - for (int w = 0; w < objW; w++) { - if (b == 0) { - x.put(w, (byte) 0); - } - if (b > 0) { - x.put(w, (byte) 1); - } - a = 0; - b = 0; - for (int h = 0; h < objH; h++) { - for (int d = 0; d < objD; d++) { - BlockData db = blockmap.get((int) originalBlockArray[fv.get()]); - if (db.getAsString().contains("minecraft:air")) { - a++; - } else { - b++; - } - fv.getAndAdd(1); - } - } - } - fv.set(0); - - // Depth adjustments - for (int d = 0; d < objD; d++) { - if (b == 0) { - z.put(d, (byte) 0); - } - if (b > 0) { - z.put(d, (byte) 1); - } - a = 0; - b = 0; - for (int h = 0; h < objH; h++) { - for (int w = 0; w < objW; w++) { - BlockData db = blockmap.get((int) originalBlockArray[fv.get()]); - if (db.getAsString().contains("minecraft:air")) { - a++; - } else { - b++; - } - fv.getAndAdd(1); - } - } - } - fv.set(0); - int CorrectObjH = getCorrectY(y, objH); - int CorrectObjW = getCorrectX(x, objW); - int CorrectObjD = getCorrectZ(z, objD); - - //IrisObject object = new IrisObject(CorrectObjW, CorrectObjH, CorrectObjH); - IrisObject object = new IrisObject(objW, objH, objD); - Vector originalVector = new Vector(objW, objH, objD); - - - int[] yc = null; - int[] xc = null; - int[] zc = null; - - - int fo = 0; - int so = 0; - int o = 0; - int c = 0; - for (Integer i : y.keySet()) { - if (y.get(i) == 0) { - o++; - } - if (y.get(i) == 1) { - c++; - if (c == 1) { - fo = o; - } - o = 0; - } - } - so = o; - yc = new int[]{fo, so}; - - fo = 0; - so = 0; - o = 0; - c = 0; - for (Integer i : x.keySet()) { - if (x.get(i) == 0) { - o++; - } - if (x.get(i) == 1) { - c++; - if (c == 1) { - fo = o; - } - o = 0; - } - } - so = o; - xc = new int[]{fo, so}; - - fo = 0; - so = 0; - o = 0; - c = 0; - for (Integer i : z.keySet()) { - if (z.get(i) == 0) { - o++; - } - if (z.get(i) == 1) { - c++; - if (c == 1) { - fo = o; - } - o = 0; - } - } - so = o; - zc = new int[]{fo, so}; - - int h1, h2, w1, w2, v1 = 0, volume = objW * objH * objD; - Map blockLocationMap = new LinkedHashMap<>(); - boolean hasAir = false; - int pos = 0; - for (int i : originalBlockArray) { - blockLocationMap.put(pos, i); - pos++; - } - - - for (int h = 0; h < objH; h++) { - for (int d = 0; d < objD; d++) { - for (int w = 0; w < objW; w++) { - BlockData bd = blockmap.get((int) originalBlockArray[v.get()]); - if (!bd.getMaterial().isAir()) { - object.setUnsigned(w, h, d, bd); - } - v.getAndAdd(1); - } - } - } - - - try { - object.write(new File(folder, schem.getName().replace(".schem", ".iob"))); - } catch (IOException e) { - Iris.info(C.RED + "Failed to save: " + schem.getName()); - throw new RuntimeException(e); - } + if (compound.containsKey("Palette") && compound.containsKey("Width") && compound.containsKey("Height") && compound.containsKey("Length")) { + int objW = ((ShortTag) compound.get("Width")).getValue(); + int objH = ((ShortTag) compound.get("Height")).getValue(); + int objD = ((ShortTag) compound.get("Length")).getValue(); + int i = -1; + int mv = objW * objH * objD; + AtomicInteger v = new AtomicInteger(0); + if (mv > 500_000) { + largeObject = true; + Iris.info(C.GRAY + "Converting.. "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob")); + Iris.info(C.GRAY + "- It may take a while"); if (sender.isPlayer()) { - if (largeObject) { - sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis())); - } else { - sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob")); + i = J.ar(() -> { + sender.sendProgress((double) v.get() / mv, "Converting"); + }, 0); + } + } + + CompoundTag paletteTag = (CompoundTag) compound.get("Palette"); + Map blockmap = new HashMap<>(paletteTag.size(), 0.9f); + for (Map.Entry> entry : paletteTag.getValue().entrySet()) { + String blockName = entry.getKey(); + BlockData bd = Bukkit.createBlockData(blockName); + Tag blockTag = entry.getValue(); + int blockId = ((IntTag) blockTag).getValue(); + blockmap.put(blockId, bd); + } + + ByteArrayTag byteArray = (ByteArrayTag) compound.get("BlockData"); + byte[] originalBlockArray = byteArray.getValue(); + + IrisObject object = new IrisObject(objW, objH, objD); + for (int h = 0; h < objH; h++) { + for (int d = 0; d < objD; d++) { + for (int w = 0; w < objW; w++) { + BlockData bd = blockmap.get((int) originalBlockArray[v.get()]); + if (!bd.getMaterial().isAir()) { + object.setUnsigned(w, h, d, bd); + } + v.getAndAdd(1); } } - if (largeObject) { - Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis())); - } else { - Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob")); - } - // schem.delete(); } - } catch (Exception e) { - Iris.info(C.RED + "Failed to convert: " + schem.getName()); + if (i != -1) J.car(i); + try { + object.shrinkwrap(); + object.write(new File(folder, schem.getName().replace(".schem", ".iob"))); + } catch (IOException e) { + Iris.info(C.RED + "Failed to save: " + schem.getName()); + throw new RuntimeException(e); + } if (sender.isPlayer()) { - sender.sendMessage(C.RED + "Failed to convert: " + schem.getName()); + if (largeObject) { + sender.sendMessage(C.IRIS + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis())); + } else { + sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob")); + } } - e.printStackTrace(); - Iris.reportError(e); + if (largeObject) { + Iris.info(C.GRAY + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis())); + } else { + Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob")); + } + FileUtils.delete(schem); } + } catch (Exception e) { + Iris.info(C.RED + "Failed to convert: " + schem.getName()); + if (sender.isPlayer()) { + sender.sendMessage(C.RED + "Failed to convert: " + schem.getName()); + } + e.printStackTrace(); + Iris.reportError(e); } + } + sender.sendMessage(C.GRAY + "converted: " + fileList.length); }); } - public static boolean isNewPointFurther(int[] originalPoint, int[] oldPoint, int[] newPoint) { - int oX = oldPoint[1]; - int oY = oldPoint[2]; - int oZ = oldPoint[3]; - - int nX = newPoint[1]; - int nY = newPoint[2]; - int nZ = newPoint[3]; - - int orX = originalPoint[1]; - int orY = originalPoint[2]; - int orZ = originalPoint[3]; - - double oldDistance = Math.sqrt(Math.pow(oX - orX, 2) + Math.pow(oY - orY, 2) + Math.pow(oZ - orZ, 2)); - double newDistance = Math.sqrt(Math.pow(nX - orX, 2) + Math.pow(nY - orY, 2) + Math.pow(nZ - orZ, 2)); - - if (newDistance > oldDistance) { - return true; - } - return false; - } - - public static int[] getCoordinates(int pos, int obX, int obY, int obZ) { - int z = 0; - int[] coords = new int[4]; - for (int h = 0; h < obY; h++) { - for (int d = 0; d < obZ; d++) { - for (int w = 0; w < obX; w++) { - if (z == pos) { - coords[1] = w; - coords[2] = h; - coords[3] = d; - return coords; - } - z++; - } - } - } - return null; - } - - public static int getCorrectY(Map y, int H) { - int fo = 0; - int so = 0; - int o = 0; - int c = 0; - for (Integer i : y.keySet()) { - if (y.get(i) == 0) { - o++; - } - if (y.get(i) == 1) { - c++; - if (c == 1) { - fo = o; - } - o = 0; - } - } - so = o; - return H = H - (fo + so); - } - - public static int getCorrectX(Map x, int W) { - int fo = 0; - int so = 0; - int o = 0; - int c = 0; - for (Integer i : x.keySet()) { - if (x.get(i) == 0) { - o++; - } - if (x.get(i) == 1) { - c++; - if (c == 1) { - fo = o; - } - o = 0; - } - } - so = o; - return W = W - (fo + so); - } - - public static int getCorrectZ(Map z, int D) { - int fo = 0; - int so = 0; - int o = 0; - int c = 0; - for (Integer i : z.keySet()) { - if (z.get(i) == 0) { - o++; - } - if (z.get(i) == 1) { - c++; - if (c == 1) { - fo = o; - } - o = 0; - } - } - so = o; - return D = D - (fo + so); - } } diff --git a/core/src/main/java/com/volmit/iris/core/wand/WandSelection.java b/core/src/main/java/com/volmit/iris/core/wand/WandSelection.java index e5754afad..2cd37c20b 100644 --- a/core/src/main/java/com/volmit/iris/core/wand/WandSelection.java +++ b/core/src/main/java/com/volmit/iris/core/wand/WandSelection.java @@ -33,6 +33,7 @@ public class WandSelection { private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST"); private final Cuboid c; private final Player p; + private static final double STEP = 0.10; public WandSelection(Cuboid c, Player p) { this.c = c; @@ -40,77 +41,58 @@ public class WandSelection { } public void draw() { - double accuracy; - double dist; + Location playerLoc = p.getLocation(); + double maxDistanceSquared = 256 * 256; + int particleCount = 0; - for (double i = c.getLowerX() - 1; i < c.getUpperX() + 1; i += 0.25) { - for (double j = c.getLowerY() - 1; j < c.getUpperY() + 1; j += 0.25) { - for (double k = c.getLowerZ() - 1; k < c.getUpperZ() + 1; k += 0.25) { - boolean ii = i == c.getLowerX() || i == c.getUpperX(); - boolean jj = j == c.getLowerY() || j == c.getUpperY(); - boolean kk = k == c.getLowerZ() || k == c.getUpperZ(); + // cube! + Location[][] edges = { + {c.getLowerNE(), new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getLowerZ())}, + {c.getLowerNE(), new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getLowerZ())}, + {c.getLowerNE(), new Location(c.getWorld(), c.getLowerX(), c.getLowerY(), c.getUpperZ() + 1)}, + {new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getLowerZ())}, + {new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getUpperZ() + 1)}, + {new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getLowerZ())}, + {new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getLowerZ()), new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getUpperZ() + 1)}, + {new Location(c.getWorld(), c.getLowerX(), c.getLowerY(), c.getUpperZ() + 1), new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getUpperZ() + 1)}, + {new Location(c.getWorld(), c.getLowerX(), c.getLowerY(), c.getUpperZ() + 1), new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getUpperZ() + 1)}, + {new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getLowerZ()), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getUpperZ() + 1)}, + {new Location(c.getWorld(), c.getLowerX(), c.getUpperY() + 1, c.getUpperZ() + 1), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getUpperZ() + 1)}, + {new Location(c.getWorld(), c.getUpperX() + 1, c.getLowerY(), c.getUpperZ() + 1), new Location(c.getWorld(), c.getUpperX() + 1, c.getUpperY() + 1, c.getUpperZ() + 1)} + }; - if ((ii && jj) || (ii && kk) || (kk && jj)) { - Vector push = new Vector(0, 0, 0); + for (Location[] edge : edges) { + Vector direction = edge[1].toVector().subtract(edge[0].toVector()); + double length = direction.length(); + direction.normalize(); - if (i == c.getLowerX()) { - push.add(new Vector(-0.55, 0, 0)); - } + for (double d = 0; d <= length; d += STEP) { + Location particleLoc = edge[0].clone().add(direction.clone().multiply(d)); - if (j == c.getLowerY()) { - push.add(new Vector(0, -0.55, 0)); - } - - if (k == c.getLowerZ()) { - push.add(new Vector(0, 0, -0.55)); - } - - if (i == c.getUpperX()) { - push.add(new Vector(0.55, 0, 0)); - } - - if (j == c.getUpperY()) { - push.add(new Vector(0, 0.55, 0)); - } - - if (k == c.getUpperZ()) { - push.add(new Vector(0, 0, 0.55)); - } - - Location a = new Location(c.getWorld(), i, j, k).add(0.5, 0.5, 0.5).add(push); - accuracy = M.lerpInverse(0, 64 * 64, p.getLocation().distanceSquared(a)); - dist = M.lerp(0.125, 3.5, accuracy); - - if (M.r(M.min(dist * 5, 0.9D) * 0.995)) { - continue; - } - - if (ii && jj) { - a.add(0, 0, RNG.r.d(-0.3, 0.3)); - } - - if (kk && jj) { - a.add(RNG.r.d(-0.3, 0.3), 0, 0); - } - - if (ii && kk) { - a.add(0, RNG.r.d(-0.3, 0.3), 0); - } - - if (p.getLocation().distanceSquared(a) < 256 * 256) { - Color color = Color.getHSBColor((float) (0.5f + (Math.sin((i + j + k + (p.getTicksLived() / 2f)) / (20f)) / 2)), 1, 1); - int r = color.getRed(); - int g = color.getGreen(); - int b = color.getBlue(); - - p.spawnParticle(REDSTONE, a.getX(), a.getY(), a.getZ(), - 1, 0, 0, 0, 0, - new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b), - (float) dist * 3f)); - } - } + if (playerLoc.distanceSquared(particleLoc) > maxDistanceSquared) { + continue; } + + spawnParticle(particleLoc, playerLoc); + particleCount++; } } } + + private void spawnParticle(Location particleLoc, Location playerLoc) { + double accuracy = M.lerpInverse(0, 64 * 64, playerLoc.distanceSquared(particleLoc)); + double dist = M.lerp(0.125, 3.5, accuracy); + + if (M.r(Math.min(dist * 5, 0.9D) * 0.995)) { + return; + } + + float hue = (float) (0.5f + (Math.sin((particleLoc.getX() + particleLoc.getY() + particleLoc.getZ() + (p.getTicksLived() / 2f)) / 20f) / 2)); + Color color = Color.getHSBColor(hue, 1, 1); + + p.spawnParticle(REDSTONE, particleLoc, + 0, 0, 0, 0, 1, + new Particle.DustOptions(org.bukkit.Color.fromRGB(color.getRed(), color.getGreen(), color.getBlue()), + (float) dist * 3f)); + } } 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 9287fb171..4b429971f 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 @@ -53,6 +53,7 @@ import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.MatterCavern; import com.volmit.iris.util.matter.MatterUpdate; +import com.volmit.iris.util.matter.TileWrapper; import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; @@ -283,9 +284,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat var mc = getMantle().getMantle().getChunk(c.getX(), c.getZ()); mc.raiseFlag(MantleFlag.TILE, () -> J.s(() -> { - mc.iterate(TileData.class, (x, y, z, tile) -> { + mc.iterate(TileWrapper.class, (x, y, z, tile) -> { int betterY = y + getWorld().minHeight(); - if (!TileData.setTileState(c.getBlock(x, betterY, z), tile)) + if (!TileData.setTileState(c.getBlock(x, betterY, z), tile.getData())) Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), tile.getMaterial().name()); }); })); diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java index 69aee2375..1807631df 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java @@ -57,7 +57,7 @@ public class MantleJigsawComponent extends IrisMantleComponent { @ChunkCoordinates private void generateJigsaw(MantleWriter writer, int x, int z, IrisBiome biome, IrisRegion region) { - long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z); + long seed = cng.fit(Integer.MIN_VALUE, Integer.MAX_VALUE, x, z); if (getDimension().getStronghold() != null) { List poss = getDimension().getStrongholds(seed()); @@ -130,7 +130,7 @@ public class MantleJigsawComponent extends IrisMantleComponent { public IrisJigsawStructure guess(int x, int z) { // todo The guess doesnt bring into account that the placer may return -1 // todo doesnt bring skipped placements into account - long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z); + long seed = cng.fit(Integer.MIN_VALUE, Integer.MAX_VALUE, x, z); IrisBiome biome = getEngineMantle().getEngine().getSurfaceBiome((x << 4) + 8, (z << 4) + 8); IrisRegion region = getEngineMantle().getEngine().getRegion((x << 4) + 8, (z << 4) + 8); diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java b/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java index 790c34727..b1d04606b 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java @@ -104,7 +104,7 @@ public class IrisBiomeCustom { JSONObject po = new JSONObject(); po.put("type", ambientParticle.getParticle().name().toLowerCase()); particle.put("options", po); - particle.put("probability", ambientParticle.getRarity()); + particle.put("probability", 1f/ambientParticle.getRarity()); effects.put("particle", particle); } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java b/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java index dddd36228..9ce29c71b 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisObject.java @@ -43,6 +43,7 @@ import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.scheduling.IrisLock; import com.volmit.iris.util.scheduling.PrecisionStopwatch; +import com.volmit.iris.util.scheduling.jobs.Job; import com.volmit.iris.util.stream.ProceduralStream; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -63,7 +64,9 @@ import org.bukkit.util.Vector; import java.io.*; import java.util.*; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; @Accessors(chain = true) @@ -384,6 +387,88 @@ public class IrisObject extends IrisRegistrant { } } + public void write(OutputStream o, VolmitSender sender) throws IOException { + AtomicReference ref = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(1); + new Job() { + private int total = getBlocks().size() * 3 + getStates().size(); + private int c = 0; + + @Override + public String getName() { + return "Saving Object"; + } + + @Override + public void execute() { + try { + DataOutputStream dos = new DataOutputStream(o); + dos.writeInt(w); + dos.writeInt(h); + dos.writeInt(d); + dos.writeUTF("Iris V2 IOB;"); + + KList palette = new KList<>(); + + for (BlockData i : getBlocks().values()) { + palette.addIfMissing(i.getAsString()); + ++c; + } + total -= getBlocks().size() - palette.size(); + + dos.writeShort(palette.size()); + + for (String i : palette) { + dos.writeUTF(i); + ++c; + } + + dos.writeInt(getBlocks().size()); + + for (BlockVector i : getBlocks().keySet()) { + dos.writeShort(i.getBlockX()); + dos.writeShort(i.getBlockY()); + dos.writeShort(i.getBlockZ()); + dos.writeShort(palette.indexOf(getBlocks().get(i).getAsString())); + ++c; + } + + dos.writeInt(getStates().size()); + for (BlockVector i : getStates().keySet()) { + dos.writeShort(i.getBlockX()); + dos.writeShort(i.getBlockY()); + dos.writeShort(i.getBlockZ()); + getStates().get(i).toBinary(dos); + ++c; + } + } catch (IOException e) { + ref.set(e); + } finally { + latch.countDown(); + } + } + + @Override + public void completeWork() {} + + @Override + public int getTotalWork() { + return total; + } + + @Override + public int getWorkCompleted() { + return c; + } + }.execute(sender, true, () -> {}); + + try { + latch.await(); + } catch (InterruptedException ignored) {} + if (ref.get() != null) + throw ref.get(); + } + public void read(File file) throws IOException { var fin = new BufferedInputStream(new FileInputStream(file)); try { @@ -408,6 +493,16 @@ public class IrisObject extends IrisRegistrant { out.close(); } + public void write(File file, VolmitSender sender) throws IOException { + if (file == null) { + return; + } + + FileOutputStream out = new FileOutputStream(file); + write(out, sender); + out.close(); + } + public void shrinkwrap() { BlockVector min = new BlockVector(); BlockVector max = new BlockVector(); @@ -478,7 +573,7 @@ public class IrisObject extends IrisRegistrant { getBlocks().put(v, data); TileData state = TileData.getTileState(block); if (state != null) { - Iris.info("Saved State " + v); + Iris.debug("Saved State " + v); getStates().put(v, state); } } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisObjectRotation.java b/core/src/main/java/com/volmit/iris/engine/object/IrisObjectRotation.java index 881d0e953..ac4b81b12 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisObjectRotation.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisObjectRotation.java @@ -22,6 +22,7 @@ import com.volmit.iris.Iris; import com.volmit.iris.engine.object.annotations.Desc; import com.volmit.iris.engine.object.annotations.Snippet; import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -30,9 +31,12 @@ import org.bukkit.Axis; import org.bukkit.Material; import org.bukkit.block.BlockFace; import org.bukkit.block.data.*; +import org.bukkit.block.data.type.Wall; +import org.bukkit.block.structure.StructureRotation; import org.bukkit.util.BlockVector; import java.util.List; +import java.util.Map; @Snippet("object-rotator") @Accessors(chain = true) @@ -41,6 +45,8 @@ import java.util.List; @Desc("Configures rotation for iris") @Data public class IrisObjectRotation { + private static final List WALL_FACES = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); + @Desc("If this rotator is enabled or not") private boolean enabled = true; @@ -283,6 +289,22 @@ public class IrisObjectRotation { for (BlockFace i : faces) { g.setFace(i, true); } + } else if (d instanceof Wall wall) { + KMap faces = new KMap<>(); + + for (BlockFace i : WALL_FACES) { + Wall.Height h = wall.getHeight(i); + BlockVector bv = new BlockVector(i.getModX(), i.getModY(), i.getModZ()); + bv = rotate(bv.clone(), spinx, spiny, spinz); + BlockFace r = getFace(bv); + if (WALL_FACES.contains(r)) { + faces.put(r, h); + } + } + + for (BlockFace i : WALL_FACES) { + wall.setHeight(i, faces.getOrDefault(i, Wall.Height.NONE)); + } } else if (d.getMaterial().equals(Material.NETHER_PORTAL) && d instanceof Orientable g) { //TODO: Fucks up logs BlockFace f = faceForAxis(g.getAxis()); diff --git a/core/src/main/java/com/volmit/iris/util/data/Cuboid.java b/core/src/main/java/com/volmit/iris/util/data/Cuboid.java index b4e0172a8..8f5d5afd3 100644 --- a/core/src/main/java/com/volmit/iris/util/data/Cuboid.java +++ b/core/src/main/java/com/volmit/iris/util/data/Cuboid.java @@ -20,6 +20,7 @@ package com.volmit.iris.util.data; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.math.Direction; +import com.volmit.iris.util.math.Position2; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.configuration.serialization.ConfigurationSerializable; @@ -651,6 +652,10 @@ public class Cuboid implements Iterable, Cloneable, ConfigurationSerializ return new CuboidIterator(getWorld(), x1, y1, z1, x2, y2, z2); } + public Iterator chunkedIterator() { + return new ChunkedCuboidIterator(getWorld(), x1, y1, z1, x2, y2, z2); + } + /* * (non-Javadoc) * @@ -746,4 +751,82 @@ public class Cuboid implements Iterable, Cloneable, ConfigurationSerializ } } + public static class ChunkedCuboidIterator implements Iterator { + private final World w; + private final int minRX, minY, minRZ, maxRX, maxY, maxRZ; + private final int minCX, minCZ, maxCX, maxCZ; + private int mX, mZ, bX, rX, rZ, y; + + private Position2 chunk; + private int cX, cZ; + + public ChunkedCuboidIterator(World w, int x1, int y1, int z1, int x2, int y2, int z2) { + this.w = w; + minY = Math.min(y1, y2); + maxY = Math.max(y1, y2); + int minX = Math.min(x1, x2); + int minZ = Math.min(z1, z2); + int maxX = Math.max(x1, x2); + int maxZ = Math.max(z1, z2); + minRX = minX & 15; + minRZ = minZ & 15; + maxRX = maxX & 15; + maxRZ = maxZ & 15; + + minCX = minX >> 4; + minCZ = minZ >> 4; + maxCX = maxX >> 4; + maxCZ = maxZ >> 4; + cX = minCX; + cZ = minCZ; + + rX = minX & 15; + rZ = minZ & 15; + y = minY; + } + + @Override + public boolean hasNext() { + return chunk != null || hasNextChunk(); + } + + public boolean hasNextChunk() { + return cX <= maxCX && cZ <= maxCZ; + } + + @Override + public Block next() { + if (chunk == null) { + chunk = new Position2(cX, cZ); + if (++cX > maxCX) { + cX = minCX; + cZ++; + } + + mX = chunk.getX() == maxCX ? maxRX : 15; + mZ = chunk.getZ() == maxCZ ? maxRZ : 15; + rX = bX = chunk.getX() == minCX ? minRX : 0; + rZ = chunk.getZ() == minCZ ? minRZ : 0; + } + + var b = w.getBlockAt((chunk.getX() << 4) + rX, y, (chunk.getZ() << 4) + rZ); + if (++y >= maxY) { + y = minY; + if (++rX > mX) { + if (++rZ > mZ) { + chunk = null; + return b; + } + rX = bX; + } + } + + return b; + } + + @Override + public void remove() { + // nop + } + } } \ No newline at end of file