diff --git a/src/main/java/com/volmit/iris/command/CommandIrisStructure.java b/src/main/java/com/volmit/iris/command/CommandIrisStructure.java index 14258ba5e..0c72205fe 100644 --- a/src/main/java/com/volmit/iris/command/CommandIrisStructure.java +++ b/src/main/java/com/volmit/iris/command/CommandIrisStructure.java @@ -10,6 +10,9 @@ public class CommandIrisStructure extends MortarCommand @Command private CommandIrisStructureCreate create; + @Command + private CommandIrisStructureOpen open; + @Command private CommandIrisStructureSave save; @@ -19,6 +22,9 @@ public class CommandIrisStructure extends MortarCommand @Command private CommandIrisStructureExpand expand; + @Command + private CommandIrisStructureVariants variants; + @Command private CommandIrisStructureClose close; diff --git a/src/main/java/com/volmit/iris/command/CommandIrisStructureOpen.java b/src/main/java/com/volmit/iris/command/CommandIrisStructureOpen.java new file mode 100644 index 000000000..723d9bc97 --- /dev/null +++ b/src/main/java/com/volmit/iris/command/CommandIrisStructureOpen.java @@ -0,0 +1,51 @@ +package com.volmit.iris.command; + +import org.bukkit.entity.Player; + +import com.volmit.iris.Iris; +import com.volmit.iris.object.IrisStructure; +import com.volmit.iris.util.MortarCommand; +import com.volmit.iris.util.MortarSender; +import com.volmit.iris.util.StructureTemplate; + +public class CommandIrisStructureOpen extends MortarCommand +{ + public CommandIrisStructureOpen() + { + super("load", "open", "o"); + requiresPermission(Iris.perm); + setCategory("Structure"); + setDescription("Open an existing structure"); + } + + @Override + public boolean handle(MortarSender sender, String[] args) + { + if(!sender.isPlayer()) + { + sender.sendMessage("You don't have a wand"); + return true; + } + + Player p = sender.player(); + + IrisStructure structure = Iris.globaldata.getStructureLoader().load(args[0]); + + if(structure == null) + { + sender.sendMessage("Can't find " + args[0]); + return true; + } + + String dimensionGuess = structure.getLoadFile().getParentFile().getParentFile().getName(); + new StructureTemplate(structure.getName(), dimensionGuess, p, p.getLocation(), 9, structure.getGridSize(), structure.getGridHeight(), structure.getMaxLayers() > 1).loadStructures(structure); + + return true; + } + + @Override + protected String getArgsUsage() + { + return ""; + } +} diff --git a/src/main/java/com/volmit/iris/command/CommandIrisStructureVariants.java b/src/main/java/com/volmit/iris/command/CommandIrisStructureVariants.java new file mode 100644 index 000000000..4389e5da0 --- /dev/null +++ b/src/main/java/com/volmit/iris/command/CommandIrisStructureVariants.java @@ -0,0 +1,40 @@ +package com.volmit.iris.command; + +import org.bukkit.entity.Player; + +import com.volmit.iris.Iris; +import com.volmit.iris.util.MortarCommand; +import com.volmit.iris.util.MortarSender; + +public class CommandIrisStructureVariants extends MortarCommand +{ + public CommandIrisStructureVariants() + { + super("variants", "var", "v"); + requiresPermission(Iris.perm); + setCategory("Structure"); + setDescription("Change or add variants in tile looking at"); + } + + @Override + public boolean handle(MortarSender sender, String[] args) + { + if(!sender.isPlayer()) + { + sender.sendMessage("You don't have a wand"); + return true; + } + + Player p = sender.player(); + + Iris.struct.get(p).openVariants(); + + return true; + } + + @Override + protected String getArgsUsage() + { + return ""; + } +} diff --git a/src/main/java/com/volmit/iris/object/IrisObject.java b/src/main/java/com/volmit/iris/object/IrisObject.java index 8cafd639a..d274f1bb8 100644 --- a/src/main/java/com/volmit/iris/object/IrisObject.java +++ b/src/main/java/com/volmit/iris/object/IrisObject.java @@ -40,6 +40,19 @@ public class IrisObject extends IrisRegistrant private int h; private transient BlockVector center; + public IrisObject copy() + { + IrisObject o = new IrisObject(w, h, d); + o.setCenter(getCenter().clone()); + + for(BlockVector i : getBlocks().k()) + { + o.getBlocks().put(i.clone(), getBlocks().get(i).clone()); + } + + return o; + } + public IrisObject(int w, int h, int d) { blocks = new KMap<>(); @@ -381,12 +394,12 @@ public class IrisObject extends IrisRegistrant return y; } - + public void rotate(IrisObjectRotation r, int spinx, int spiny, int spinz) { KMap v = blocks.copy(); blocks.clear(); - + for(BlockVector i : v.keySet()) { blocks.put(r.rotate(i.clone(), spinx, spiny, spinz), r.rotate(v.get(i).clone(), spinx, spiny, spinz)); diff --git a/src/main/java/com/volmit/iris/object/IrisStructureTile.java b/src/main/java/com/volmit/iris/object/IrisStructureTile.java index 7f594dd06..9296b6273 100644 --- a/src/main/java/com/volmit/iris/object/IrisStructureTile.java +++ b/src/main/java/com/volmit/iris/object/IrisStructureTile.java @@ -1,10 +1,13 @@ package com.volmit.iris.object; +import java.util.Objects; + 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.KMap; import com.volmit.iris.util.RegistryListObject; import com.volmit.iris.util.Required; @@ -62,7 +65,7 @@ public class IrisStructureTile @Desc("List of objects to place centered in this tile") private KList objects = new KList<>(); - private transient IrisObject forceObject; + private transient KMap forceObjects = new KMap<>(); @RegistryListObject @ArrayType(min = 1, type = IrisRareObject.class) @@ -78,6 +81,11 @@ public class IrisStructureTile } + public int hashFace() + { + return Objects.hash(ceiling, floor, south, north, east, west); + } + public String toString() { return (ceiling.required() ? "C" : "") + (floor.required() ? "F" : "") + "| " + (north.required() ? "X" : "-") + (south.required() ? "X" : "-") + (east.required() ? "X" : "-") + (west.required() ? "X" : "-") + " |"; diff --git a/src/main/java/com/volmit/iris/util/StructureTemplate.java b/src/main/java/com/volmit/iris/util/StructureTemplate.java index 4de5f1a5f..ccc40e1b1 100644 --- a/src/main/java/com/volmit/iris/util/StructureTemplate.java +++ b/src/main/java/com/volmit/iris/util/StructureTemplate.java @@ -30,11 +30,20 @@ import org.bukkit.util.BlockVector; import com.google.gson.Gson; import com.volmit.iris.Iris; +import com.volmit.iris.noise.CNG; import com.volmit.iris.object.IrisObject; import com.volmit.iris.object.IrisStructure; import com.volmit.iris.object.IrisStructureTile; +import com.volmit.iris.object.NoiseStyle; import com.volmit.iris.object.StructureTileCondition; import com.volmit.iris.object.TileResult; +import com.volmit.iris.util.inventory.C; +import com.volmit.iris.util.inventory.MaterialBlock; +import com.volmit.iris.util.inventory.UIElement; +import com.volmit.iris.util.inventory.UIStaticDecorator; +import com.volmit.iris.util.inventory.UIWindow; +import com.volmit.iris.util.inventory.Window; +import com.volmit.iris.util.inventory.WindowResolution; import lombok.Data; @@ -60,11 +69,14 @@ public class StructureTemplate implements Listener, IObjectPlacer private Player worker; private KMap updates = new KMap<>(); private File folder; + private CNG variants; + private KMap forceVariant = new KMap<>(); public StructureTemplate(String name, String dimension, Player worker, Location c, int size, int w, int h, boolean use3d) { this.worker = worker; rng = new RNG(); + variants = NoiseStyle.STATIC.create(rng.nextParallelRNG(397878)); folder = Iris.instance.getDataFolder("packs", dimension); gLatch = new ChronoLatch(250); focus = center; @@ -86,7 +98,7 @@ public class StructureTemplate implements Listener, IObjectPlacer structure.setName(Form.capitalizeWords(name.replaceAll("\\Q-\\E", " "))); structure.setWallChance(0.35); defineStructures(); - updateTiles(center, null, null); + regenerate(); Iris.struct.open(this); } @@ -98,9 +110,12 @@ public class StructureTemplate implements Listener, IObjectPlacer for(IrisStructureTile i : structure.getTiles()) { - File objectFile = new File(folder, "objects/structure/" + structure.getLoadKey() + "/" + i.getForceObject().getLoadKey() + ".iob"); - Iris.verbose("Saving " + objectFile.getPath()); - i.getForceObject().write(objectFile); + for(IrisObject j : i.getForceObjects().v()) + { + File objectFile = new File(folder, "objects/structure/" + structure.getLoadKey() + "/" + j.getLoadKey() + ".iob"); + Iris.verbose("Saving " + objectFile.getPath()); + j.write(objectFile); + } } Iris.verbose("Saving " + structureFile.getPath()); @@ -113,6 +128,170 @@ public class StructureTemplate implements Listener, IObjectPlacer } } + public void loadStructures(IrisStructure input) + { + Iris.info("Loading existing structure"); + + for(IrisStructureTile i : structure.getTiles().copy()) + { + String realType = i.getForceObjects().get(1).getLoadKey().replaceAll("\\Q-1\\E", ""); + + for(IrisStructureTile j : input.getTiles()) + { + if(j.hashFace() == i.hashFace()) + { + Iris.verbose("Found matching face configuration: " + j.hashFace()); + structure.getTiles().remove(i); + IrisStructureTile hijacked = new IrisStructureTile(); + hijacked.setCeiling(j.getCeiling()); + hijacked.setFloor(j.getFloor()); + hijacked.setNorth(j.getNorth()); + hijacked.setSouth(j.getSouth()); + hijacked.setEast(j.getEast()); + hijacked.setWest(j.getWest()); + + for(String k : j.getObjects()) + { + int v = hijacked.getForceObjects().size() + 1; + IrisObject o = Iris.globaldata.getObjectLoader().load(k).copy(); + String b = o.getLoadKey(); + o.setLoadKey(realType + "-" + v); + + if(b.equals(o.getLoadKey())) + { + Iris.warn("Loading Object " + b + " as " + o.getLoadKey() + " (not deleting the old file)"); + } + + hijacked.getForceObjects().put(v, o); + hijacked.getObjects().add("structure/" + this.structure.getLoadKey() + "/" + o.getLoadKey()); + } + + structure.getTiles().add(i); + break; + } + } + } + } + + public void openVariants() + { + try + { + Location m = worker.getTargetBlockExact(64).getLocation(); + + if(isWithinBounds(m)) + { + focus = m.clone(); + Cuboid b = getTileBounds(m); + Location center = b.getCenter(); + TileResult r = structure.getTile(rng, center.getX(), center.getY(), center.getZ()); + openVariants(r.getTile(), b); + return; + } + } + + catch(Throwable ef) + { + ef.printStackTrace(); + } + + worker.sendMessage("Look at a tile to configure variants."); + } + + public void openVariants(IrisStructureTile t, Cuboid at) + { + int var = getVariant(at, t); + Window w = new UIWindow(worker); + w.setTitle("Variants"); + w.setDecorator(new UIStaticDecorator(new UIElement("dec").setMaterial(new MaterialBlock(Material.BLACK_STAINED_GLASS_PANE)))); + WindowResolution r = WindowResolution.W5_H1; + w.setResolution(r); + + if(t.getForceObjects().size() > 4) + { + r = WindowResolution.W3_H3; + w.setResolution(r); + } + + if(t.getForceObjects().size() > 8) + { + r = WindowResolution.W9_H6; + w.setResolution(r); + w.setViewportHeight((int) Math.ceil((double) (t.getForceObjects().size() + 1) / 9D)); + } + int m = 0; + + UIElement ea = new UIElement("add"); + ea.setEnchanted(true); + ea.setMaterial(new MaterialBlock(Material.EMERALD)); + ea.setName("New Variant from Current Tile"); + + ea.getLore().add("- Left Click to copy current variant into a new variant"); + ea.onLeftClick((ee) -> + { + w.close(); + createVariantCopy(t, at); + }); + + w.setElement(w.getLayoutPosition(m), w.getLayoutRow(m), ea); + m++; + + for(Integer i : t.getForceObjects().k()) + { + UIElement e = new UIElement("var-" + i); + e.setEnchanted(var == i); + e.setCount(i); + e.setMaterial(new MaterialBlock(var == i ? Material.ENDER_EYE : Material.ENDER_PEARL)); + e.setName(t.getForceObjects().get(i).getLoadKey()); + + if(var != i) + { + e.getLore().add("- Left Click to select this variant"); + e.onLeftClick((ee) -> + { + w.close(); + switchVariant(t, at, i); + }); + } + + w.setElement(w.getLayoutPosition(m), w.getLayoutRow(m), e); + m++; + } + + w.open(); + } + + public void deleteVariant(IrisStructureTile t, Cuboid at) + { + + } + + public void switchVariant(IrisStructureTile t, Cuboid at, int var) + { + forceVariant.put(at.getCenter(), var); + updateTile(at); + } + + public void createVariantCopy(IrisStructureTile t, Cuboid at) + { + int variant = getVariant(at, t); + IrisObject origin = t.getForceObjects().get(variant); + IrisObject object = new IrisObject(origin.getW(), origin.getH(), origin.getD()); + object.setCenter(origin.getCenter().clone()); + + for(BlockVector i : origin.getBlocks().k()) + { + object.getBlocks().put(i.clone(), origin.getBlocks().get(i).clone()); + } + + int nv = t.getForceObjects().size() + 1; + object.setLoadKey(origin.getLoadKey().replaceAll("\\Q-" + variant + "\\E", "-" + nv)); + t.getObjects().add("structure/" + this.structure.getLoadKey() + "/" + object.getLoadKey()); + t.getForceObjects().put(nv, object); + forceVariant.put(at.getCenter(), nv); + regenerate(); + } + public void setWallChance(double w) { structure.setWallChance(w); @@ -122,6 +301,7 @@ public class StructureTemplate implements Listener, IObjectPlacer public void regenerate() { rng = new RNG(); + variants = NoiseStyle.STATIC.create(rng.nextParallelRNG(397878)); updateTiles(center, null, null); } @@ -207,7 +387,7 @@ public class StructureTemplate implements Listener, IObjectPlacer return; } - IrisObject o = r.getTile().getForceObject(); + IrisObject o = r.getTile().getForceObjects().get(getVariant(getTileBounds(l), r.getTile())); double yrot = r.getPlacement().getRotation().getYAxis().getMax(); double trot = -yrot; r.getPlacement().getRotation().getYAxis().setMin(trot); @@ -238,7 +418,7 @@ public class StructureTemplate implements Listener, IObjectPlacer Iris.wand.draw(b, worker); Location center = b.getCenter(); TileResult r = structure.getTile(rng, center.getX(), center.getY(), center.getZ()); - worker.sendTitle("", r.getTile().getForceObject().getLoadKey() + " " + r.getPlacement().getRotation().getYAxis().getMax() + "°", 0, 20, 40); + worker.sendTitle("", C.GRAY + r.getTile().getForceObjects().get(getVariant(b, r.getTile())).getLoadKey() + " " + C.DARK_GRAY + r.getPlacement().getRotation().getYAxis().getMax() + "°", 0, 20, 40); } public void updateTiles(Location from, IrisStructureTile tileType, Cuboid ignore) @@ -263,7 +443,7 @@ public class StructureTemplate implements Listener, IObjectPlacer Location center = getTileBounds(l).getCenter(); TileResult r = structure.getTile(rng, center.getX(), center.getY(), center.getZ()); - if(r == null || !r.getTile().getForceObject().getLoadKey().equals(tileType.getForceObject().getLoadKey())) + if(r == null || !r.getTile().getForceObjects().get(getVariant(getTileBounds(l), r.getTile())).getLoadKey().equals(tileType.getForceObjects().get(getVariant(getTileBounds(l), r.getTile())).getLoadKey())) { continue; } @@ -286,6 +466,22 @@ public class StructureTemplate implements Listener, IObjectPlacer center.getWorld().spawnParticle(Particle.EXPLOSION_HUGE, center.getX(), center.getY(), center.getZ(), 1); } + public int getVariant(Cuboid c, IrisStructureTile t) + { + if(t.getForceObjects().size() == 1) + { + return t.getForceObjects().keys().nextElement(); + } + + if(forceVariant.containsKey(c.getCenter())) + { + return forceVariant.get(c.getCenter()); + } + + Location ce = c.getCenter(); + return variants.fit(t.getForceObjects().keypair(), ce.getBlockX(), ce.getBlockY(), ce.getBlockZ()).getK(); + } + public void updateTile(Cuboid c) { Location center = c.getCenter(); @@ -298,7 +494,7 @@ public class StructureTemplate implements Listener, IObjectPlacer return; } - r.getTile().getForceObject().place(bottomCenter.getBlockX(), bottomCenter.getBlockY(), bottomCenter.getBlockZ(), this, r.getPlacement(), rng); + r.getTile().getForceObjects().get(getVariant(c, r.getTile())).place(bottomCenter.getBlockX(), bottomCenter.getBlockY(), bottomCenter.getBlockZ(), this, r.getPlacement(), rng); center.getWorld().playSound(center, Sound.BLOCK_ANCIENT_DEBRIS_BREAK, 1f, 0.35f); center.getWorld().spawnParticle(Particle.FLASH, center.getX(), center.getY(), center.getZ(), 1); } @@ -360,12 +556,17 @@ public class StructureTemplate implements Listener, IObjectPlacer } public IrisStructureTile tileFor(String name, StructureTileCondition f, StructureTileCondition c, StructureTileCondition n, StructureTileCondition e, StructureTileCondition w, StructureTileCondition s) + { + return tileFor(name, f, c, n, e, w, s, 1); + } + + public IrisStructureTile tileFor(String name, StructureTileCondition f, StructureTileCondition c, StructureTileCondition n, StructureTileCondition e, StructureTileCondition w, StructureTileCondition s, int variant) { IrisObject o = new IrisObject(this.w, this.h, this.w); - o.setLoadKey(name.toLowerCase().replaceAll("\\Q \\E", "-")); + o.setLoadKey(name.toLowerCase().replaceAll("\\Q \\E", "-").trim() + "-" + variant); IrisStructureTile t = new IrisStructureTile(); - t.setForceObject(o); - t.setObjects(new KList<>("structure/" + this.structure.getLoadKey() + "/" + o.getLoadKey())); + t.getForceObjects().put(variant, o); + t.getObjects().add("structure/" + this.structure.getLoadKey() + "/" + o.getLoadKey()); t.setFloor(f); t.setCeiling(c); t.setNorth(n); diff --git a/src/main/java/com/volmit/iris/util/inventory/UIElement.java b/src/main/java/com/volmit/iris/util/inventory/UIElement.java index 578d2d15f..d3a3d056c 100644 --- a/src/main/java/com/volmit/iris/util/inventory/UIElement.java +++ b/src/main/java/com/volmit/iris/util/inventory/UIElement.java @@ -6,7 +6,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import com.volmit.iris.util.KList; -import com.volmit.iris.util.M; public class UIElement implements Element { @@ -40,6 +39,11 @@ public class UIElement implements Element return material; } + public Double clip(double value, double min, double max) + { + return Double.valueOf(Math.min(max, Math.max(min, value))); + } + @Override public UIElement setMaterial(MaterialBlock material) { @@ -191,7 +195,7 @@ public class UIElement implements Element @Override public Element setCount(int c) { - count = (int) M.clip(c, 1, 64); + count = (int) clip(c, 1, 64).intValue(); return this; } @@ -207,7 +211,7 @@ public class UIElement implements Element { try { - ItemStack is = new ItemStack(getMaterial().getMaterial(), getCount(), getEffectiveDurability(), getMaterial().getData()); + ItemStack is = new ItemStack(getMaterial().getMaterial(), getCount(), getEffectiveDurability()); ItemMeta im = is.getItemMeta(); im.setDisplayName(getName()); im.setLore(getLore().copy()); @@ -232,7 +236,7 @@ public class UIElement implements Element @Override public Element setProgress(double progress) { - this.progress = M.clip(progress, 0D, 1D); + this.progress = clip(progress, 0D, 1D); return this; } @@ -253,7 +257,7 @@ public class UIElement implements Element else { int prog = (int) ((double) getMaterial().getMaterial().getMaxDurability() * (1D - getProgress())); - return M.clip(prog, 1, (getMaterial().getMaterial().getMaxDurability() - 1)).shortValue(); + return clip(prog, 1, (getMaterial().getMaterial().getMaxDurability() - 1)).shortValue(); } } } diff --git a/src/main/java/com/volmit/iris/util/inventory/UIWindow.java b/src/main/java/com/volmit/iris/util/inventory/UIWindow.java index 117ca7901..98603f30e 100644 --- a/src/main/java/com/volmit/iris/util/inventory/UIWindow.java +++ b/src/main/java/com/volmit/iris/util/inventory/UIWindow.java @@ -15,7 +15,6 @@ import com.volmit.iris.Iris; import com.volmit.iris.util.J; import com.volmit.iris.util.KMap; import com.volmit.iris.util.KSet; -import com.volmit.iris.util.M; public class UIWindow implements Window, Listener { @@ -42,7 +41,7 @@ public class UIWindow implements Window, Listener setTitle(""); setDecorator(new UIVoidDecorator()); setResolution(WindowResolution.W9_H6); - setViewportHeight((int) M.clip(3, 1, getResolution().getMaxHeight()).intValue()); + setViewportHeight((int) clip(3, 1, getResolution().getMaxHeight()).intValue()); setViewportPosition(0); } @@ -331,7 +330,7 @@ public class UIWindow implements Window, Listener @Override public UIWindow scroll(int direction) { - viewportPosition = (int) M.clip(viewportPosition + direction, 0, getMaxViewportPosition()); + viewportPosition = (int) clip(viewportPosition + direction, 0, getMaxViewportPosition()).doubleValue(); updateInventory(); return this; @@ -346,7 +345,7 @@ public class UIWindow implements Window, Listener @Override public UIWindow setViewportHeight(int height) { - viewportSize = (int) M.clip(height, 1, getResolution().getMaxHeight()); + viewportSize = (int) clip(height, 1, getResolution().getMaxHeight()).doubleValue(); if(isVisible()) { @@ -383,7 +382,7 @@ public class UIWindow implements Window, Listener highestRow = row; } - elements.put(getRealPosition((int) M.clip(position, -getResolution().getMaxWidthOffset(), getResolution().getMaxWidthOffset()), row), e); + elements.put(getRealPosition((int) clip(position, -getResolution().getMaxWidthOffset(), getResolution().getMaxWidthOffset()).doubleValue(), row), e); updateInventory(); return this; } @@ -391,7 +390,7 @@ public class UIWindow implements Window, Listener @Override public Element getElement(int position, int row) { - return elements.get(getRealPosition((int) M.clip(position, -getResolution().getMaxWidthOffset(), getResolution().getMaxWidthOffset()), row)); + return elements.get(getRealPosition((int) clip(position, -getResolution().getMaxWidthOffset(), getResolution().getMaxWidthOffset()).doubleValue(), row)); } @Override @@ -434,7 +433,7 @@ public class UIWindow implements Window, Listener @Override public int getRealPosition(int position, int row) { - return (int) (((row * getResolution().getWidth()) + getResolution().getMaxWidthOffset()) + M.clip(position, -getResolution().getMaxWidthOffset(), getResolution().getMaxWidthOffset())); + return (int) (((row * getResolution().getWidth()) + getResolution().getMaxWidthOffset()) + clip(position, -getResolution().getMaxWidthOffset(), getResolution().getMaxWidthOffset())); } @Override @@ -472,12 +471,17 @@ public class UIWindow implements Window, Listener return resolution; } + public Double clip(double value, double min, double max) + { + return Double.valueOf(Math.min(max, Math.max(min, value))); + } + @Override public Window setResolution(WindowResolution resolution) { close(); this.resolution = resolution; - setViewportHeight((int) M.clip(getViewportHeight(), 1, getResolution().getMaxHeight())); + setViewportHeight((int) clip(getViewportHeight(), 1, getResolution().getMaxHeight()).doubleValue()); return this; }