diff --git a/src/main/java/io/github/thebusybiscuit/exoticgarden/Berry.java b/src/main/java/io/github/thebusybiscuit/exoticgarden/Berry.java index 32b33430..b6e82402 100644 --- a/src/main/java/io/github/thebusybiscuit/exoticgarden/Berry.java +++ b/src/main/java/io/github/thebusybiscuit/exoticgarden/Berry.java @@ -1,7 +1,7 @@ package io.github.thebusybiscuit.exoticgarden; -import java.util.Arrays; -import java.util.List; +import java.util.EnumSet; +import java.util.Set; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -13,6 +13,8 @@ public class Berry { + private static final Set SOILS = EnumSet.of(Material.GRASS_BLOCK, Material.DIRT); + private final ItemStack item; private final String id; private final String texture; @@ -59,8 +61,7 @@ public String toBush() { } public boolean isSoil(Material type) { - List soils = Arrays.asList(Material.GRASS_BLOCK, Material.DIRT); - return soils.contains(type); + return SOILS.contains(type); } } diff --git a/src/main/java/io/github/thebusybiscuit/exoticgarden/ExoticGarden.java b/src/main/java/io/github/thebusybiscuit/exoticgarden/ExoticGarden.java index cb9fd4a5..e9c093cd 100644 --- a/src/main/java/io/github/thebusybiscuit/exoticgarden/ExoticGarden.java +++ b/src/main/java/io/github/thebusybiscuit/exoticgarden/ExoticGarden.java @@ -392,14 +392,14 @@ public static ItemStack harvestPlant(@Nonnull Block block) { BlockStorage.deleteLocationInfoUnsafely(block.getLocation(), false); block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, Material.OAK_LEAVES); - block.setType(Material.AIR); + block.setType(Material.AIR, false); - plant.setType(Material.OAK_SAPLING); + plant.setType(Material.OAK_SAPLING, false); BlockStorage.deleteLocationInfoUnsafely(plant.getLocation(), false); BlockStorage.store(plant, getItem(berry.toBush())); return berry.getItem().clone(); default: - block.setType(Material.OAK_SAPLING); + block.setType(Material.OAK_SAPLING, false); BlockStorage.deleteLocationInfoUnsafely(block.getLocation(), false); BlockStorage.store(block, getItem(berry.toBush())); return berry.getItem().clone(); @@ -423,7 +423,7 @@ public void harvestFruit(Block fruit) { ItemStack fruits = check.getItem().clone(); fruit.getWorld().playEffect(loc, Effect.STEP_SOUND, Material.OAK_LEAVES); fruit.getWorld().dropItemNaturally(loc, fruits); - fruit.setType(Material.AIR); + fruit.setType(Material.AIR, false); } } diff --git a/src/main/java/io/github/thebusybiscuit/exoticgarden/Tree.java b/src/main/java/io/github/thebusybiscuit/exoticgarden/Tree.java index 6714e955..0e500907 100644 --- a/src/main/java/io/github/thebusybiscuit/exoticgarden/Tree.java +++ b/src/main/java/io/github/thebusybiscuit/exoticgarden/Tree.java @@ -3,7 +3,8 @@ import java.io.File; import java.io.IOException; import java.util.Arrays; -import java.util.List; +import java.util.Collection; +import java.util.EnumSet; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -16,7 +17,7 @@ public class Tree { private final String sapling; private final String texture; private final String fruit; - private final List soils; + private final Collection soils; private Schematic schematic; @@ -24,7 +25,7 @@ public Tree(String fruit, String texture, Material... soil) { this.sapling = fruit + "_SAPLING"; this.texture = texture; this.fruit = fruit; - this.soils = Arrays.asList(soil); + this.soils = EnumSet.copyOf(Arrays.asList(soil)); } public Schematic getSchematic() throws IOException { diff --git a/src/main/java/io/github/thebusybiscuit/exoticgarden/listeners/PlantsListener.java b/src/main/java/io/github/thebusybiscuit/exoticgarden/listeners/PlantsListener.java index 30bf7afc..9912adfd 100644 --- a/src/main/java/io/github/thebusybiscuit/exoticgarden/listeners/PlantsListener.java +++ b/src/main/java/io/github/thebusybiscuit/exoticgarden/listeners/PlantsListener.java @@ -157,7 +157,7 @@ private void growStructure(StructureGrowEvent e) { for (Tree tree : ExoticGarden.getTrees()) { if (item.getId().equalsIgnoreCase(tree.getSapling())) { BlockStorage.clearBlockInfo(e.getLocation()); - Schematic.pasteSchematic(e.getLocation(), tree); + Schematic.pasteSchematic(e.getLocation(), tree, false); return; } } @@ -166,7 +166,7 @@ private void growStructure(StructureGrowEvent e) { if (item.getId().equalsIgnoreCase(berry.toBush())) { switch (berry.getType()) { case BUSH: - e.getLocation().getBlock().setType(Material.OAK_LEAVES); + e.getLocation().getBlock().setType(Material.OAK_LEAVES, false); break; case ORE_PLANT: case DOUBLE_PLANT: @@ -186,16 +186,16 @@ private void growStructure(StructureGrowEvent e) { } BlockStorage.store(blockAbove, berry.getItem()); - e.getLocation().getBlock().setType(Material.OAK_LEAVES); - blockAbove.setType(Material.PLAYER_HEAD); + e.getLocation().getBlock().setType(Material.OAK_LEAVES, false); + blockAbove.setType(Material.PLAYER_HEAD, false); Rotatable rotatable = (Rotatable) blockAbove.getBlockData(); rotatable.setRotation(faces[ThreadLocalRandom.current().nextInt(faces.length)]); - blockAbove.setBlockData(rotatable); + blockAbove.setBlockData(rotatable, false); PlayerHead.setSkin(blockAbove, PlayerSkin.fromHashCode(berry.getTexture()), true); break; default: - e.getLocation().getBlock().setType(Material.PLAYER_HEAD); + e.getLocation().getBlock().setType(Material.PLAYER_HEAD, false); Rotatable s = (Rotatable) e.getLocation().getBlock().getBlockData(); s.setRotation(faces[ThreadLocalRandom.current().nextInt(faces.length)]); e.getLocation().getBlock().setBlockData(s); @@ -216,8 +216,8 @@ private void growStructure(StructureGrowEvent e) { private void pasteTree(ChunkPopulateEvent e, int x, int z, Tree tree) { for (int y = e.getWorld().getMaxHeight(); y > 30; y--) { Block current = e.getWorld().getBlockAt(x, y, z); - if (!current.getType().isSolid() && current.getType() != Material.WATER && current.getType() != Material.SEAGRASS && current.getType() != Material.TALL_SEAGRASS && !(current.getBlockData() instanceof Waterlogged && ((Waterlogged) current.getBlockData()).isWaterlogged()) && tree.isSoil(current.getRelative(0, -1, 0).getType()) && isFlat(current)) { - Schematic.pasteSchematic(new Location(e.getWorld(), x, y, z), tree); + if (current.getType() != Material.WATER && current.getType() != Material.SEAGRASS && current.getType() != Material.TALL_SEAGRASS && !current.getType().isSolid() && !(current.getBlockData() instanceof Waterlogged && ((Waterlogged) current.getBlockData()).isWaterlogged()) && tree.isSoil(current.getRelative(0, -1, 0).getType()) && isFlat(current)) { + Schematic.pasteSchematic(e.getWorld(), x, y, z, tree, false); break; } } @@ -226,12 +226,12 @@ private void pasteTree(ChunkPopulateEvent e, int x, int z, Tree tree) { private void growBush(ChunkPopulateEvent e, int x, int z, Berry berry, Random random, boolean isPaper) { for (int y = e.getWorld().getMaxHeight(); y > 30; y--) { Block current = e.getWorld().getBlockAt(x, y, z); - if (!current.getType().isSolid() && current.getType() != Material.WATER && berry.isSoil(current.getRelative(BlockFace.DOWN).getType())) { + if (current.getType() != Material.WATER && !current.getType().isSolid() && berry.isSoil(current.getRelative(BlockFace.DOWN).getType())) { BlockStorage.store(current, berry.getItem()); switch (berry.getType()) { case BUSH: if (isPaper) { - current.setType(Material.OAK_LEAVES); + current.setType(Material.OAK_LEAVES, false); } else { plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> current.setType(Material.OAK_LEAVES)); @@ -239,10 +239,10 @@ private void growBush(ChunkPopulateEvent e, int x, int z, Berry berry, Random ra break; case FRUIT: if (isPaper) { - current.setType(Material.PLAYER_HEAD); + current.setType(Material.PLAYER_HEAD, false); Rotatable s = (Rotatable) current.getBlockData(); s.setRotation(faces[random.nextInt(faces.length)]); - current.setBlockData(s); + current.setBlockData(s, false); PlayerHead.setSkin(current, PlayerSkin.fromHashCode(berry.getTexture()), true); } else { @@ -250,7 +250,7 @@ private void growBush(ChunkPopulateEvent e, int x, int z, Berry berry, Random ra current.setType(Material.PLAYER_HEAD); Rotatable s = (Rotatable) current.getBlockData(); s.setRotation(faces[random.nextInt(faces.length)]); - current.setBlockData(s); + current.setBlockData(s, false); PlayerHead.setSkin(current, PlayerSkin.fromHashCode(berry.getTexture()), true); }); } @@ -258,20 +258,20 @@ private void growBush(ChunkPopulateEvent e, int x, int z, Berry berry, Random ra case ORE_PLANT: case DOUBLE_PLANT: if (isPaper) { - current.setType(Material.PLAYER_HEAD); + current.setType(Material.PLAYER_HEAD, false); Rotatable s = (Rotatable) current.getBlockData(); s.setRotation(faces[random.nextInt(faces.length)]); - current.setBlockData(s); + current.setBlockData(s, false); PlayerHead.setSkin(current, PlayerSkin.fromHashCode(berry.getTexture()), true); } else { plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { BlockStorage.store(current.getRelative(BlockFace.UP), berry.getItem()); - current.setType(Material.OAK_LEAVES); - current.getRelative(BlockFace.UP).setType(Material.PLAYER_HEAD); + current.setType(Material.OAK_LEAVES, false); + current.getRelative(BlockFace.UP).setType(Material.PLAYER_HEAD, false); Rotatable ss = (Rotatable) current.getRelative(BlockFace.UP).getBlockData(); ss.setRotation(faces[random.nextInt(faces.length)]); - current.getRelative(BlockFace.UP).setBlockData(ss); + current.getRelative(BlockFace.UP).setBlockData(ss, false); PlayerHead.setSkin(current.getRelative(BlockFace.UP), PlayerSkin.fromHashCode(berry.getTexture()), true); }); } @@ -301,7 +301,7 @@ private boolean isFlat(Block current) { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onHarvest(BlockBreakEvent e) { if (Slimefun.getProtectionManager().hasPermission(e.getPlayer(), e.getBlock().getLocation(), Interaction.BREAK_BLOCK)) { - if (e.getBlock().getType().equals(Material.PLAYER_HEAD) || Tag.LEAVES.isTagged(e.getBlock().getType())) { + if (e.getBlock().getType() == Material.PLAYER_HEAD || Tag.LEAVES.isTagged(e.getBlock().getType())) { dropFruitFromTree(e.getBlock()); } @@ -348,7 +348,7 @@ public void onDecay(LeavesDecayEvent e) { if (item != null) { e.setCancelled(true); - e.getBlock().setType(Material.AIR); + e.getBlock().setType(Material.AIR, false); e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), item); } } @@ -429,7 +429,7 @@ private void dropFruitFromTree(Block block) { ItemStack fruits = check.getItem(); fruit.getWorld().playEffect(loc, Effect.STEP_SOUND, Material.OAK_LEAVES); fruit.getWorld().dropItemNaturally(loc, fruits); - fruit.setType(Material.AIR); + fruit.setType(Material.AIR, false); break; } } diff --git a/src/main/java/io/github/thebusybiscuit/exoticgarden/schematics/Schematic.java b/src/main/java/io/github/thebusybiscuit/exoticgarden/schematics/Schematic.java index 253eebfe..887cf251 100644 --- a/src/main/java/io/github/thebusybiscuit/exoticgarden/schematics/Schematic.java +++ b/src/main/java/io/github/thebusybiscuit/exoticgarden/schematics/Schematic.java @@ -9,6 +9,7 @@ import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.Rotatable; @@ -51,6 +52,8 @@ */ public class Schematic { + private static final BlockFace[] BLOCK_FACES = { BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST, BlockFace.WEST, BlockFace.NORTH_WEST }; + private final short[] blocks; private final byte[] data; private final short width; @@ -106,7 +109,11 @@ public short getHeight() { return height; } - public static void pasteSchematic(Location loc, Tree tree) { + public static void pasteSchematic(Location loc, Tree tree, boolean doPhysics) { + pasteSchematic(loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), tree, doPhysics); + } + + public static void pasteSchematic(World world, int x1, int y1, int z1, Tree tree, boolean doPhysics) { Schematic schematic; try { @@ -117,7 +124,6 @@ public static void pasteSchematic(Location loc, Tree tree) { return; } - BlockFace[] faces = { BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST, BlockFace.WEST, BlockFace.NORTH_WEST }; short[] blocks = schematic.getBlocks(); byte[] blockData = schematic.getData(); @@ -125,23 +131,27 @@ public static void pasteSchematic(Location loc, Tree tree) { short width = schematic.getWidth(); short height = schematic.getHeight(); + // Performance - avoid repeatedly calculating this value in a loop + int processedX = x1 - length / 2; + int processedZ = z1 - width / 2; + for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { for (int z = 0; z < length; ++z) { int index = y * width * length + z * width + x; - int blockX = x + loc.getBlockX() - length / 2; - int blockY = y + loc.getBlockY(); - int blockZ = z + loc.getBlockZ() - width / 2; - Block block = new Location(loc.getWorld(), blockX, blockY, blockZ).getBlock(); + int blockX = x + processedX; + int blockY = y + y1; + int blockZ = z + processedZ; + Block block = world.getBlockAt(blockX, blockY, blockZ); Material blockType = block.getType(); - if ((!blockType.isSolid() && !blockType.isInteractable() && !SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(blockType)) || blockType == Material.AIR || blockType == Material.CAVE_AIR || org.bukkit.Tag.SAPLINGS.isTagged(blockType)) { + if (blockType.isAir() || org.bukkit.Tag.SAPLINGS.isTagged(blockType) || (!blockType.isSolid() && !blockType.isInteractable() && !SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(blockType))) { Material material = parseId(blocks[index], blockData[index]); if (material != null) { if (blocks[index] != 0) { - block.setType(material); + block.setType(material, doPhysics); } if (org.bukkit.Tag.LEAVES.isTagged(material)) { @@ -151,8 +161,8 @@ public static void pasteSchematic(Location loc, Tree tree) { } else if (material == Material.PLAYER_HEAD) { Rotatable s = (Rotatable) block.getBlockData(); - s.setRotation(faces[ThreadLocalRandom.current().nextInt(faces.length)]); - block.setBlockData(s); + s.setRotation(BLOCK_FACES[ThreadLocalRandom.current().nextInt(BLOCK_FACES.length)]); + block.setBlockData(s, doPhysics); PlayerHead.setSkin(block, PlayerSkin.fromHashCode(tree.getTexture()), true); BlockStorage.store(block, tree.getFruit());