diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 7829495..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Build JAR - -on: - push: - branches: [ master ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'adopt' - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Get project version - run: echo "version=$(grep '^version' build.gradle | cut -d' ' -f3 | tr -d '\"')" >> $GITHUB_ENV - - name: Build with Gradle - run: ./gradlew build -x test - - name: Publish artifact - uses: actions/upload-artifact@v4 - with: - name: FoliaFlow-${{ env.version }}-${{ github.sha }} - path: build/libs/FoliaFlow-${{ env.version }}.jar diff --git a/.gitignore b/.gitignore index cdb5be5..3c37caf 100644 --- a/.gitignore +++ b/.gitignore @@ -116,4 +116,3 @@ run/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar -niri-rpc/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 8b13789..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/README.md b/README.md index e1bf6f5..7770d78 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,15 @@ -# THIS IS NOT MY PLUGIN, I JUST EDITED ONE SINGLE LINE IN PLUGIN.YML, THE ORIGINAL IS AT: https://github.com/MidnightTale/FoliaFlow - -FoliaFlow is a Minecraft plugin that allows players to using gravity block duplication glitch again in Paper and Folia - -## How is work? -Whenever a falling sand entity comes close to or hits the end portal, a new falling sand entity is summoned with a velocity that shoots it straight into the portal. However, we encountered a problem when the entity got reset by the safe teleport Paper patch - it lose its velocity. To fix this, we added the velocity back when the entity was in the end. - -## ⚠️If you using folia -And type of concreate factory collector that use piston full block to stop falling blocks. You should change to slab to prevent block early break follow picture below -### Top View -![topviewff](https://user-images.githubusercontent.com/125941391/234716000-8dfe3f57-b9a4-4340-8d1a-4e63fe2cdb91.png) -### Side View -![sideviewff](https://user-images.githubusercontent.com/125941391/234716115-f793602c-17f9-4689-9740-7ff25013eed4.png) +# FoliaFlow +![sss1](https://user-images.githubusercontent.com/125941391/231678608-9762d384-dc3a-440c-a4eb-3340cb39a3e3.png) +FoliaFlow is a Minecraft plugin that allows players to using gravity block duplication glitch ## Installation To install FoliaFlow, follow these steps: -1. Download the plugin JAR file from the [Modrinth](https://modrinth.com/plugin/foliaflow). +1. Download the plugin JAR file from the [releases page](https://github.com/Hynse/FoliaFlow/releases). 2. Copy the JAR file to the `plugins` folder of your Minecraft server. -3. Restart your server to load the plugin. - -## Config flies (config.yml) -```yml -# Don't touch this file unless you know what you're doing -# Default values seems vanilla. -# If you find values that seems more vanilla please create a PR -# https://github.com/Hynse/FoliaFlow - -# Default value for horizontal_coefficient -# - Folia (1.499) -# - Paper (2) -horizontal_coefficient: 1.499 -# ----------------------------------------- - -vertical_coefficient: -1.7 -spawn_height: 0.08 - -# Default value for teleport_offset -# - Folia (0.5) -# - Paper (2.4) -teleport_offset: 0.5 -# ----------------------------------------- -``` - -## Permissions -`foliaflow.reload` for using command `/flowreload` to reload config flies +3. Restart your server to enable the plugin. ## Contributing diff --git a/build.gradle b/build.gradle index 722f80f..bc97e26 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,10 @@ plugins { id 'java' } +def loader = 'folia' +def server = '1.19.4' group = 'xyz.hynse' -version = "3.0" +version = "1.3-${server}-${loader}" repositories { mavenCentral() @@ -11,10 +13,14 @@ 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 "dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT" + compileOnly "dev.folia:folia-api:1.19.4-R0.1-SNAPSHOT" } def targetJavaVersion = 17 diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 diff --git a/src/main/java/xyz/hynse/foliaflow/FoliaFlow.java b/src/main/java/xyz/hynse/foliaflow/FoliaFlow.java index b1cbc6b..57f23ce 100644 --- a/src/main/java/xyz/hynse/foliaflow/FoliaFlow.java +++ b/src/main/java/xyz/hynse/foliaflow/FoliaFlow.java @@ -1,73 +1,171 @@ package xyz.hynse.foliaflow; -import org.bukkit.configuration.file.YamlConfiguration; +import io.papermc.paper.threadedregions.scheduler.AsyncScheduler; +import io.papermc.paper.threadedregions.scheduler.RegionScheduler; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.data.type.Slab; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.util.Vector; -import xyz.hynse.foliaflow.command.ReloadCommand; -import xyz.hynse.foliaflow.util.CheckSafeTeleportation; -import xyz.hynse.foliaflow.watcher.PortalWatcher; +import java.util.*; +import java.util.concurrent.TimeUnit; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import static org.bukkit.Bukkit.getScheduler; -public class FoliaFlow extends JavaPlugin { - private boolean isFirstEnable = true; - //public boolean isUnSafeTeleport = false; - public static FoliaFlow instance; - public static double horizontalCoefficient; - public static double verticalCoefficient; - public static double spawnHeight; - public static double TeleportOffset; - //public static CheckSafeTeleportation checkSafeTeleportation; +public class FoliaFlow extends JavaPlugin implements Listener { + private final double vh = 0.2; + private final double vt = 0.8; + private final Vector velocity1 = new Vector(0, vh, vt); + private final Vector velocity2 = new Vector(vt, vh, 0); + private final Vector velocity3 = new Vector(0, vh, -vt); + private final Vector velocity4 = new Vector(-vt, vh, 0); + + private final Vector[] velocities = {velocity1, velocity2, velocity3, velocity4}; + private int counter = 0; + private final Set movingBlocks = new HashSet<>(); + private final Map velocitiesMap = new HashMap<>(); // Create a map to store velocities + private ScheduledTask task; + + private ScheduledTask blockktask; @Override public void onEnable() { - instance = this; - register(); - if (isFirstEnable) { - isFirstEnable = false; - copyDefaultConfig(); - setInitialConfigValues(); - } - reload(); - } + super.onEnable(); - private void copyDefaultConfig() { - File configFile = new File(getDataFolder(), "config.yml"); - if (!configFile.exists()) { - saveResource("config.yml", false); - } - } - - private void setInitialConfigValues() { - File configFile = new File(getDataFolder(), "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); - InputStream defaultConfigStream = getResource("config.yml"); - YamlConfiguration defaultConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(defaultConfigStream)); - config.options().copyDefaults(true); - config.setDefaults(defaultConfig); + // Get the region scheduler for the server try { - config.save(configFile); - } catch (IOException e) { - e.printStackTrace(); + RegionScheduler schedulerblock = getServer().getRegionScheduler(); + + // Schedule a repeating task to run every tick using runAtFixedRate() method + blockktask = schedulerblock.runAtFixedRate(this, Objects.requireNonNull(Bukkit.getWorld("world_the_end")), 1, 1, (schedulerTask) -> { + Block block = Objects.requireNonNull(Bukkit.getWorld("world_the_end")).getBlockAt(100, 48, 0); + if (block.getType() == Material.OBSIDIAN) { + block.setType(Material.COBBLED_DEEPSLATE_SLAB); + Slab slab = (Slab) block.getBlockData(); + slab.setType(Slab.Type.BOTTOM); + block.setBlockData(slab); + } + }, 1L, 1L); + } catch (NullPointerException block) { + getServer().getLogger().info("Region Scheduler erorr (likly chunky it not load)"); + } + AsyncScheduler scheduler = getServer().getAsyncScheduler(); + task = scheduler.runAtFixedRate(this, (scheduledTask) -> getScheduler().runTask(this, () -> { + for (World world : Bukkit.getWorlds()) { + for (Entity entity : world.getEntities()) { + if (entity.getType() == EntityType.FALLING_BLOCK && entity.getWorld().getEnvironment() == World.Environment.THE_END) { + Location centerLoc = new Location(entity.getWorld(), 100, 48.5, 0); + Location loc = entity.getLocation(); + if (loc.distance(centerLoc) <= 1) { + // Set the initial velocity of the falling block only if it doesn't have a velocity stored + if (!velocitiesMap.containsKey(entity)) { + try { + int index = counter % 4; + counter++; + Vector velocity = velocities[index]; + entity.setVelocity(velocity); + velocitiesMap.put(entity, velocity); // Store the velocity in the map + movingBlocks.add(entity.getLocation()); // Add the location to the set + } catch (NullPointerException e) { + // Handle the exception here, for example: + e.printStackTrace(); + getServer().getLogger().info("An error occurred: " + e.getMessage()); + } + } + } + } + } + } + }), 0L, 1L, TimeUnit.MILLISECONDS); + getServer().getPluginManager().registerEvents(this, this); + getServer().getConsoleSender().sendMessage(""); + getServer().getConsoleSender().sendMessage(ChatColor.GREEN + " ______________ "); + getServer().getConsoleSender().sendMessage(ChatColor.GREEN + " / ____/ ____/ /___ _ __"); + getServer().getConsoleSender().sendMessage(ChatColor.GREEN + " / /_ / /_ / / __ \\ | /| / /"); + getServer().getConsoleSender().sendMessage(ChatColor.GREEN + " / __/ / __/ / / /_/ / |/ |/ / "); + getServer().getConsoleSender().sendMessage(ChatColor.GREEN + "/_/ /_/ /_/\\____/|__/|__/ "); + getServer().getConsoleSender().sendMessage(""); + getServer().getConsoleSender().sendMessage(ChatColor.YELLOW + "Plugin started successfully!"); + getServer().getConsoleSender().sendMessage(""); + } + + @Override + public void onDisable() { + task.cancel(); + blockktask.cancel(); + super.onDisable(); + debug(); + } + + @EventHandler + public void onFallingBlockToBlock(EntityChangeBlockEvent e){ + if(e.getEntityType() == EntityType.FALLING_BLOCK){ + Entity entity = e.getEntity(); + Location loc = entity.getLocation(); + Vector vel = entity.getVelocity(); + Block movingTo = getBlockMovingTo(loc, vel); + try { + + if(movingTo != null && movingTo.getType() == Material.END_PORTAL){ + Location spawnLoc = movingTo.getLocation(); + spawnLoc.setX(spawnLoc.getX()+0.5); + spawnLoc.setY(spawnLoc.getY()-0.25); + spawnLoc.setZ(spawnLoc.getZ()+0.5); + + FallingBlock dummy = loc.getWorld().spawnFallingBlock(spawnLoc, ((FallingBlock) entity).getBlockData()); + dummy.setDropItem(true); + dummy.setHurtEntities(true); + dummy.setGravity(true); + Vector dummyVel = vel.clone(); + dummyVel.setY(-dummyVel.getY()); + dummyVel.multiply(new Vector(2, 1, 2)); + + dummyVel.add(new Vector(0, 1, 0)); + + dummy.setVelocity(dummyVel); + } + } catch (NullPointerException dummy) { + getServer().getLogger().info("onFallingBlockToBlock erorr (likly chunky it not load)"); + } } } - public void reload() { - saveDefaultConfig(); - reloadConfig(); - horizontalCoefficient = getConfig().getDouble("horizontal_coefficient"); - verticalCoefficient = getConfig().getDouble("vertical_coefficient"); - spawnHeight = getConfig().getDouble("spawn_height"); - TeleportOffset = getConfig().getDouble("teleport_offset"); + Block getBlockMovingTo(Location loc, Vector vel) { + double absMax = 0, max = 0; + char dir = ' '; + Block relative = null; + if (Math.abs(vel.getX()) > absMax) { + max = vel.getX(); + absMax = Math.abs(vel.getX()); + dir = 'x'; + } + if (Math.abs(vel.getY()) > absMax) { + max = vel.getY(); + absMax = Math.abs(vel.getY()); + dir = 'y'; + } + if (Math.abs(vel.getZ()) > absMax) { + max = vel.getZ(); + dir = 'z'; + } + switch (dir) { + case 'x' -> relative = loc.getBlock().getRelative((int) Math.signum(max), 0, 0); + case 'y' -> relative = loc.getBlock().getRelative(0, (int) Math.signum(max), 0); + case 'z' -> relative = loc.getBlock().getRelative(0, 0, (int) Math.signum(max)); + } + //debug("Moving falling block from location " + loc.toString() + " to location " + dir); + return relative; } - private void register() { - getCommand("flowreload").setExecutor(new ReloadCommand()); -// checkSafeTeleportation = new CheckSafeTeleportation(); -// checkSafeTeleportation.updateSafeTeleportation(); - getServer().getPluginManager().registerEvents(new PortalWatcher(), this); + private void debug() { + getServer().getConsoleSender().sendMessage(ChatColor.AQUA + "[FoliaFlow] " + "Plugin stopped successfully!"); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/hynse/foliaflow/command/ReloadCommand.java b/src/main/java/xyz/hynse/foliaflow/command/ReloadCommand.java deleted file mode 100644 index a81bd5d..0000000 --- a/src/main/java/xyz/hynse/foliaflow/command/ReloadCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package xyz.hynse.foliaflow.command; - -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; - -import xyz.hynse.foliaflow.FoliaFlow; - -public class ReloadCommand implements CommandExecutor { - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!sender.hasPermission("foliaflow.reload")) return true; - try { - FoliaFlow.instance.reload(); - sender.sendMessage(ChatColor.YELLOW + "FoliaFlow reloaded."); - } catch (Exception e) { - sender.sendMessage(ChatColor.RED + "Something went wrong reloading FoliaFlow, see the console for more."); - e.printStackTrace(); - } - return true; - } -} diff --git a/src/main/java/xyz/hynse/foliaflow/util/CheckSafeTeleportation.java b/src/main/java/xyz/hynse/foliaflow/util/CheckSafeTeleportation.java deleted file mode 100644 index 58940d3..0000000 --- a/src/main/java/xyz/hynse/foliaflow/util/CheckSafeTeleportation.java +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.hynse.foliaflow.util; - -import org.yaml.snakeyaml.Yaml; -import xyz.hynse.foliaflow.FoliaFlow; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Map; - -import static org.bukkit.Bukkit.getServer; - -public class CheckSafeTeleportation { - - public boolean checkUnsafeEndPortalTeleportation() { - File configFile = new File(getServer().getWorldContainer(), "config/paper-global.yml"); - if (!configFile.exists()) { - FoliaFlow.instance.getLogger().warning("paper-global.yml not found!"); - return false; - } - - try (FileInputStream fis = new FileInputStream(configFile)) { - Yaml yaml = new Yaml(); - Map config = yaml.load(fis); - - Map unsupportedSettings = (Map) config.get("unsupported-settings"); - if (unsupportedSettings != null) { - Boolean setting = (Boolean) unsupportedSettings.get("allow-unsafe-end-portal-teleportation"); - return setting != null && setting; - } - } catch (IOException e) { - FoliaFlow.instance.getLogger().severe("Failed to read paper-global.yml: " + e.getMessage()); - } - - return false; - } - - -// public void updateSafeTeleportation() { -// boolean safeTeleportation = checkUnsafeEndPortalTeleportation(); -// if (safeTeleportation) { -// FoliaFlow.instance.isUnSafeTeleport = true; -// FoliaFlow.instance.getLogger().info("Unsafe End Portal Teleportation is true."); -// } else { -// FoliaFlow.instance.isUnSafeTeleport = false; -// FoliaFlow.instance.getLogger().info("Unsafe End Portal Teleportation is false."); -// } -// } -} diff --git a/src/main/java/xyz/hynse/foliaflow/util/SchedulerUtil.java b/src/main/java/xyz/hynse/foliaflow/util/SchedulerUtil.java deleted file mode 100644 index 5883390..0000000 --- a/src/main/java/xyz/hynse/foliaflow/util/SchedulerUtil.java +++ /dev/null @@ -1,32 +0,0 @@ -package xyz.hynse.foliaflow.util; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Entity; -import org.bukkit.plugin.Plugin; - -public class SchedulerUtil { - - private static Boolean IS_FOLIA = null; - - private static boolean tryFolia() { - try { - Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - - public static Boolean isFolia() { - if (IS_FOLIA == null) IS_FOLIA = tryFolia(); - return IS_FOLIA; - } - - public static void runLaterEntity(Entity entity, Plugin plugin, Runnable runnable, int ticks) { - if (isFolia()) { - entity.getScheduler().runDelayed(plugin, (task) -> runnable.run(), null, ticks); - } else { - Bukkit.getScheduler().runTaskLater(plugin, runnable, ticks); - } - } -} diff --git a/src/main/java/xyz/hynse/foliaflow/util/VelocityUtil.java b/src/main/java/xyz/hynse/foliaflow/util/VelocityUtil.java deleted file mode 100644 index 953fbee..0000000 --- a/src/main/java/xyz/hynse/foliaflow/util/VelocityUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package xyz.hynse.foliaflow.util; - -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.util.Vector; - -public class VelocityUtil { - public static Block getBlockMovingTo(Location loc, Vector vel) { - double absX = Math.abs(vel.getX()); - double absY = Math.abs(vel.getY()); - double absZ = Math.abs(vel.getZ()); - if (absX > absY && absX > absZ) { - return loc.getBlock().getRelative((int) Math.signum(vel.getX()), 0, 0); - } else if (absY > absZ) { - return loc.getBlock().getRelative(0, (int) Math.signum(vel.getY()), 0); - } - return loc.getBlock().getRelative(0, 0, (int) Math.signum(vel.getZ())); - } -} diff --git a/src/main/java/xyz/hynse/foliaflow/watcher/PortalWatcher.java b/src/main/java/xyz/hynse/foliaflow/watcher/PortalWatcher.java deleted file mode 100644 index 581b07b..0000000 --- a/src/main/java/xyz/hynse/foliaflow/watcher/PortalWatcher.java +++ /dev/null @@ -1,73 +0,0 @@ -package xyz.hynse.foliaflow.watcher; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.FallingBlock; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityPortalEnterEvent; -import org.bukkit.util.Vector; - -import xyz.hynse.foliaflow.FoliaFlow; -import xyz.hynse.foliaflow.util.SchedulerUtil; - -import static xyz.hynse.foliaflow.util.VelocityUtil.getBlockMovingTo; - -public class PortalWatcher implements Listener { - - private static final String DUPE_TAG = "foliaflow_dupe"; - - @EventHandler - public void onFallingBlockToBlock(EntityChangeBlockEvent e){ - if(e.getEntityType() != EntityType.FALLING_BLOCK) return; - Entity entity = e.getEntity(); - if(entity.getScoreboardTags().contains(DUPE_TAG)) return; - Location loc = entity.getLocation(); - Vector vel = entity.getVelocity(); - Block movingTo = getBlockMovingTo(loc, vel); - - if(movingTo.getType() == Material.END_PORTAL){ - spawnDupe(entity, movingTo, false); - } - } - - @EventHandler - public void onPortalEnter(EntityPortalEnterEvent e){ - if(e.getEntityType() != EntityType.FALLING_BLOCK) return; - Entity entity = e.getEntity(); - if(entity.getScoreboardTags().contains(DUPE_TAG)) return; - Block portal = e.getLocation().getBlock(); - - if(portal.getType() == Material.END_PORTAL && portal.getRelative(0, -1, 0).getType().name().endsWith("_FENCE")){ - spawnDupe(entity, portal, true); - } - } - - private void spawnDupe(Entity entity, Block portal, boolean passThrough){ - Location spawnLoc = portal.getLocation(); - spawnLoc.add(0.5, FoliaFlow.spawnHeight, 0.5); - - FallingBlock dummy = entity.getWorld().spawnFallingBlock(spawnLoc, ((FallingBlock) entity).getBlockData()); - dummy.addScoreboardTag(DUPE_TAG); - Vector dummyVel = entity.getVelocity().clone(); - dummyVel.multiply(FoliaFlow.horizontalCoefficient); - if(passThrough){ - dummyVel.setY(entity.getVelocity().getY()); - } else { - dummyVel.setY(entity.getVelocity().getY() * FoliaFlow.verticalCoefficient); - } - dummy.setVelocity(dummyVel); - - SchedulerUtil.runLaterEntity(dummy, FoliaFlow.instance, () -> { - // Portal teleportation is a bit below vanilla, so we teleport it above - dummy.teleportAsync(dummy.getLocation().add(0, FoliaFlow.TeleportOffset, 0)); - dummy.setVelocity(dummyVel); - }, - 2 - ); - } -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml deleted file mode 100644 index 6c9c6cb..0000000 --- a/src/main/resources/config.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Don't touch this file unless you know what you're doing -# Default values seems vanilla. -# If you find values that seems more vanilla please create a PR -# https://github.com/Hynse/FoliaFlow - -# Default value for horizontal_coefficient -# - Folia (1.499) -# - Paper (2) -horizontal_coefficient: 1.499 -# ----------------------------------------- - -vertical_coefficient: -1.7 -spawn_height: 0.08 - -# Default value for teleport_offset -# - Folia (0.5) -# - Paper (2.4) -teleport_offset: 0.5 -# ----------------------------------------- diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index fb90a09..19f50a9 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,10 +1,5 @@ name: FoliaFlow version: '${version}' main: xyz.hynse.foliaflow.FoliaFlow -api-version: 26.1.2 -folia-supported: true -commands: - flowreload: - description: Reload FoliaFlow - usage: / - permission: foliaflow.reload +api-version: 1.19 +folia-supported: true \ No newline at end of file