diff --git a/build.gradle b/build.gradle index f672864..75f99b8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,10 @@ plugins { id 'java' + id("xyz.jpenilla.run-paper") version "2.3.1" } group = 'de.shiewk' -version = '3.0.1' +version = pluginVersion repositories { mavenCentral() @@ -11,14 +12,11 @@ repositories { name = "papermc-repo" url = "https://repo.papermc.io/repository/maven-public/" } - maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/groups/public/" - } } dependencies { - compileOnly("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT") + //compileOnly("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT") + compileOnly 'dev.folia:folia-api:1.20.6-R0.1-SNAPSHOT' } def targetJavaVersion = 21 @@ -39,11 +37,26 @@ tasks.withType(JavaCompile).configureEach { } } +runPaper { + folia { + registerTask() + } +} + +runServer { + minecraftVersion("1.21.6") + downloadPlugins { + // for testing from other client versions + modrinth("ViaVersion", "5.4.1") + modrinth("ViaBackwards", "5.4.1") + } +} + processResources { def props = [version: version] inputs.properties props filteringCharset 'UTF-8' - filesMatching('plugin.yml') { + filesMatching('paper-plugin.yml') { expand props } } diff --git a/gradle.properties b/gradle.properties index e69de29..0979b4b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -0,0 +1 @@ +pluginVersion = 3.1.0 \ No newline at end of file diff --git a/src/main/java/de/shiewk/blockhistory/v3/BlockHistoryPlugin.java b/src/main/java/de/shiewk/blockhistory/v3/BlockHistoryPlugin.java index 46a2f0e..2e7bde2 100644 --- a/src/main/java/de/shiewk/blockhistory/v3/BlockHistoryPlugin.java +++ b/src/main/java/de/shiewk/blockhistory/v3/BlockHistoryPlugin.java @@ -2,6 +2,7 @@ package de.shiewk.blockhistory.v3; import de.shiewk.blockhistory.v3.command.BlockHistoryCommand; import de.shiewk.blockhistory.v3.listener.BlockListener; +import de.shiewk.blockhistory.v3.util.SchedulerUtil; import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; @@ -21,6 +22,19 @@ import static net.kyori.adventure.text.Component.text; public final class BlockHistoryPlugin extends JavaPlugin { + public static final boolean isFolia; + + static { + boolean folia; + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + folia = true; + } catch (ClassNotFoundException e) { + folia = false; + } + isFolia = folia; + } + private static ComponentLogger LOGGER = null; private static BlockHistoryPlugin INSTANCE = null; @@ -41,6 +55,7 @@ public final class BlockHistoryPlugin extends JavaPlugin { @Override public void onEnable() { + LOGGER.info("Folia: {}", isFolia ? "yes" : "no"); statManager = new StatManager(); Path saveDirectory = Path.of(getDataFolder().getPath(), "history"); try { @@ -52,7 +67,7 @@ public final class BlockHistoryPlugin extends JavaPlugin { getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, this::registerCommands); - Bukkit.getScheduler().scheduleSyncRepeatingTask(this, BlockListener::clearCache, 6000, 6000); + SchedulerUtil.scheduleGlobalRepeating(this, BlockListener::clearCache, 6000, 6000); listen(new BlockListener()); } diff --git a/src/main/java/de/shiewk/blockhistory/v3/HistoryManager.java b/src/main/java/de/shiewk/blockhistory/v3/HistoryManager.java index 233f001..2d17d01 100644 --- a/src/main/java/de/shiewk/blockhistory/v3/HistoryManager.java +++ b/src/main/java/de/shiewk/blockhistory/v3/HistoryManager.java @@ -89,9 +89,9 @@ public final class HistoryManager { logger.info("Shutdown finished ({}ms)", (System.nanoTime() - n) / 1000000); } - public CompletableFuture addHistoryElement(BlockHistoryElement element){ + public void addHistoryElement(BlockHistoryElement element){ Objects.requireNonNull(element); - return CompletableFuture.runAsync(() -> { + writeExecutor.execute(() -> { try { byte[] saveData = element.saveData(); writeToDisk( @@ -112,7 +112,7 @@ public final class HistoryManager { BlockHistoryPlugin.logger().warn(s); } } - }, writeExecutor); + }); } private void writeToDisk(Path path, byte[] saveData) throws LowDiskSpaceException, IOException { @@ -148,7 +148,7 @@ public final class HistoryManager { while (true) { try { int b = dataIn.readUnsignedByte(); - BlockHistoryElement element = BlockHistoryElement.read(b, dataIn, world, location.getChunk().getX(), location.getChunk().getZ()); + BlockHistoryElement element = BlockHistoryElement.read(b, dataIn, world, getChunkX(location), getChunkZ(location)); if (element.x() == x && element.y() == y && element.z() == z){ callback.onElementFound(element); } @@ -161,6 +161,28 @@ public final class HistoryManager { } } + public static int getChunkZ(Location location) { + int pos; + if (location.getZ() < 0){ + pos = ((location.getBlockZ() + 1) / 16) - 1; + } else { + pos = location.getBlockZ() / 16; + } + + return pos; + } + + public static int getChunkX(Location location) { + int pos; + if (location.getX() < 0){ + pos = ((location.getBlockX() + 1) / 16) - 1; + } else { + pos = location.getBlockX() / 16; + } + + return pos; + } + public CompletableFuture approximateDiskSpaceBytes() { return CompletableFuture.supplyAsync(() -> { try { diff --git a/src/main/java/de/shiewk/blockhistory/v3/listener/BlockListener.java b/src/main/java/de/shiewk/blockhistory/v3/listener/BlockListener.java index 385f3c3..d7d6ea5 100644 --- a/src/main/java/de/shiewk/blockhistory/v3/listener/BlockListener.java +++ b/src/main/java/de/shiewk/blockhistory/v3/listener/BlockListener.java @@ -3,10 +3,10 @@ package de.shiewk.blockhistory.v3.listener; import de.shiewk.blockhistory.v3.BlockHistoryPlugin; import de.shiewk.blockhistory.v3.history.BlockHistoryElement; import de.shiewk.blockhistory.v3.history.BlockHistoryType; +import de.shiewk.blockhistory.v3.util.SchedulerUtil; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -25,13 +25,15 @@ import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.event.player.PlayerInteractAtEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.RejectedExecutionException; public final class BlockListener implements Listener { - private static final Object2ObjectOpenHashMap igniters = new Object2ObjectOpenHashMap<>(); - private static final Object2ObjectOpenHashMap blocks = new Object2ObjectOpenHashMap<>(); + private static final Map igniters = BlockHistoryPlugin.isFolia ? new ConcurrentHashMap<>() : new Object2ObjectOpenHashMap<>(); + private static final Map blocks = BlockHistoryPlugin.isFolia ? new ConcurrentHashMap<>() : new Object2ObjectOpenHashMap<>(); public static void clearCache() { igniters.clear(); @@ -52,7 +54,7 @@ public final class BlockListener implements Listener { @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) public void onBucketEmptied(PlayerBucketEmptyEvent event){ - Bukkit.getScheduler().scheduleSyncDelayedTask(BlockHistoryPlugin.instance(), () -> { + SchedulerUtil.scheduleGlobal(BlockHistoryPlugin.instance(), () -> { final Block block = event.getBlock(); createAndAddEntry(BlockHistoryType.EMPTY_BUCKET, event.getPlayer(), block); }); diff --git a/src/main/java/de/shiewk/blockhistory/v3/util/BlockHistoryFileNames.java b/src/main/java/de/shiewk/blockhistory/v3/util/BlockHistoryFileNames.java index 57ae930..14193ef 100644 --- a/src/main/java/de/shiewk/blockhistory/v3/util/BlockHistoryFileNames.java +++ b/src/main/java/de/shiewk/blockhistory/v3/util/BlockHistoryFileNames.java @@ -1,6 +1,6 @@ package de.shiewk.blockhistory.v3.util; -import org.bukkit.Chunk; +import de.shiewk.blockhistory.v3.HistoryManager; import org.bukkit.Location; import org.bukkit.World; @@ -50,17 +50,7 @@ public final class BlockHistoryFileNames { public static Path encode(Path parentDirectory, Location location){ // encoded string is 13 characters long World world = location.getWorld(); - Chunk chunk = location.getChunk(); - int chunkX = chunk.getX(); - int chunkZ = chunk.getZ(); - // 20 bytes - long packed = 0; - - packed |= chunkX & 0b1111111111111111111L; - if (chunkX < 0) packed |= 0b10000000000000000000; - - packed |= (chunkZ & 0b1111111111111111111L) << 20; - if (chunkZ < 0) packed |= 0b1000000000000000000000000000000000000000L; + long packed = getPackedPos(location); String encodedChunkFileName = new String(new char[]{ base32encode((short) (packed >> 35 & 0b11111)), @@ -78,4 +68,19 @@ public final class BlockHistoryFileNames { encodedChunkFileName ); } + + private static long getPackedPos(Location location) { + int chunkX = HistoryManager.getChunkX(location); + int chunkZ = HistoryManager.getChunkZ(location); + + // 20 bits + long packed = 0; + + packed |= chunkX & 0b1111111111111111111L; + if (chunkX < 0) packed |= 0b10000000000000000000; + + packed |= (chunkZ & 0b1111111111111111111L) << 20; + if (chunkZ < 0) packed |= 0b1000000000000000000000000000000000000000L; + return packed; + } } diff --git a/src/main/java/de/shiewk/blockhistory/v3/util/SchedulerUtil.java b/src/main/java/de/shiewk/blockhistory/v3/util/SchedulerUtil.java new file mode 100644 index 0000000..faaa541 --- /dev/null +++ b/src/main/java/de/shiewk/blockhistory/v3/util/SchedulerUtil.java @@ -0,0 +1,25 @@ +package de.shiewk.blockhistory.v3.util; + +import de.shiewk.blockhistory.v3.BlockHistoryPlugin; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; + +public final class SchedulerUtil { + private SchedulerUtil(){} + + public static void scheduleGlobal(Plugin plugin, Runnable task){ + if (BlockHistoryPlugin.isFolia){ + Bukkit.getGlobalRegionScheduler().run(plugin, t -> task.run()); + } else { + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, task); + } + } + + public static void scheduleGlobalRepeating(Plugin plugin, Runnable task, int delay, int interval) { + if (BlockHistoryPlugin.isFolia){ + Bukkit.getGlobalRegionScheduler().runAtFixedRate(plugin, t -> task.run(), delay, interval); + } else { + Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, task, delay, interval); + } + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/paper-plugin.yml similarity index 92% rename from src/main/resources/plugin.yml rename to src/main/resources/paper-plugin.yml index 2b64252..ea6da44 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/paper-plugin.yml @@ -6,6 +6,8 @@ prefix: BlockHistory load: STARTUP authors: [ Shiewk ] description: BlockHistory is a Paper plugin that helps you to find griefers more easily. +folia-supported: true +website: https://github.com/Shiewk/BlockHistory3 permissions: blockhistory.command.root: default: op