Compare commits

...
Sign in to create a new pull request.

51 commits

Author SHA1 Message Date
99af88ee82 Update README.md
Some checks failed
Build JAR / build (push) Has been cancelled
2026-08-04 21:22:05 +02:00
b9c87885de updated to 26.1.2
Some checks are pending
Build JAR / build (push) Waiting to run
please work
2026-08-04 21:20:10 +02:00
MidnightTale
8acab44797 fix: detect vertical falling blocks entering end portals 2026-08-03 16:46:04 +07:00
MidnightTale
a5172407b5 Merge MoRanYue/FoliaFlow 2026-08-03 11:24:15 +07:00
MidnightTale
6b4d10faf3 bump to 3.0 2026-08-03 11:18:36 +07:00
MoRanYue
4f5818c272 feat: update to 26.1.2 and use modern API 2026-07-04 19:24:30 +08:00
MidnightTale
a2df8bbe7d
Update build.yml 2024-06-03 11:49:36 +07:00
MidnightTale
3d428ffcfa
Update build.yml 2024-06-03 11:48:26 +07:00
MidnightTale
d83991f028
Update build.yml 2024-05-31 10:18:24 +07:00
MidnightTale
1f26c62b31
Update README.md 2024-05-28 04:59:00 +07:00
MidnightTale
672f3d2b94
change to java 17 2024-05-28 04:37:37 +07:00
MidnightTale
0a87ba80c6
update 2.4 2024-05-28 04:34:43 +07:00
MidnightTale
d84aef8126 Fix block disappear 2023-08-29 19:09:05 +07:00
MidnightTale
99b4c3d08c for got to update config 2023-08-29 17:46:32 +07:00
MidnightTale
79789db92c version bump 2023-08-29 17:41:57 +07:00
MidnightTale
f301f159e6 is happen on paper 1.20 build 169 teleportation is a bit below vanilla 2023-08-29 17:33:07 +07:00
Mid
d974903c34
Merge pull request #21 from xiaoyueyoqwq/patch-1
Update config.yml
2023-06-09 22:33:06 +07:00
xiaoyueyoqwq
211fd88d80
Update config.yml
After testing, the -1 value solves many problems in the sand brushing process, such as momentum instability, obsidian platform problems, sand block rotation, jumping flight, etc
2023-06-04 02:00:10 +08:00
Mid
79b594aec0
Merge pull request #19 from KaiijuMC/master
Add +x permission to gradlew
2023-05-02 15:43:18 +07:00
kugge
b4e08f7778 Add +x permission to gradlew 2023-05-02 10:43:25 +02:00
Mid
70c2fb1500
Update build.yml 2023-04-30 18:09:22 +07:00
Mid
962d08c8a6
Update build.yml 2023-04-30 18:07:26 +07:00
Mid
9ef9f85bec
Create build.yml 2023-04-30 18:07:11 +07:00
Mid
86bf7be44f
Update README.md 2023-04-27 05:26:13 +07:00
Mid
32393dbd3e
Update README.md 2023-04-27 04:46:07 +07:00
Mid
0c1ca62cca
Update README.md 2023-04-27 04:45:17 +07:00
MidnightTale
08df685a0e set closet vanilla vaule horizontalCoefficient config base on folia or paper 2023-04-27 04:28:01 +07:00
Mid
1a3d65b782
Merge pull request #18 from KaiijuMC/master
Configurable FoliaOffset
2023-04-27 03:44:27 +07:00
Sofiane H. Djerbi
c9a8159ea8 Configurable FoliaOffset 2023-04-26 23:43:26 +03:00
Mid
07806d8e6f
Merge pull request #17 from KaiijuMC/master
Add configurable spawn height
2023-04-27 02:03:19 +07:00
Sofiane H. Djerbi
ada248f722 Add configurable spawn height 2023-04-26 21:59:44 +03:00
Mid
5ca0f1ec39
Merge pull request #16 from KaiijuMC/master
Add configurable coefficients and reload command
2023-04-27 01:44:44 +07:00
Sofiane H. Djerbi
d988f5419a
Merge branch 'master' into master 2023-04-26 21:42:22 +03:00
Sofiane H. Djerbi
452e8ceb23 Configurable coefficients and reload command 2023-04-26 21:33:16 +03:00
Sofiane H. Djerbi
3bad24ab89 Delete Paper plugin (this is not a paper plugin) 2023-04-26 21:30:54 +03:00
Mid
964c9c192e
Merge pull request #15 from KaiijuMC/master
Vanilla parity fix on Folia
2023-04-26 18:54:27 +07:00
Sofiane H. Djerbi
cfa36f99e5 Vanilla parity fix on Folia 2023-04-26 14:51:43 +03:00
Sofiane H. Djerbi
a370af7eb5 Vanilla parity fix on Folia 2023-04-26 14:43:39 +03:00
MidnightTale
b6212bad98 version 2023-04-26 18:31:31 +07:00
Mid
dc83bb8a2d
Merge pull request #14 from KaiijuMC/master
Update README.md
2023-04-26 18:17:06 +07:00
Sofiane H. Djerbi
276c1b2191
Update README.md 2023-04-26 13:10:51 +03:00
Mid
a21172ae28
Merge pull request #13 from KaiijuMC/master
Paper compatibility
2023-04-26 16:29:18 +07:00
Sofiane H. Djerbi
c5f152fdbf Paper compatibility 2023-04-26 12:24:49 +03:00
Mid
2a84850dd6
Update README.md 2023-04-26 12:35:31 +07:00
MidnightTale
94d1269944 version 2023-04-26 12:22:35 +07:00
MidnightTale
fa83f08e57 fix version not show in console 2023-04-26 12:20:07 +07:00
Mid
1c7aa44558
Merge pull request #12 from KaiijuMC/master
Huge refactoring + optimisations
2023-04-26 12:16:31 +07:00
Sofiane H. Djerbi
3846c7945f
Merge branch 'master' into master 2023-04-26 05:16:46 +03:00
Sofiane H. Djerbi
758b5dc8fc Refactoring / Optimize project 2023-04-26 05:15:30 +03:00
MidnightTale
2369212335 Change spawn overworld falling block to above portal 2023-04-26 03:14:24 +07:00
MidnightTale
792c0c5f1d optimize code 2023-04-25 23:18:42 +07:00
14 changed files with 345 additions and 182 deletions

