From d79caba5434756ad91d74566939bd26b04d533c1 Mon Sep 17 00:00:00 2001 From: YouHaveTrouble Date: Fri, 23 Jul 2021 02:10:30 +0200 Subject: [PATCH] //replace --- .../youhavetrouble/blockedit/BlockEdit.java | 7 ++ .../blockedit/commands/ReplaceCommand.java | 70 +++++++++++++++++++ .../operations/ReplaceOperation.java | 60 ++++++++++++++++ src/main/resources/plugin.yml | 5 +- 4 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/main/java/me/youhavetrouble/blockedit/commands/ReplaceCommand.java create mode 100644 src/main/java/me/youhavetrouble/blockedit/operations/ReplaceOperation.java diff --git a/src/main/java/me/youhavetrouble/blockedit/BlockEdit.java b/src/main/java/me/youhavetrouble/blockedit/BlockEdit.java index c6eda32..7240f45 100644 --- a/src/main/java/me/youhavetrouble/blockedit/BlockEdit.java +++ b/src/main/java/me/youhavetrouble/blockedit/BlockEdit.java @@ -1,6 +1,7 @@ package me.youhavetrouble.blockedit; import me.youhavetrouble.blockedit.api.BlockEditWands; +import me.youhavetrouble.blockedit.commands.ReplaceCommand; import me.youhavetrouble.blockedit.commands.SetCommand; import me.youhavetrouble.blockedit.commands.WandCommand; import me.youhavetrouble.blockedit.wands.SelectionWand; @@ -35,6 +36,12 @@ public final class BlockEdit extends JavaPlugin { bukkitSetCommand.setExecutor(setCommand); bukkitSetCommand.setTabCompleter(setCommand); } + ReplaceCommand replaceCommand = new ReplaceCommand(); + PluginCommand bukkitReplaceCommand = getCommand("/replace"); + if (bukkitReplaceCommand != null) { + bukkitReplaceCommand.setExecutor(replaceCommand); + bukkitReplaceCommand.setTabCompleter(replaceCommand); + } } diff --git a/src/main/java/me/youhavetrouble/blockedit/commands/ReplaceCommand.java b/src/main/java/me/youhavetrouble/blockedit/commands/ReplaceCommand.java new file mode 100644 index 0000000..fb511ed --- /dev/null +++ b/src/main/java/me/youhavetrouble/blockedit/commands/ReplaceCommand.java @@ -0,0 +1,70 @@ +package me.youhavetrouble.blockedit.commands; + +import me.youhavetrouble.blockedit.BEPlayer; +import me.youhavetrouble.blockedit.WorkSplitter; +import me.youhavetrouble.blockedit.operations.ReplaceOperation; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.bukkit.util.BoundingBox; +import org.bukkit.util.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class ReplaceCommand implements TabExecutor { + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player player)) return true; + if (args.length == 0) { + player.sendMessage(Component.text("You need to provide block type")); + return true; + } + if (args.length < 2) { + player.sendMessage(Component.text("You need to provide block type to replace")); + return true; + } + Material materialToReplace = Material.getMaterial(args[0].toUpperCase()); + if (materialToReplace == null) { + player.sendMessage(Component.text("Provided material does not exist")); + return true; + } + Material material = Material.getMaterial(args[1].toUpperCase()); + if (material == null) { + player.sendMessage(Component.text("Provided material does not exist")); + return true; + } + + BlockData blockData = material.createBlockData(); + BlockData blockDataToReplaceWith = materialToReplace.createBlockData(); + BEPlayer bePlayer = BEPlayer.getByPlayer(player); + BoundingBox selection = bePlayer.getSelection(); + if (selection == null) { + player.sendMessage(Component.text("You need to select 2 points to do this")); + return true; + } + new ReplaceOperation(WorkSplitter.getOperatedOnChunks(selection), bePlayer,blockDataToReplaceWith, blockData, 1); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1 || args.length == 2) { + ArrayList suggestions = new ArrayList<>(); + for (Material material : Material.values()) { + if (material.isBlock()) + suggestions.add(material.name().toLowerCase()); + } + return StringUtil.copyPartialMatches(args[args.length-1], suggestions, new ArrayList<>()); + } + return null; + } + +} diff --git a/src/main/java/me/youhavetrouble/blockedit/operations/ReplaceOperation.java b/src/main/java/me/youhavetrouble/blockedit/operations/ReplaceOperation.java new file mode 100644 index 0000000..a200b63 --- /dev/null +++ b/src/main/java/me/youhavetrouble/blockedit/operations/ReplaceOperation.java @@ -0,0 +1,60 @@ +package me.youhavetrouble.blockedit.operations; + +import me.youhavetrouble.blockedit.BEPlayer; +import me.youhavetrouble.blockedit.BlockEdit; +import me.youhavetrouble.blockedit.util.ChunkWork; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.util.BoundingBox; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +public class ReplaceOperation { + + private final BoundingBox selection; + private final BlockData blockToSet, getBlockToReplace; + private final List chunkwork = new ArrayList<>(); + + public ReplaceOperation(HashSet chunkWorks, BEPlayer bePlayer,BlockData blockToReplace , BlockData blockToSet, int chunksPerTick) { + this.selection = bePlayer.getSelection(); + this.blockToSet = blockToSet; + this.getBlockToReplace = blockToReplace; + this.chunkwork.addAll(chunkWorks); + AtomicInteger element = new AtomicInteger(chunkwork.size()-1); + + Bukkit.getScheduler().runTaskTimer(BlockEdit.getPlugin(), (task) -> { + if (element.get() < 0) { + task.cancel(); + return; + } + for (int i = 0; i<= chunksPerTick; i++) { + processChunkWork(chunkwork.get(element.getAndDecrement()), bePlayer.getSelectionWorld()); + } + }, 0, 1); + } + + private void processChunkWork(ChunkWork chunkWork, UUID worldUuid) { + World world = Bukkit.getWorld(worldUuid); + if (world == null) return; + chunkWork.getChunkAsync(world).thenAccept(chunk -> { + // skip y levels that are not in the selection + for (int y = (int) selection.getMinY(); y <= selection.getMaxY(); y++) { + for (int x = 0; x <= 15; x++) { + for (int z = 0; z <= 15; z++) { + Block block = chunk.getBlock(x, y, z); + if (!selection.contains(block.getLocation().toVector())) continue; + if (block.getBlockData().matches(getBlockToReplace)) + block.setBlockData(blockToSet); + } + } + } + }); + } + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 4c7b3f1..9825f02 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -13,4 +13,7 @@ commands: description: Gives you a blockedit wand /set: permission: blockedit.set - description: Set selection to chosen block + description: Set selection area to chosen block + /replace: + permission: blockedit.replace + description: Replace selected blocks in selection area