diff --git a/luminol-api/paper-patches/features/0009-Add-missing-teleportation-apis-for-folia.patch b/luminol-api/paper-patches/features/0009-Add-missing-teleportation-apis-for-folia.patch new file mode 100644 index 0000000..1364b93 --- /dev/null +++ b/luminol-api/paper-patches/features/0009-Add-missing-teleportation-apis-for-folia.patch @@ -0,0 +1,348 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Fri, 31 Jan 2025 20:28:47 +0800 +Subject: [PATCH] Add missing teleportation apis for folia + + +diff --git a/src/main/java/me/earthme/luminol/api/entity/EntityTeleportAsyncEvent.java b/src/main/java/me/earthme/luminol/api/entity/EntityTeleportAsyncEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0c218c99073e4d20532f81c5ab467fbf3e7a57e8 +--- /dev/null ++++ b/src/main/java/me/earthme/luminol/api/entity/EntityTeleportAsyncEvent.java +@@ -0,0 +1,75 @@ ++package me.earthme.luminol.api.entity; ++ ++import org.apache.commons.lang3.Validate; ++import org.bukkit.Location; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A simple event fired when a teleportAsync was called ++ * @see org.bukkit.entity.Entity#teleportAsync(org.bukkit.Location, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause) ++ * @see org.bukkit.entity.Entity#teleportAsync(org.bukkit.Location) ++ * (Also fired when teleportAsync called from nms) ++ */ ++public class EntityTeleportAsyncEvent extends Event implements Cancellable { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ private boolean cancelled = false; ++ ++ private final Entity entity; ++ private final PlayerTeleportEvent.TeleportCause teleportCause; ++ private final Location destination; ++ ++ public EntityTeleportAsyncEvent(Entity entity, PlayerTeleportEvent.TeleportCause teleportCause, Location destination) { ++ Validate.notNull(entity, "entity cannot be a null value!"); ++ Validate.notNull(teleportCause, "teleportCause cannot be a null value!"); ++ Validate.notNull(destination, "destination cannot be a null value!"); ++ ++ this.entity = entity; ++ this.teleportCause = teleportCause; ++ this.destination = destination; ++ } ++ ++ /** ++ * Get the entity is about to be teleported ++ * @return that entity ++ */ ++ public @NotNull Entity getEntity() { ++ return this.entity; ++ } ++ ++ /** ++ * Get the cause of the teleport ++ * @return the cause ++ */ ++ public @NotNull PlayerTeleportEvent.TeleportCause getTeleportCause() { ++ return this.teleportCause; ++ } ++ ++ /** ++ * Get the destination of the teleport ++ * @return the destination ++ */ ++ public @NotNull Location getDestination() { ++ return this.destination; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLERS; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++} +diff --git a/src/main/java/me/earthme/luminol/api/entity/PostEntityPortalEvent.java b/src/main/java/me/earthme/luminol/api/entity/PostEntityPortalEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..50b601d124bbaf4eedb626d84ed6dae9ab6e9ef1 +--- /dev/null ++++ b/src/main/java/me/earthme/luminol/api/entity/PostEntityPortalEvent.java +@@ -0,0 +1,36 @@ ++package me.earthme.luminol.api.entity; ++ ++import org.apache.commons.lang3.Validate; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A simple event created for missing teleport events api of folia ++ * This event is fired when the entity portal process has been done ++ */ ++public class PostEntityPortalEvent extends Event { ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Entity teleportedEntity; ++ ++ public PostEntityPortalEvent(Entity teleportedEntity) { ++ Validate.notNull(teleportedEntity, "teleportedEntity cannot be null!"); ++ ++ this.teleportedEntity = teleportedEntity; ++ } ++ ++ /** ++ * Get the entity which was teleported ++ * @return the entity which was teleported ++ */ ++ public Entity getTeleportedEntity() { ++ return this.teleportedEntity; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/me/earthme/luminol/api/entity/PreEntityPortalEvent.java b/src/main/java/me/earthme/luminol/api/entity/PreEntityPortalEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e25146f3b5d296ecd21e62ed97f574f6a3a4af1d +--- /dev/null ++++ b/src/main/java/me/earthme/luminol/api/entity/PreEntityPortalEvent.java +@@ -0,0 +1,73 @@ ++package me.earthme.luminol.api.entity; ++ ++import org.apache.commons.lang3.Validate; ++import org.bukkit.Location; ++import org.bukkit.World; ++import org.bukkit.entity.Entity; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A simple event created for missing teleport events api of folia ++ * This event will be fired when a portal teleportation is about to happen ++ */ ++public class PreEntityPortalEvent extends Event implements Cancellable { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ private final Entity entity; ++ private final Location portalPos; ++ private final World destination; ++ ++ private boolean cancelled = false; ++ ++ public PreEntityPortalEvent(Entity entity, Location portalPos, World destination) { ++ Validate.notNull(entity, "entity cannot be null!"); ++ Validate.notNull(portalPos, "portalPos cannot be null!"); ++ Validate.notNull(destination, "destination cannot be null!"); ++ ++ this.entity = entity; ++ this.portalPos = portalPos; ++ this.destination = destination; ++ } ++ ++ /** ++ * Get the entity that is about to teleport ++ * @return the entity ++ */ ++ public @NotNull Entity getEntity() { ++ return this.entity; ++ } ++ ++ /** ++ * Get the location of the portal ++ * @return the portal location ++ */ ++ public @NotNull Location getPortalPos() { ++ return this.portalPos; ++ } ++ ++ /** ++ * Get the destination world ++ * @return the destination world ++ */ ++ public @NotNull World getDestination() { ++ return this.destination; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLERS; ++ } ++} +diff --git a/src/main/java/me/earthme/luminol/api/entity/player/PostPlayerRespawnEvent.java b/src/main/java/me/earthme/luminol/api/entity/player/PostPlayerRespawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bf4469593b22f3e5cff89953819e7fdde252abf5 +--- /dev/null ++++ b/src/main/java/me/earthme/luminol/api/entity/player/PostPlayerRespawnEvent.java +@@ -0,0 +1,35 @@ ++package me.earthme.luminol.api.entity.player; ++ ++import org.apache.commons.lang3.Validate; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A simple event fired when the respawn process of player is done ++ */ ++public class PostPlayerRespawnEvent extends Event { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ private final Player player; ++ ++ public PostPlayerRespawnEvent(Player player) { ++ Validate.notNull(player, "Player cannot be a null value!"); ++ ++ this.player = player; ++ } ++ ++ /** ++ * Get the respawned player ++ * @return the player ++ */ ++ public @NotNull Player getPlayer() { ++ return this.player; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLERS; ++ } ++} +diff --git a/src/main/java/me/earthme/luminol/api/portal/EndPlatformCreateEvent.java b/src/main/java/me/earthme/luminol/api/portal/EndPlatformCreateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..12b2bef2f66f22bb56c10434cc08b39cef335447 +--- /dev/null ++++ b/src/main/java/me/earthme/luminol/api/portal/EndPlatformCreateEvent.java +@@ -0,0 +1,30 @@ ++package me.earthme.luminol.api.portal; ++ ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A event fired when an end platform is created. ++ */ ++public class EndPlatformCreateEvent extends Event implements Cancellable { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ private boolean cancelled = false; ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLERS; ++ } ++} +diff --git a/src/main/java/me/earthme/luminol/api/portal/PortalLocateEvent.java b/src/main/java/me/earthme/luminol/api/portal/PortalLocateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f68bf95bba671f3cf90d9878d93dd319bdf9db40 +--- /dev/null ++++ b/src/main/java/me/earthme/luminol/api/portal/PortalLocateEvent.java +@@ -0,0 +1,57 @@ ++package me.earthme.luminol.api.portal; ++ ++import org.apache.commons.lang3.Validate; ++import org.bukkit.Location; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A event fired when the portal process started locating the destination position ++ */ ++public class PortalLocateEvent extends Event { ++ private static final HandlerList HANDLERS = new HandlerList(); ++ ++ private final Location original; ++ private Location destination; ++ ++ public PortalLocateEvent(Location original, Location destination) { ++ Validate.notNull(original, "original couldn't be null!"); ++ Validate.notNull(destination, "destination couldn't be null!"); ++ ++ this.original = original; ++ this.destination = destination; ++ } ++ ++ /** ++ * Get the destination position of this teleportation ++ * @return the destination position ++ */ ++ public Location getDestination() { ++ return this.destination; ++ } ++ ++ /** ++ * Set the destination position of this teleportation ++ * @param destination the destination position ++ */ ++ public void setDestination(@NotNull Location destination) { ++ Validate.notNull(destination, "Destination position couldn't be null!"); ++ Validate.isTrue(destination.getWorld().equals(this.destination.getWorld()), "Destination position couldn't be a different level!"); ++ ++ this.destination = destination; ++ } ++ ++ /** ++ * Get the original portal position of this teleportation ++ * @return the original portal position ++ */ ++ public Location getOriginal() { ++ return this.original; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLERS; ++ } ++} diff --git a/luminol-server/minecraft-patches/features/0041-Add-missing-teleportation-apis-for-folia.patch b/luminol-server/minecraft-patches/features/0041-Add-missing-teleportation-apis-for-folia.patch new file mode 100644 index 0000000..b29e509 --- /dev/null +++ b/luminol-server/minecraft-patches/features/0041-Add-missing-teleportation-apis-for-folia.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Fri, 31 Jan 2025 20:28:45 +0800 +Subject: [PATCH] Add missing teleportation apis for folia + + +diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java +index 9fd3fe181df2ce6dbe695f6463d3940ac4c01167..822d401150d3764004b2570da828b4f69f19dcec 100644 +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -1653,6 +1653,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + if (respawnComplete != null) { + respawnComplete.accept(ServerPlayer.this); + } ++ // Luminol - Add missing teleportation apis ++ new me.earthme.luminol.api.entity.player.PostPlayerRespawnEvent(ServerPlayer.this.getBukkitEntity()).callEvent(); ++ // Luminol end + } + ); + }); +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index 406c382ae2fdaa7d8996d250487bbdfb7e4bb7f9..29fc2e5af0b6ec81c3f0c1c89f76166e7f4ac19c 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -4164,6 +4164,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } + + // TODO any events that can modify go HERE ++ // Luminol start - Add missing teleportation apis ++ if (!new me.earthme.luminol.api.entity.EntityTeleportAsyncEvent( ++ this.getBukkitEntity(), ++ cause, ++ io.papermc.paper.util.MCUtil.toLocation(destination, pos, yaw ,pitch) ++ ).callEvent()) { ++ return false; ++ } ++ // Luminol end + + // check for same region + if (destination == this.level()) { +@@ -4280,7 +4289,20 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + // we just select the spawn position + case END: { + if (destination.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END) { +- BlockPos targetPos = ServerLevel.END_SPAWN_POINT; ++ BlockPos targetPos1 = ServerLevel.END_SPAWN_POINT; // Luminol - Rename ++ // Luminol start - Add missing teleportation apis ++ final org.bukkit.Location orginalPortalLocation = io.papermc.paper.util.MCUtil.toLocation(origin, originPortal); ++ final org.bukkit.Location targetPortalLocation = io.papermc.paper.util.MCUtil.toLocation(destination, targetPos1); ++ ++ final me.earthme.luminol.api.portal.PortalLocateEvent portalLocateEvent = new me.earthme.luminol.api.portal.PortalLocateEvent( ++ orginalPortalLocation, ++ targetPortalLocation ++ ); ++ ++ portalLocateEvent.callEvent(); ++ ++ final BlockPos targetPos = io.papermc.paper.util.MCUtil.toBlockPosition(portalLocateEvent.getDestination()); // Swap value ++ // Luminol end + // need to load chunks so we can create the platform + destination.moonrise$loadChunksAsync( + targetPos, 16, // load 16 blocks to be safe from block physics +@@ -4305,7 +4327,20 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } + ); + } else { +- BlockPos spawnPos = destination.getSharedSpawnPos(); ++ BlockPos spawnPos1 = destination.getSharedSpawnPos(); // Luminol - Rename ++ // Luminol start - Add missing teleportation apis ++ final org.bukkit.Location orginalPortalLocation = io.papermc.paper.util.MCUtil.toLocation(origin, originPortal); ++ final org.bukkit.Location targetPortalLocation = io.papermc.paper.util.MCUtil.toLocation(destination, spawnPos1); ++ ++ final me.earthme.luminol.api.portal.PortalLocateEvent portalLocateEvent = new me.earthme.luminol.api.portal.PortalLocateEvent( ++ orginalPortalLocation, ++ targetPortalLocation ++ ); ++ ++ portalLocateEvent.callEvent(); ++ ++ final BlockPos spawnPos = io.papermc.paper.util.MCUtil.toBlockPosition(portalLocateEvent.getDestination()); // Swap value ++ // Luminol end + // need to load chunk for heightmap + destination.moonrise$loadChunksAsync( + spawnPos, 0, +@@ -4355,8 +4390,20 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + + WorldBorder destinationBorder = destination.getWorldBorder(); + double dimensionScale = net.minecraft.world.level.dimension.DimensionType.getTeleportationScale(origin.dimensionType(), destination.dimensionType()); +- BlockPos targetPos = destination.getWorldBorder().clampToBounds(this.getX() * dimensionScale, this.getY(), this.getZ() * dimensionScale); ++ BlockPos targetPos1 = destination.getWorldBorder().clampToBounds(this.getX() * dimensionScale, this.getY(), this.getZ() * dimensionScale); // Luminol - Rename ++ // Luminol start - Add missing teleportation apis ++ final org.bukkit.Location orginalPortalLocation = io.papermc.paper.util.MCUtil.toLocation(origin, originPortal); ++ final org.bukkit.Location targetPortalLocation = io.papermc.paper.util.MCUtil.toLocation(destination, targetPos1); ++ ++ final me.earthme.luminol.api.portal.PortalLocateEvent portalLocateEvent = new me.earthme.luminol.api.portal.PortalLocateEvent( ++ orginalPortalLocation, ++ targetPortalLocation ++ ); ++ ++ portalLocateEvent.callEvent(); + ++ final BlockPos targetPos = io.papermc.paper.util.MCUtil.toBlockPosition(portalLocateEvent.getDestination()); // Swap value ++ // Luminol end + ca.spottedleaf.concurrentutil.completable.CallbackCompletable portalFound + = new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>(); + +@@ -4493,9 +4540,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (!this.canPortalAsync(destination, takePassengers)) { + return false; + } ++ // Luminol start - Add missing teleportation events ++ if (!new me.earthme.luminol.api.entity.PreEntityPortalEvent( ++ this.getBukkitEntity(), ++ io.papermc.paper.util.MCUtil.toLocation(this.level, portalPos), ++ destination.getWorld() ++ ).callEvent()) { ++ return false; ++ } ++ // Luminol end + // Kaiiju start - sync end platform spawning & entity teleportation + final java.util.function.Consumer tpComplete = type == PortalType.END && destination.getTypeKey() == LevelStem.END ? +- e -> net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, ServerLevel.END_SPAWN_POINT.below(), true, null) : teleportComplete; ++ e -> { if (new me.earthme.luminol.api.portal.EndPlatformCreateEvent().callEvent()) net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, ServerLevel.END_SPAWN_POINT.below(), true, null); } : teleportComplete; // Luminol - Add missing teleportation events + // Kaiiju end + + Vec3 initialPosition = this.position(); +@@ -4569,6 +4625,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + tpComplete.accept(teleported); + } + // Kaiiju end ++ // Luminol start - Add missing teleportation events ++ new me.earthme.luminol.api.entity.PostEntityPortalEvent(teleported.getBukkitEntity()).callEvent(); ++ // Luminol end + } + ); + });