diff --git a/API/src/main/java/com/bgsoftware/superiorskyblock/api/island/Island.java b/API/src/main/java/com/bgsoftware/superiorskyblock/api/island/Island.java index 444ad9243..020479930 100644 --- a/API/src/main/java/com/bgsoftware/superiorskyblock/api/island/Island.java +++ b/API/src/main/java/com/bgsoftware/superiorskyblock/api/island/Island.java @@ -1679,6 +1679,22 @@ public interface Island extends Comparable, IMissionsHolder { */ void clearGeneratorAmounts(World.Environment environment); + /** + * Generate a block at a specified location. + * The method calculates a block to generate from {@link #getGeneratorAmounts(World.Environment)}. + * It doesn't look for any conditions for generating it - lava, water, etc are not required. + * The method will fail if there are no valid generator rates for the environment. + * + * @param location The location to generate block at. + * @param optimizeCobblestone When set to true and cobblestone needs to be generated, the plugin will + * not play effects, count the block towards the block counts or set the block. + * This is useful when calling the method from BlockFromToEvent, and instead of letting + * the player do the logic of vanilla, the plugin lets the game do it. + * @return The block type that was generated, null if failed. + */ + @Nullable + Key generateBlock(Location location, boolean optimizeCobblestone); + /* * Schematic methods */ diff --git a/src/main/java/com/bgsoftware/superiorskyblock/island/SIsland.java b/src/main/java/com/bgsoftware/superiorskyblock/island/SIsland.java index 0636290df..e8f13f587 100644 --- a/src/main/java/com/bgsoftware/superiorskyblock/island/SIsland.java +++ b/src/main/java/com/bgsoftware/superiorskyblock/island/SIsland.java @@ -68,6 +68,7 @@ import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.WeatherType; import org.bukkit.World; import org.bukkit.block.Biome; @@ -101,6 +102,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; @@ -2944,6 +2946,68 @@ public void clearGeneratorAmounts(World.Environment environment) { } } + @Override + public Key generateBlock(Location location, boolean optimizeCobblestone) { + Preconditions.checkNotNull(location, "location parameter cannot be null."); + Preconditions.checkNotNull(location.getWorld(), "location's world cannot be null."); + + World.Environment environment = location.getWorld().getEnvironment(); + + int totalGeneratorAmounts = getGeneratorTotalAmount(environment); + + if (totalGeneratorAmounts == 0) + return null; + + Map generatorAmounts = getGeneratorAmounts(environment); + + String newState = "COBBLESTONE"; + + if (totalGeneratorAmounts == 1) { + newState = generatorAmounts.keySet().iterator().next(); + } else { + int generatedIndex = ThreadLocalRandom.current().nextInt(totalGeneratorAmounts); + int currentIndex = 0; + for (Map.Entry entry : generatorAmounts.entrySet()) { + currentIndex += entry.getValue(); + if (generatedIndex < currentIndex) { + newState = entry.getKey(); + break; + } + } + } + + Key generatedBlock = Key.of(newState); + + String[] typeSections = newState.split(":"); + + if (optimizeCobblestone && typeSections[0].contains("COBBLESTONE")) + /* Block is being counted in BlocksListener#onBlockFromToMonitor */ + return generatedBlock; + + // If the block is a custom block, and the event was cancelled - we need to call the handleBlockPlace manually. + handleBlockPlace(generatedBlock, 1); + + Material generateBlockType = Material.valueOf(typeSections[0]); + byte blockData = typeSections.length == 2 ? Byte.parseByte(typeSections[1]) : 0; + int combinedId = plugin.getNMSAlgorithms().getCombinedId(generateBlockType, blockData); + + if (combinedId == -1) { + SuperiorSkyblockPlugin.log("&cFailed to generate block for type " + generateBlockType + ":" + blockData); + generateBlockType = Material.COBBLESTONE; + blockData = 0; + combinedId = plugin.getNMSAlgorithms().getCombinedId(generateBlockType, blockData); + } + + PluginDebugger.debug("Action: Generate Block, Island: " + getOwner().getName() + + ", Block: " + generateBlockType + ":" + blockData); + + plugin.getNMSWorld().setBlock(location, combinedId); + + plugin.getNMSWorld().playGeneratorSound(location); + + return generatedBlock; + } + /* * Settings related methods */ diff --git a/src/main/java/com/bgsoftware/superiorskyblock/island/spawn/SpawnIsland.java b/src/main/java/com/bgsoftware/superiorskyblock/island/spawn/SpawnIsland.java index b60acc3a5..083e5a5e9 100644 --- a/src/main/java/com/bgsoftware/superiorskyblock/island/spawn/SpawnIsland.java +++ b/src/main/java/com/bgsoftware/superiorskyblock/island/spawn/SpawnIsland.java @@ -1364,6 +1364,12 @@ public void clearGeneratorAmounts(World.Environment environment) { // Do nothing. } + @Nullable + @Override + public Key generateBlock(Location location, boolean optimizeCobblestone) { + return null; + } + @Override public boolean wasSchematicGenerated(World.Environment environment) { return true; diff --git a/src/main/java/com/bgsoftware/superiorskyblock/key/ConstantKeys.java b/src/main/java/com/bgsoftware/superiorskyblock/key/ConstantKeys.java index a6e4beabf..a54f3ff3c 100644 --- a/src/main/java/com/bgsoftware/superiorskyblock/key/ConstantKeys.java +++ b/src/main/java/com/bgsoftware/superiorskyblock/key/ConstantKeys.java @@ -21,6 +21,8 @@ public final class ConstantKeys { public static final Key END_PORTAL_FRAME_WITH_EYE = Key.of(Materials.END_PORTAL_FRAME.toBukkitType(), (short) 7); public static final Key END_PORTAL_FRAME = Key.of(Materials.END_PORTAL_FRAME.toBukkitType().name()); public static final Key WET_SPONGE = Key.of("WET_SPONGE"); + public static final Key COBBLESTONE = Key.of("COBBLESTONE"); + private ConstantKeys() { } diff --git a/src/main/java/com/bgsoftware/superiorskyblock/module/generators/listeners/GeneratorsListener.java b/src/main/java/com/bgsoftware/superiorskyblock/module/generators/listeners/GeneratorsListener.java index bb47c492a..efaa966ac 100644 --- a/src/main/java/com/bgsoftware/superiorskyblock/module/generators/listeners/GeneratorsListener.java +++ b/src/main/java/com/bgsoftware/superiorskyblock/module/generators/listeners/GeneratorsListener.java @@ -2,10 +2,10 @@ import com.bgsoftware.superiorskyblock.SuperiorSkyblockPlugin; import com.bgsoftware.superiorskyblock.api.island.Island; -import com.bgsoftware.superiorskyblock.key.Key; +import com.bgsoftware.superiorskyblock.api.key.Key; +import com.bgsoftware.superiorskyblock.key.ConstantKeys; import com.bgsoftware.superiorskyblock.module.generators.GeneratorsModule; import com.bgsoftware.superiorskyblock.utils.ServerVersion; -import com.bgsoftware.superiorskyblock.utils.debug.PluginDebugger; import com.bgsoftware.superiorskyblock.utils.legacy.Materials; import org.bukkit.Material; import org.bukkit.World; @@ -17,10 +17,6 @@ import org.bukkit.event.block.BlockFormEvent; import org.bukkit.event.block.BlockFromToEvent; -import javax.annotation.Nullable; -import java.util.Map; -import java.util.concurrent.ThreadLocalRandom; - @SuppressWarnings("unused") public final class GeneratorsListener implements Listener { @@ -53,7 +49,9 @@ public void onBlockFormEvent(BlockFormEvent e) { if (e.getBlock().getType() != LAVA_MATERIAL || e.getNewState().getType() != BASALT_MATERIAL) return; - if (performBlockGeneration(e.getBlock(), island)) + Key generatedBlock = island.generateBlock(e.getBlock().getLocation(), true); + + if (generatedBlock != null && !generatedBlock.equals(ConstantKeys.COBBLESTONE)) e.setCancelled(true); } @@ -77,65 +75,10 @@ public void onBlockFromToEvent(BlockFromToEvent e) { if (block.getType().isSolid()) return; - if (performBlockGeneration(block, island)) - e.setCancelled(true); - } - - private boolean performBlockGeneration(Block block, Island island) { - World.Environment environment = block.getWorld().getEnvironment(); - Map generatorAmounts = island.getGeneratorAmounts(environment); - - int totalGeneratorAmounts = island.getGeneratorTotalAmount(environment); - - if (totalGeneratorAmounts == 0) - return false; - - String newState = "COBBLESTONE"; - - if (totalGeneratorAmounts == 1) { - newState = generatorAmounts.keySet().iterator().next(); - } else { - int generatedIndex = ThreadLocalRandom.current().nextInt(totalGeneratorAmounts); - int currentIndex = 0; - for (Map.Entry entry : generatorAmounts.entrySet()) { - currentIndex += entry.getValue(); - if (generatedIndex < currentIndex) { - newState = entry.getKey(); - break; - } - } - } + Key generatedBlock = island.generateBlock(block.getLocation(), true); - String[] typeSections = newState.split(":"); - - /* Block is being placed in BlocksListener#onBlockFromToMonitor - island.handleBlockPlace(Key.of(newState), 1); */ - - if (typeSections[0].contains("COBBLESTONE")) - return false; - - // If the block is a custom block, and the event was cancelled - we need to call the handleBlockPlace manually. - island.handleBlockPlace(Key.of(newState), 1); - - Material generateBlockType = Material.valueOf(typeSections[0]); - byte blockData = typeSections.length == 2 ? Byte.parseByte(typeSections[1]) : 0; - int combinedId = plugin.getNMSAlgorithms().getCombinedId(generateBlockType, blockData); - - if (combinedId == -1) { - SuperiorSkyblockPlugin.log("&cFailed to generate block for type " + generateBlockType + ":" + blockData); - generateBlockType = Material.COBBLESTONE; - blockData = 0; - combinedId = plugin.getNMSAlgorithms().getCombinedId(generateBlockType, blockData); - } - - PluginDebugger.debug("Action: Generate Block, Island: " + island.getOwner().getName() + - ", Block: " + generateBlockType + ":" + blockData); - - plugin.getNMSWorld().setBlock(block.getLocation(), combinedId); - - plugin.getNMSWorld().playGeneratorSound(block.getLocation()); - - return true; + if (generatedBlock != null && !generatedBlock.equals(ConstantKeys.COBBLESTONE)) + e.setCancelled(true); } private boolean canGenerateBlock(Block block) {