From 1a293a69363b367353cf0257ab7dddb8420ebf9c Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 26 Mar 2023 10:05:54 -0700 Subject: [PATCH] Implements NMS for pasting and supports older versions of server (#2110) * Implements NMS for pasting and supports older versions of server * Remove trial code that shouldn't have been committed. * Remove trial code that shouldn't have been committed. * Remove 1.19.3 support. * Use 1.19.4 in POM --- pom.xml | 3 +- .../bentobox/nms/SimpleWorldRegenerator.java | 1 - .../nms/v1_19_R3/PasteHandlerImpl.java | 82 +++++++++++++++++++ .../world/bentobox/bentobox/util/Util.java | 37 ++++++--- src/main/resources/plugin.yml | 1 + 5 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 src/main/java/world/bentobox/bentobox/nms/v1_19_R3/PasteHandlerImpl.java diff --git a/pom.xml b/pom.xml index a7659b985..38d2f4ed6 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,7 @@ 1.22.1 bentobox-world https://sonarcloud.io + ${project.basedir}/lib @@ -312,7 +313,7 @@ 3.2.2 provided - + org.spigotmc spigot diff --git a/src/main/java/world/bentobox/bentobox/nms/SimpleWorldRegenerator.java b/src/main/java/world/bentobox/bentobox/nms/SimpleWorldRegenerator.java index d46ef8415..e7142284b 100644 --- a/src/main/java/world/bentobox/bentobox/nms/SimpleWorldRegenerator.java +++ b/src/main/java/world/bentobox/bentobox/nms/SimpleWorldRegenerator.java @@ -13,7 +13,6 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; -import org.bukkit.generator.LimitedRegion; import org.bukkit.inventory.InventoryHolder; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.BoundingBox; diff --git a/src/main/java/world/bentobox/bentobox/nms/v1_19_R3/PasteHandlerImpl.java b/src/main/java/world/bentobox/bentobox/nms/v1_19_R3/PasteHandlerImpl.java new file mode 100644 index 000000000..14af30231 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/nms/v1_19_R3/PasteHandlerImpl.java @@ -0,0 +1,82 @@ +package world.bentobox.bentobox.nms.v1_19_R3; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData; + +import net.minecraft.core.BlockPosition; +import net.minecraft.world.level.block.state.IBlockData; +import net.minecraft.world.level.chunk.Chunk; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.nms.PasteHandler; +import world.bentobox.bentobox.util.DefaultPasteUtil; +import world.bentobox.bentobox.util.Util; + +public class PasteHandlerImpl implements PasteHandler { + + protected static final IBlockData AIR = ((CraftBlockData) Bukkit.createBlockData(Material.AIR)).getState(); + + @Override + public CompletableFuture pasteBlocks(Island island, World world, Map blockMap) { + return blockMap.entrySet().stream() + .map(entry -> setBlock(island, entry.getKey(), entry.getValue())) + .collect( + Collectors.collectingAndThen( + Collectors.toList(), + list -> CompletableFuture.allOf(list.toArray(new CompletableFuture[0])) + ) + ); + } + + @Override + public CompletableFuture pasteEntities(Island island, World world, Map> entityMap) { + return entityMap.entrySet().stream() + .map(entry -> DefaultPasteUtil.setEntity(island, entry.getKey(), entry.getValue())) + .collect( + Collectors.collectingAndThen( + Collectors.toList(), + list -> CompletableFuture.allOf(list.toArray(new CompletableFuture[0])) + ) + ); + } + + /** + * Set the block to the location + * + * @param island - island + * @param location - location + * @param bpBlock - blueprint block + */ + public static CompletableFuture setBlock(Island island, Location location, BlueprintBlock bpBlock) { + return Util.getChunkAtAsync(location).thenRun(() -> { + Block block = location.getBlock(); + // Set the block data - default is AIR + BlockData bd = DefaultPasteUtil.createBlockData(bpBlock); + CraftBlockData craft = (CraftBlockData) bd; + net.minecraft.world.level.World nmsWorld = ((CraftWorld) location.getWorld()).getHandle(); + Chunk nmsChunk = nmsWorld.d(location.getBlockX() >> 4, location.getBlockZ() >> 4); + BlockPosition bp = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + // Setting the block to air before setting to another state prevents some console errors + nmsChunk.a(bp, AIR, false); + nmsChunk.a(bp, craft.getState(), false); + block.setBlockData(bd, false); + DefaultPasteUtil.setBlockState(island, block, bpBlock); + // Set biome + if (bpBlock.getBiome() != null) { + block.setBiome(bpBlock.getBiome()); + } + }); + } +} diff --git a/src/main/java/world/bentobox/bentobox/util/Util.java b/src/main/java/world/bentobox/bentobox/util/Util.java index 822bf7ef7..b804d5d73 100644 --- a/src/main/java/world/bentobox/bentobox/util/Util.java +++ b/src/main/java/world/bentobox/bentobox/util/Util.java @@ -738,6 +738,32 @@ public class Util { } return regenerator; } + + /** + * Checks what version the server is running and picks the appropriate NMS handler, or fallback + * @return PasteHandler + */ + public static PasteHandler getPasteHandler() { + if (pasteHandler == null) { + String serverPackageName = Bukkit.getServer().getClass().getPackage().getName(); + String pluginPackageName = plugin.getClass().getPackage().getName(); + String version = serverPackageName.substring(serverPackageName.lastIndexOf('.') + 1); + PasteHandler handler; + try { + Class clazz = Class.forName(pluginPackageName + ".nms." + version + ".PasteHandlerImpl"); + if (PasteHandler.class.isAssignableFrom(clazz)) { + handler = (PasteHandler) clazz.getConstructor().newInstance(); + } else { + throw new IllegalStateException("Class " + clazz.getName() + " does not implement PasteHandler"); + } + } catch (Exception e) { + plugin.logWarning("No PasteHandler found for " + version + ", falling back to Bukkit API."); + handler = new world.bentobox.bentobox.nms.fallback.PasteHandlerImpl(); + } + setPasteHandler(handler); + } + return pasteHandler; + } /** * Set the paste handler the plugin will use @@ -747,17 +773,6 @@ public class Util { Util.pasteHandler = pasteHandler; } - /** - * Get the paste handler the plugin will use - * @return an NMS accelerated class for this server - */ - public static PasteHandler getPasteHandler() { - if (pasteHandler == null) { - setPasteHandler(new world.bentobox.bentobox.nms.fallback.PasteHandlerImpl()); - } - return pasteHandler; - } - /** * Broadcast a localized message to all players with the permission {@link Server#BROADCAST_CHANNEL_USERS} * diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index bc5ef1ccb..1d84e6f85 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -60,3 +60,4 @@ permissions: bentobox.version: description: Allows to use /bentobox version default: op +