Paper icon indicating copy to clipboard operation
Paper copied to clipboard

EntityTeleportEndGatewayEvent not work in passengers

Open Doc94 opened this issue 4 years ago • 4 comments

Expected behavior

When a entity mounted in another entity enter to a END_GATEWAY and is cancel using EntityTeleportEndGatewayEvent the entity mounted cant be teleported.

Observed/Actual behavior

When a player in a boat enter to the END_GATEWAY the boat not teleport because the EntityTeleportEndGatewayEvent is cancelled but the passengers (player) still can teleport.

Steps/models to reproduce

@EventHandler public void portalEnter(EntityTeleportEndGatewayEvent event) { event.setCancelled(true); }

  • Enter to the END
  • Destroy the BEDROCK
  • Put a boat
  • Navigate to the portal

Plugin list

N/A

Paper version

This server is running Paper version git-Paper-276 (MC: 1.17.1) (Implementing API version 1.17.1-R0.1-SNAPSHOT) (Git: 1707c10) You are 2 version(s) behind Previous version: git-Paper-266 (MC: 1.17.1)

Agreements

  • [X] I am running the latest version of Paper available from https://papermc.io/downloads.
  • [X] I have searched for and ensured there isn't already an open issue regarding this.
  • [X] My version of Minecraft is supported by Paper.

Other

The event works like paralel to PlayerTeleportEvent not?

because this issue happen with enderpearls too, then the temporal fix is use the two events EntityTeleportEndGatewayEvent and PlayerTeleportEvent because PlayerPortalEvent is not valid for this cases.

Doc94 avatar Sep 24 '21 21:09 Doc94

I can validate that this is the behavior on d0a2193d4a93ecc7dd69499cd1aa86c94d0f51f4. This is due to the fact that end gateways have an internal cooldown between each teleportation that is started even if the first entity that was to be teleported got its event cancelled.

Specifically TheEndGatewayBlockEntity.java line 112 breaks out of the loop over all entities after the first potential candidate, preventing any further logic from executing in regards to teleportation, whether the teleport was successful or not.

// edit[0]: The reason why I moved this to accepted was the fact that an entity in the same portal as another (at least in my opinion) should not block the other entity from teleporting. The passenger use-case I am not as sure about and should be subject to further discussion on here.

lynxplay avatar Sep 25 '21 16:09 lynxplay

@lynxplay where is the internal cooldown applied if the teleports fail? I see this

            if (blockEntity.age % 2400L == 0L) {
                TheEndGatewayBlockEntity.triggerCooldown(world, pos, state, blockEntity);
            }

but doesnt that only trigger the cooldown every 2400 ticks (2 minutes)? otherwise, the cooldown is applied if the player/entity events succeed

Machine-Maker avatar Oct 08 '21 05:10 Machine-Maker

@lynxplay where is the internal cooldown applied if the teleports fail? I see this

            if (blockEntity.age % 2400L == 0L) {
                TheEndGatewayBlockEntity.triggerCooldown(world, pos, state, blockEntity);
            }

but doesnt that only trigger the cooldown every 2400 ticks (2 minutes)? otherwise, the cooldown is applied if the player/entity events succeed

In TheEndGatewayBlockEntity#teleportTick

if (flag1) {
    --blockEntity.teleportCooldown;
} else {

ticks down until the block entities teleport cooldown becomes zero or less (as expected). If that is the case and a teleport is supposed to happen, a list of possible entities is gathered (see line 105) and the first entitiy that Entity#canChangeDimensions will be passed into TheEndGatewayBlockEntity#teleportEntity which, starts off as follows:

public static void teleportEntity(Level world, BlockPos pos, BlockState state, Entity entity, TheEndGatewayBlockEntity blockEntity) {
    if (world instanceof ServerLevel && !blockEntity.isCoolingDown()) {
        ServerLevel worldserver = (ServerLevel) world;

        blockEntity.teleportCooldown = 100;

effectively resetting the cooldown checked previously. Additionally, this method does not return any form of feedback whether the teleportation performed was cancelled by an event, causing

for (Entity entity : list) {
    if (entity.canChangeDimensions()) {
        TheEndGatewayBlockEntity.teleportEntity(world, pos, state, entity, blockEntity);
        break;
    }
}

to break out of the loop early no matter the teleportation result (successful/cancelled), meaning no other entities eligible for the teleportation in that tick were attempted to teleport.

In the next tick, the gateway is back to the 100 tick cooldown set by TheEndGatewayBlockEntity#teleportEntity, causing the described issue.

I hope this clarified where I think the cooldown originates from a bit :+1:

lynxplay avatar Oct 08 '21 07:10 lynxplay

Well, going back into the "passenger" use-case, it is always the root vehicle that is attempted to be teleported (see TheEndGatewayBlockEntity:211), so if a player were to ride a boat into an end gateway, the player would never trigger a teleport event, rather two events for the boat would be called.

The passengers will hence never be teleported on its own, making at least this concrete issue rather "works-as-intended".

The secondary issue regarding the "blocking" of the end gateway by an entity that has its events cancelled remains.

lynxplay avatar Oct 10 '21 19:10 lynxplay

Closing now that the original issue is no longer relevant. The other issues mentioned above can be their own issue if they are still relevant.

Lulu13022002 avatar Dec 06 '25 17:12 Lulu13022002