27
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,27 @@
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

1
.gitignore vendored
View file

@ -116,3 +116,4 @@ run/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
niri-rpc/

View file

@ -1,19 +1,51 @@
# FoliaFlow
![sss1](https://user-images.githubusercontent.com/125941391/231678608-9762d384-dc3a-440c-a4eb-3340cb39a3e3.png)
# 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 folia (paper soon)
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 lost its velocity. To fix this, we added the velocity back when the entity was in the end. Another issue we faced was that the entity would instantly turn into a block upon teleportation because it have block below. To solve this, we made the center block of the spawn platform a slab, ensuring that the entity stays in its falling state.
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)
## Installation
To install FoliaFlow, follow these steps:
1. Download the plugin JAR file from the [releases page](https://github.com/Hynse/FoliaFlow/releases).
1. Download the plugin JAR file from the [Modrinth](https://modrinth.com/plugin/foliaflow).
2. Copy the JAR file to the `plugins` folder of your Minecraft server.
3. Restart your server to enable the plugin.
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
## Contributing

View file

@ -3,7 +3,7 @@ plugins {
}
group = 'xyz.hynse'
version = "1.7"
version = "3.0"
repositories {
mavenCentral()
@ -14,7 +14,7 @@ repositories {
}
dependencies {
compileOnly "dev.folia:folia-api:1.19.4-R0.1-SNAPSHOT"
compileOnly "dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT"
}
def targetJavaVersion = 17

0
gradlew vendored Normal file → Executable file
View file

View file

@ -1,185 +1,73 @@
package xyz.hynse.foliaflow;
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
import io.papermc.paper.threadedregions.scheduler.RegionScheduler;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Slab;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.BlockDisplay;
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.io.File;
import java.io.IOException;
import java.util.*;
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);
import java.io.InputStream;
import java.io.InputStreamReader;
private final Vector[] velocities = {velocity1, velocity2, velocity3, velocity4};
private int counter = 0;
private final Set<Location> movingBlocks = new HashSet<>();
private final Map<Entity, Vector> velocitiesMap = new HashMap<>();
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;
@Override
public void onEnable() {
super.onEnable();
RegionScheduler schedulerblock = getServer().getRegionScheduler();
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);
instance = this;
register();
if (isFirstEnable) {
isFirstEnable = false;
copyDefaultConfig();
setInitialConfigValues();
}
reload();
}
}, 1L, 1L);
GlobalRegionScheduler schedulervelocity = this.getServer().getGlobalRegionScheduler();
schedulervelocity.runAtFixedRate(this, (scheduledTask) -> {
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) {
if (!velocitiesMap.containsKey(entity)) {
int index = counter % 4;
counter++;
Vector velocity = velocities[index];
entity.setVelocity(velocity);
velocitiesMap.put(entity, velocity);
movingBlocks.add(entity.getLocation());
private void copyDefaultConfig() {
File configFile = new File(getDataFolder(), "config.yml");
if (!configFile.exists()) {
saveResource("config.yml", false);
}
}
}
}
}
}, 20L, 1L);
File dataFile = new File(getDataFolder(), "data.yml");
YamlConfiguration config = YamlConfiguration.loadConfiguration(dataFile);
// Get the existing flag value, or default to false if it doesn't exist
boolean entitySpawned = config.getBoolean("entity_spawned", false);
// If the entity has not already been spawned, spawn it and set the flag to true
if (!entitySpawned) {
RegionScheduler schedulerdisplay = getServer().getRegionScheduler();
String tag = "FoliaFlow_Display";
schedulerdisplay.run(this, Objects.requireNonNull(Bukkit.getWorld("world_the_end")), 1, 1, (schedulerTask) -> {
World endWorld = getServer().getWorld("world_the_end");
assert endWorld != null;
Chunk chunk = endWorld.getChunkAt(0, 0);
if (!chunk.isLoaded()) {
chunk.load();
getLogger().info("Loaded Chunk");
}
boolean displayExists = endWorld.getEntitiesByClass(BlockDisplay.class).stream()
.anyMatch(entity -> entity.getScoreboardTags().contains(tag));
getLogger().info("Exist BlockDisplay" + "(" + tag + ")");
if (!displayExists) {
BlockDisplay display = (BlockDisplay) endWorld.spawnEntity(new Location(endWorld, 100.0005, 48, -0.0005), EntityType.BLOCK_DISPLAY);
display.setBlock(Bukkit.createBlockData(Material.OBSIDIAN));
display.addScoreboardTag(tag);
getLogger().info("Setup BlockDisplay" + "(" + tag + ") " + display);
// Set the flag to indicate that the entity has been spawned
config.set("entity_spawned", true);
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);
try {
config.save(dataFile);
config.save(configFile);
} catch (IOException e) {
getLogger().warning("Failed to save plugin data file");
}
}
});
}
getServer().getPluginManager().registerEvents(this, this);
}
@Override
public void onDisable() {
super.onDisable();
}
@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 error (likely chunky it not load)");
}
e.printStackTrace();
}
}
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';
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");
}
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));
}
return relative;
private void register() {
getCommand("flowreload").setExecutor(new ReloadCommand());
// checkSafeTeleportation = new CheckSafeTeleportation();
// checkSafeTeleportation.updateSafeTeleportation();
getServer().getPluginManager().registerEvents(new PortalWatcher(), this);
}
}

View file

@ -0,0 +1,23 @@
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;
}
}

View file

@ -0,0 +1,49 @@
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<String, Object> config = yaml.load(fis);
Map<String, Object> unsupportedSettings = (Map<String, Object>) 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.");
// }
// }
}

View file

@ -0,0 +1,32 @@
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);
}
}
}

View file

@ -0,0 +1,19 @@
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()));
}
}

View file

@ -0,0 +1,73 @@
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
);
}
}

View file

@ -0,0 +1,19 @@
# 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
# -----------------------------------------

View file

@ -1,5 +0,0 @@
name: FoliaFlow
version: '${version}'
main: xyz.hynse.foliaflow.FoliaFlow
api-version: 1.19
folia-supported: true

View file

@ -1,5 +1,10 @@
name: FoliaFlow
version: '${version}'
main: xyz.hynse.foliaflow.FoliaFlow
api-version: 1.19
api-version: 26.1.2
folia-supported: true
commands:
flowreload:
description: Reload FoliaFlow
usage: /<command>
permission: foliaflow.reload