diff --git a/src/com/dre/brewery/Barrel.java b/src/com/dre/brewery/Barrel.java index f42bb90..0c07086 100644 --- a/src/com/dre/brewery/Barrel.java +++ b/src/com/dre/brewery/Barrel.java @@ -8,6 +8,7 @@ import com.dre.brewery.filedata.BConfig; import com.dre.brewery.integration.LogBlockBarrel; import com.dre.brewery.lore.BrewLore; import com.dre.brewery.utility.BUtil; +import com.dre.brewery.utility.BoundingBox; import com.dre.brewery.utility.LegacyUtil; import org.bukkit.Location; import org.bukkit.Material; @@ -24,6 +25,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -52,7 +54,7 @@ public class Barrel implements InventoryHolder { } // load from file - public Barrel(Block spigot, byte sign, String[] st, String[] wo, Map items, float time) { + public Barrel(Block spigot, byte sign, BoundingBox bounds, Map items, float time) { this.spigot = spigot; if (isLarge()) { this.inventory = P.p.getServer().createInventory(this, 27, P.p.languageReader.get("Etc_Barrel")); @@ -68,7 +70,7 @@ public class Barrel implements InventoryHolder { } this.time = time; - body = new BarrelBody(this, sign, st, wo); + body = new BarrelBody(this, sign, bounds); } public static void onUpdate() { @@ -216,15 +218,24 @@ public class Barrel implements InventoryHolder { return body.hasBlock(block); } + /** + * Deprecated, just use hasBlock + */ + @Deprecated public boolean hasWoodBlock(Block block) { - return body.hasWoodBlock(block); + return body.hasBlock(block); } + /** + * Deprecated, just use hasBlock + */ + @Deprecated public boolean hasStairsBlock(Block block) { - return body.hasStairsBlock(block); + return body.hasBlock(block); } // Get the Barrel by Block, null if that block is not part of a barrel + @Nullable public static Barrel get(Block block) { if (block == null) { return null; @@ -232,13 +243,13 @@ public class Barrel implements InventoryHolder { Material type = block.getType(); if (LegacyUtil.isFence(type) || LegacyUtil.isSign(type) ) { return getBySpigot(block); - } else if (LegacyUtil.isWoodPlanks(type) || LegacyUtil.isWoodStairs(type)) { + } else { return getByWood(block); } - return null; } // Get the Barrel by Sign or Spigot (Fastest) + @Nullable public static Barrel getBySpigot(Block sign) { // convert spigot if neccessary Block spigot = BarrelBody.getSpigotOfSign(sign); @@ -263,16 +274,11 @@ public class Barrel implements InventoryHolder { } // Get the barrel by its corpus (Wood Planks, Stairs) + @Nullable public static Barrel getByWood(Block wood) { - if (LegacyUtil.isWoodPlanks(wood.getType())) { + if (LegacyUtil.isWoodPlanks(wood.getType()) || LegacyUtil.isWoodStairs(wood.getType())) { for (Barrel barrel : barrels) { - if (barrel.body.hasWoodBlock(wood)) { - return barrel; - } - } - } else if (LegacyUtil.isWoodStairs(wood.getType())) { - for (Barrel barrel : Barrel.barrels) { - if (barrel.body.hasStairsBlock(wood)) { + if (barrel.getSpigot().getWorld().equals(wood.getWorld()) && barrel.body.getBounds().contains(wood)) { return barrel; } } diff --git a/src/com/dre/brewery/BarrelBody.java b/src/com/dre/brewery/BarrelBody.java index c1cb350..88795a9 100644 --- a/src/com/dre/brewery/BarrelBody.java +++ b/src/com/dre/brewery/BarrelBody.java @@ -1,57 +1,43 @@ package com.dre.brewery; import com.dre.brewery.utility.BUtil; +import com.dre.brewery.utility.BoundingBox; import com.dre.brewery.utility.LegacyUtil; -import org.apache.commons.lang.ArrayUtils; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; +import java.util.Objects; // The Blocks that make up a Barrel in the World public class BarrelBody { private final Barrel barrel; private final Block spigot; - private int[] woodsloc = null; // location of wood Blocks - private int[] stairsloc = null; // location of stair Blocks + private BoundingBox bounds; private byte signoffset; public BarrelBody(Barrel barrel, byte signoffset) { this.barrel = barrel; this.signoffset = signoffset; spigot = barrel.getSpigot(); + this.bounds = new BoundingBox(0, 0, 0, 0, 0, 0); } // Loading from file - public BarrelBody(Barrel barrel, byte signoffset, String[] st, String[] wo) { + public BarrelBody(Barrel barrel, byte signoffset, BoundingBox bounds) { this(barrel, signoffset); - int i = 0; - if (wo.length > 1) { - woodsloc = new int[wo.length]; - for (String wos : wo) { - woodsloc[i] = P.p.parseInt(wos); - i++; - } - i = 0; - } - if (st.length > 1) { - stairsloc = new int[st.length]; - for (String sts : st) { - stairsloc[i] = P.p.parseInt(sts); - i++; - } - } - - if (woodsloc == null && stairsloc == null) { - // If loading from old data, or block locations are missing, regenerate them + if (bounds == null || bounds.area() > 64 ) { + // If loading from old data, or block locations are missing, or other error, regenerate BoundingBox // This will only be done in those extreme cases. Block broken = getBrokenBlock(true); if (broken != null) { barrel.remove(broken, null); } + } else { + this.bounds = bounds; } } @@ -63,20 +49,14 @@ public class BarrelBody { return spigot; } - public int[] getWoodsloc() { - return woodsloc; + @NotNull + public BoundingBox getBounds() { + return bounds; } - public void setWoodsloc(int[] woodsloc) { - this.woodsloc = woodsloc; - } - - public int[] getStairsloc() { - return stairsloc; - } - - public void setStairsloc(int[] stairsloc) { - this.stairsloc = stairsloc; + public void setBounds(@NotNull BoundingBox bounds) { + Objects.requireNonNull(bounds); + this.bounds = bounds; } public byte getSignoffset() { @@ -162,57 +142,16 @@ public class BarrelBody { } } - // Returns true if this Block is part of this Barrel + /** + * Returns true if this Block is part of this Barrel + * + * @param block the block to check + * @return true if the given block is part of this Barrel + */ public boolean hasBlock(Block block) { if (block != null) { - if (LegacyUtil.isWoodPlanks(block.getType())) { - return hasWoodBlock(block); - } else if (LegacyUtil.isWoodStairs(block.getType())) { - return hasStairsBlock(block); - } - } - return false; - } - - public boolean hasWoodBlock(Block block) { - if (woodsloc != null) { - if (spigot.getWorld() != null && spigot.getWorld().equals(block.getWorld())) { - if (woodsloc.length > 2) { - int x = block.getX(); - if (Math.abs(x - woodsloc[0]) < 10) { - for (int i = 0; i < woodsloc.length - 2; i += 3) { - if (woodsloc[i] == x) { - if (woodsloc[i + 1] == block.getY()) { - if (woodsloc[i + 2] == block.getZ()) { - return true; - } - } - } - } - } - } - } - } - return false; - } - - public boolean hasStairsBlock(Block block) { - if (stairsloc != null) { - if (spigot.getWorld() != null && spigot.getWorld().equals(block.getWorld())) { - if (stairsloc.length > 2) { - int x = block.getX(); - if (Math.abs(x - stairsloc[0]) < 10) { - for (int i = 0; i < stairsloc.length - 2; i += 3) { - if (stairsloc[i] == x) { - if (stairsloc[i + 1] == block.getY()) { - if (stairsloc[i + 2] == block.getZ()) { - return true; - } - } - } - } - } - } + if (spigot.getWorld().equals(block.getWorld())) { + return bounds != null && bounds.contains(block.getX(), block.getY(), block.getZ()); } } return false; @@ -280,29 +219,21 @@ public class BarrelBody { int endX; int endZ; - ArrayList stairs = new ArrayList<>(); - if (direction == 1) { startX = 1; - endX = startX + 1; startZ = -1; - endZ = 0; } else if (direction == 2) { startX = -2; - endX = startX + 1; startZ = 0; - endZ = 1; } else if (direction == 3) { startX = 0; - endX = 1; startZ = 1; - endZ = startZ + 1; } else { startX = -1; - endX = 0; startZ = -2; - endZ = startZ + 1; } + endX = startX + 1; + endZ = startZ + 1; Material type; int x = startX; @@ -321,9 +252,6 @@ public class BarrelBody { return block; } } - stairs.add(block.getX()); - stairs.add(block.getY()); - stairs.add(block.getZ()); z++; } else { return spigot.getRelative(x, y, z); @@ -336,7 +264,13 @@ public class BarrelBody { x = startX; y++; } - stairsloc = ArrayUtils.toPrimitive(stairs.toArray(new Integer[0])); + bounds = new BoundingBox( + spigot.getX() + startX, + spigot.getY(), + spigot.getZ() + startZ, + spigot.getX() + endX, + spigot.getY() + 1, + spigot.getZ() + endZ); return null; } @@ -350,28 +284,24 @@ public class BarrelBody { int endX; int endZ; - ArrayList stairs = new ArrayList<>(); - ArrayList woods = new ArrayList<>(); - if (direction == 1) { startX = 1; - endX = startX + 3; startZ = -1; - endZ = 1; } else if (direction == 2) { startX = -4; - endX = startX + 3; startZ = -1; - endZ = 1; } else if (direction == 3) { startX = -1; - endX = 1; startZ = 1; - endZ = startZ + 3; } else { startX = -1; - endX = 1; startZ = -4; + } + if (direction == 1 || direction == 2) { + endX = startX + 3; + endZ = startZ + 2; + } else { + endX = startX + 2; endZ = startZ + 3; } @@ -386,35 +316,16 @@ public class BarrelBody { type = block.getType(); if (direction == 1 || direction == 2) { if (y == 1 && z == 0) { - if (x == -1 || x == -4 || x == 1 || x == 4) { - woods.add(block.getX()); - woods.add(block.getY()); - woods.add(block.getZ()); - } z++; continue; } } else { if (y == 1 && x == 0) { - if (z == -1 || z == -4 || z == 1 || z == 4) { - woods.add(block.getX()); - woods.add(block.getY()); - woods.add(block.getZ()); - } z++; continue; } } if (LegacyUtil.isWoodPlanks(type) || LegacyUtil.isWoodStairs(type)) { - if (LegacyUtil.isWoodPlanks(type)) { - woods.add(block.getX()); - woods.add(block.getY()); - woods.add(block.getZ()); - } else { - stairs.add(block.getX()); - stairs.add(block.getY()); - stairs.add(block.getZ()); - } z++; } else { return block; @@ -427,8 +338,13 @@ public class BarrelBody { x = startX; y++; } - stairsloc = ArrayUtils.toPrimitive(stairs.toArray(new Integer[0])); - woodsloc = ArrayUtils.toPrimitive(woods.toArray(new Integer[0])); + bounds = new BoundingBox( + spigot.getX() + startX, + spigot.getY(), + spigot.getZ() + startZ, + spigot.getX() + endX, + spigot.getY() + 2, + spigot.getZ() + endZ); return null; } @@ -437,19 +353,6 @@ public class BarrelBody { if (signoffset != 0) { config.set(prefix + ".sign", signoffset); } - if (stairsloc != null && stairsloc.length > 0) { - StringBuilder st = new StringBuilder(); - for (int i : stairsloc) { - st.append(i).append(","); - } - config.set(prefix + ".st", st.substring(0, st.length() - 1)); - } - if (woodsloc != null && woodsloc.length > 0) { - StringBuilder wo = new StringBuilder(); - for (int i : woodsloc) { - wo.append(i).append(","); - } - config.set(prefix + ".wo", wo.substring(0, wo.length() - 1)); - } + config.set(prefix + ".bounds", bounds.serialize()); } } diff --git a/src/com/dre/brewery/filedata/BData.java b/src/com/dre/brewery/filedata/BData.java index 6d4a29a..96209eb 100644 --- a/src/com/dre/brewery/filedata/BData.java +++ b/src/com/dre/brewery/filedata/BData.java @@ -2,6 +2,8 @@ package com.dre.brewery.filedata; import com.dre.brewery.*; import com.dre.brewery.utility.BUtil; +import com.dre.brewery.utility.BoundingBox; +import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.math.NumberUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -14,6 +16,7 @@ import org.bukkit.inventory.ItemStack; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -209,19 +212,40 @@ public class BData { Block block = world.getBlockAt(P.p.parseInt(splitted[0]), P.p.parseInt(splitted[1]), P.p.parseInt(splitted[2])); float time = (float) section.getDouble(barrel + ".time", 0.0); byte sign = (byte) section.getInt(barrel + ".sign", 0); - String[] st = section.getString(barrel + ".st", "").split(","); - String[] wo = section.getString(barrel + ".wo", "").split(","); + + BoundingBox box = null; + if (section.contains(barrel + ".bounds")) { + String[] bds = section.getString(barrel + ".bounds", "").split(","); + if (bds.length == 6) { + box = new BoundingBox(P.p.parseInt(bds[0]), P.p.parseInt(bds[1]), P.p.parseInt(bds[2]), P.p.parseInt(bds[3]), P.p.parseInt(bds[4]), P.p.parseInt(bds[5])); + } + } else if (section.contains(barrel + ".st")) { + // Convert from Stair and Wood Locations to BoundingBox + String[] st = section.getString(barrel + ".st", "").split(","); + String[] wo = section.getString(barrel + ".wo", "").split(","); + int woLength = wo.length; + if (woLength <= 1) { + woLength = 0; + } + String[] points = new String[st.length + woLength]; + System.arraycopy(st, 0, points, 0, st.length); + if (woLength > 1) { + System.arraycopy(wo, 0, points, st.length, woLength); + } + int[] locs = ArrayUtils.toPrimitive(Arrays.stream(points).map(s -> P.p.parseInt(s)).toArray(Integer[]::new)); + box = BoundingBox.fromPoints(locs); + } Barrel b; if (invSection != null) { - b = new Barrel(block, sign, st, wo, invSection.getValues(true), time); + b = new Barrel(block, sign, box, invSection.getValues(true), time); } else { // Barrel has no inventory - b = new Barrel(block, sign, st, wo, null, time); + b = new Barrel(block, sign, box, null, time); } // In case Barrel Block locations were missing and could not be recreated: do not add the barrel - if (b.getBody().getStairsloc() != null || b.getBody().getWoodsloc() != null) { + if (b.getBody().getBounds() != null) { Barrel.barrels.add(b); } diff --git a/src/com/dre/brewery/listeners/PlayerListener.java b/src/com/dre/brewery/listeners/PlayerListener.java index f30e0fd..70bf2cd 100644 --- a/src/com/dre/brewery/listeners/PlayerListener.java +++ b/src/com/dre/brewery/listeners/PlayerListener.java @@ -49,11 +49,11 @@ public class PlayerListener implements Listener { Barrel barrel = null; if (LegacyUtil.isWoodPlanks(type)) { if (BConfig.openEverywhere) { - barrel = Barrel.get(clickedBlock); + barrel = Barrel.getByWood(clickedBlock); } } else if (LegacyUtil.isWoodStairs(type)) { for (Barrel barrel2 : Barrel.barrels) { - if (barrel2.getBody().hasStairsBlock(clickedBlock)) { + if (barrel2.getBody().hasBlock(clickedBlock)) { if (BConfig.openEverywhere || !barrel2.isLarge()) { barrel = barrel2; } @@ -67,6 +67,8 @@ public class PlayerListener implements Listener { if (barrel != null) { event.setCancelled(true); + P.p.debugLog("Barrel has area of: " + barrel.getBody().getBounds().area()); + if (!barrel.hasPermsOpen(player, event)) { return; } diff --git a/src/com/dre/brewery/utility/BoundingBox.java b/src/com/dre/brewery/utility/BoundingBox.java new file mode 100644 index 0000000..e5fe831 --- /dev/null +++ b/src/com/dre/brewery/utility/BoundingBox.java @@ -0,0 +1,64 @@ +package com.dre.brewery.utility; + +import org.bukkit.Location; +import org.bukkit.block.Block; + +public class BoundingBox { + + private final int x1; + private final int y1; + private final int z1; + private final int x2; + private final int y2; + private final int z2; + + public BoundingBox(int x1, int y1, int z1, int x2, int y2, int z2) { + this.x1 = Math.min(x1, x2); + this.y1 = Math.min(y1, y2); + this.z1 = Math.min(z1, z2); + this.x2 = Math.max(x2, x1); + this.y2 = Math.max(y2, y1); + this.z2 = Math.max(z2, z1); + } + + public boolean contains(int x, int y, int z) { + return (x >= x1 && x <= x2) && (y >= y1 && y <= y2) && (z >= z1 && z <= z2); + } + + public boolean contains(Location loc) { + return contains(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + } + + public boolean contains(Block block) { + return contains(block.getX(), block.getY(), block.getZ()); + } + + public int area() { + return (x2 - x1 + 1) * (y2 - y1 + 1) * (z2 - z1 + 1); + } + + public String serialize() { + return x1 + "," + y1 + "," + z1 + "," + x2 + "," + y2 + "," + z2; + } + + public static BoundingBox fromPoints(int[] locations) { + if (locations.length % 3 != 0) throw new IllegalArgumentException("Locations has to be pairs of three"); + + int length = locations.length / 3; + int minx = Integer.MAX_VALUE, + miny = Integer.MAX_VALUE, + minz = Integer.MAX_VALUE, + maxx = Integer.MIN_VALUE, + maxy = Integer.MIN_VALUE, + maxz = Integer.MIN_VALUE; + for (int i = 0; i < length; i++) { + minx = Math.min(locations[i], minx); + miny = Math.min(locations[i + 1], miny); + minz = Math.min(locations[i + 2], minz); + maxx = Math.max(locations[i], maxx); + maxy = Math.max(locations[i + 1], maxy); + maxz = Math.max(locations[i + 2], maxz); + } + return new BoundingBox(minx, miny, minz, maxx, maxy, maxz); + } +}