From 71599472b9c40c060fd6f2543003ef4f7118fb06 Mon Sep 17 00:00:00 2001 From: fishshi <2855691008@qq.com> Date: Fri, 20 Sep 2024 14:14:47 +0800 Subject: [PATCH 1/2] add ALLOW_PLAYER_CHANGE_WORLD --- .../v1/ServerEntityWorldChangeEvents.java | 26 +++++++++++++++++++ .../entity/event/ServerPlayerEntityMixin.java | 12 +++++++++ .../test/entity/event/EntityEventTests.java | 10 +++++++ 3 files changed, 48 insertions(+) diff --git a/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java b/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java index b1fa89d736..82c013a32a 100644 --- a/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java +++ b/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java @@ -45,6 +45,19 @@ public final class ServerEntityWorldChangeEvents { } }); + /** + * Called before a player is being moved to a different world. + */ + public static final Event ALLOW_PLAYER_CHANGE_WORLD = EventFactory.createArrayBacked(AllowPlayerChange.class, callbacks -> (player, origin, destination) -> { + for (AllowPlayerChange callback : callbacks) { + if (!callback.allowChangeWorld(player, origin, destination)){ + return false; + } + } + + return true; + }); + /** * An event which is called after a player has been moved to a different world. * @@ -75,6 +88,19 @@ public interface AfterEntityChange { void afterChangeWorld(Entity originalEntity, Entity newEntity, ServerWorld origin, ServerWorld destination); } + @FunctionalInterface + public interface AllowPlayerChange { + /** + * Called before a player is being moved to a different world. + * + * @param player the player + * @param origin the original world the player is in + * @param destination the new world the player is moving to + * @return true if the player is allowed to change worlds, false otherwise + */ + boolean allowChangeWorld(ServerPlayerEntity player, ServerWorld origin, ServerWorld destination); + } + @FunctionalInterface public interface AfterPlayerChange { /** diff --git a/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/mixin/entity/event/ServerPlayerEntityMixin.java b/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/mixin/entity/event/ServerPlayerEntityMixin.java index 2c13abe408..43e4e4b4e3 100644 --- a/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/mixin/entity/event/ServerPlayerEntityMixin.java +++ b/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/mixin/entity/event/ServerPlayerEntityMixin.java @@ -20,6 +20,7 @@ import com.mojang.datafixers.util.Either; import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -43,6 +44,7 @@ import net.minecraft.util.Unit; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.world.TeleportTarget; import net.minecraft.world.World; import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents; @@ -77,6 +79,16 @@ private void notifyDeath(DamageSource source, CallbackInfo ci) { ServerLivingEntityEvents.AFTER_DEATH.invoker().afterDeath((ServerPlayerEntity) (Object) this, source); } + @Inject(method = "teleportTo", at = @At(value = "FIELD", target = "Lnet/minecraft/server/network/ServerPlayerEntity;inTeleportationState:Z", opcode = Opcodes.PUTFIELD), cancellable = true) + private void beforeWorldChanged(TeleportTarget teleportTarget, CallbackInfoReturnable cir) { + ServerPlayerEntity player = (ServerPlayerEntity) (Object) this; + boolean allowed = ServerEntityWorldChangeEvents.ALLOW_PLAYER_CHANGE_WORLD.invoker().allowChangeWorld(player, player.getServerWorld(), teleportTarget.world()); + + if (!allowed) { + cir.setReturnValue(null); + } + } + /** * This is called by {@code teleportTo}. */ diff --git a/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java b/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java index f6e1779ed5..433d0dd4b9 100644 --- a/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java +++ b/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java @@ -64,6 +64,16 @@ public void onInitialize() { LOGGER.info("Entity {} Killed: {}", entity, killed); }); + ServerEntityWorldChangeEvents.ALLOW_PLAYER_CHANGE_WORLD.register((player, origin, destination) -> { + if (player.getStackInHand(Hand.MAIN_HAND).getItem() == Items.END_ROD) { + LOGGER.info("Player {} failed to change world because of handing an end rod", player.getGameProfile().getName()); + return false; + } + + LOGGER.info("Allow Moving player {}: [{} -> {}]", player, origin.getRegistryKey().getValue(), destination.getRegistryKey().getValue()); + return true; + }); + ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.register((player, origin, destination) -> { LOGGER.info("Moved player {}: [{} -> {}]", player, origin.getRegistryKey().getValue(), destination.getRegistryKey().getValue()); }); From e36f266fc63524a8f3381df6b1bfcb519d3a3f52 Mon Sep 17 00:00:00 2001 From: fishshi <2855691008@qq.com> Date: Sat, 21 Sep 2024 13:30:21 +0800 Subject: [PATCH 2/2] fix --- .../api/entity/event/v1/ServerEntityWorldChangeEvents.java | 2 +- .../net/fabricmc/fabric/test/entity/event/EntityEventTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java b/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java index 82c013a32a..7088594adf 100644 --- a/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java +++ b/fabric-entity-events-v1/src/main/java/net/fabricmc/fabric/api/entity/event/v1/ServerEntityWorldChangeEvents.java @@ -50,7 +50,7 @@ public final class ServerEntityWorldChangeEvents { */ public static final Event ALLOW_PLAYER_CHANGE_WORLD = EventFactory.createArrayBacked(AllowPlayerChange.class, callbacks -> (player, origin, destination) -> { for (AllowPlayerChange callback : callbacks) { - if (!callback.allowChangeWorld(player, origin, destination)){ + if (!callback.allowChangeWorld(player, origin, destination)) { return false; } } diff --git a/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java b/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java index 433d0dd4b9..5071efa365 100644 --- a/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java +++ b/fabric-entity-events-v1/src/testmod/java/net/fabricmc/fabric/test/entity/event/EntityEventTests.java @@ -65,7 +65,7 @@ public void onInitialize() { }); ServerEntityWorldChangeEvents.ALLOW_PLAYER_CHANGE_WORLD.register((player, origin, destination) -> { - if (player.getStackInHand(Hand.MAIN_HAND).getItem() == Items.END_ROD) { + if (player.getMainHandStack().isOf(Items.END_ROD)) { LOGGER.info("Player {} failed to change world because of handing an end rod", player.getGameProfile().getName()); return false; }