Skip to content

Commit c595211

Browse files
committed
Adjust some of our teleporter code to more closely match new vanilla code:
- Query Entity#canUsePortal rather than us checking if they are a passenger directly - Allow vanilla's changeDimension logic to handle teleporting passengers across dimensions now that vanilla supports it - Make use of post transition logic to do things like triggering player advancements so that even if the player is riding a minecart they will get the advancement - Align the player with the exit teleporter as part of the initial teleport, rather than doing so by teleporting the entity more or less in place
1 parent b0920ed commit c595211

File tree

2 files changed

+57
-67
lines changed

2 files changed

+57
-67
lines changed

src/main/java/mekanism/common/network/to_server/PacketPortableTeleporterTeleport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import net.minecraft.world.InteractionHand;
2929
import net.minecraft.world.item.ItemStack;
3030
import net.minecraft.world.level.Level;
31+
import net.minecraft.world.level.portal.DimensionTransition;
3132
import net.neoforged.neoforge.common.NeoForge;
3233
import net.neoforged.neoforge.network.handling.IPayloadContext;
3334
import org.jetbrains.annotations.NotNull;
@@ -97,8 +98,7 @@ public void handle(IPayloadContext context) {
9798
double oldY = player.getY();
9899
double oldZ = player.getZ();
99100
Level oldWorld = player.level();
100-
TileEntityTeleporter.teleportEntityTo(player, teleWorld, event, false);
101-
TileEntityTeleporter.alignPlayer(player, event, teleporter);
101+
TileEntityTeleporter.teleportEntityTo(player, teleWorld, teleporter, event, false, DimensionTransition.DO_NOTHING);
102102
if (player.level() != oldWorld || player.distanceToSqr(oldX, oldY, oldZ) >= 25) {
103103
//If the player teleported over 5 blocks, play the sound at both the destination and the source
104104
oldWorld.playSound(null, oldX, oldY, oldZ, SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS);

src/main/java/mekanism/common/tile/TileEntityTeleporter.java

Lines changed: 55 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import net.minecraft.world.level.block.state.BlockState;
7474
import net.minecraft.world.level.chunk.ChunkAccess;
7575
import net.minecraft.world.level.portal.DimensionTransition;
76+
import net.minecraft.world.level.portal.DimensionTransition.PostDimensionTransition;
7677
import net.minecraft.world.phys.AABB;
7778
import net.minecraft.world.phys.Vec3;
7879
import net.neoforged.neoforge.common.NeoForge;
@@ -88,6 +89,11 @@ public class TileEntityTeleporter extends TileEntityMekanism implements IChunkLo
8889
private static final TeleportInfo NO_FRAME = new TeleportInfo((byte) 2, null, Collections.emptyList());
8990
private static final TeleportInfo NO_LINK = new TeleportInfo((byte) 3, null, Collections.emptyList());
9091
private static final TeleportInfo NOT_ENOUGH_ENERGY = new TeleportInfo((byte) 4, null, Collections.emptyList());
92+
private static final PostDimensionTransition AWARD_ADVANCEMENT = entity -> {
93+
if (entity instanceof ServerPlayer player) {
94+
MekanismCriteriaTriggers.TELEPORT.value().trigger(player);
95+
}
96+
};
9197

9298
public final Set<UUID> didTeleport = new ObjectOpenHashSet<>();
9399
private final Predicate<Entity> SAME_DIMENSION_TARGET = entity -> canTeleportEntity(entity, null);
@@ -134,43 +140,37 @@ protected IInventorySlotHolder getInitialInventory(IContentsListener listener) {
134140
}
135141

136142
private boolean canTeleportEntity(Entity entity, @Nullable Level destinationLevel) {
137-
if (entity.isSpectator() || entity.isPassenger() || entity instanceof PartEntity || entity.getType().is(Tags.EntityTypes.TELEPORTING_NOT_SUPPORTED)) {
143+
if (entity.isSpectator() || !entity.canUsePortal(false) || entity instanceof PartEntity || entity.getType().is(Tags.EntityTypes.TELEPORTING_NOT_SUPPORTED)) {
138144
return false;
139145
} else if (destinationLevel != null && !entity.canChangeDimensions(entity.level(), destinationLevel)) {
140146
return false;
141147
}
142148
return !didTeleport.contains(entity.getUUID());
143149
}
144150

145-
public static void alignPlayer(ServerPlayer player, MekanismTeleportEvent.Teleporter event, TileEntityTeleporter teleporter) {
146-
alignPlayer(player, BlockPos.containing(event.getTarget()), teleporter);
147-
}
148-
149-
private static void alignPlayer(ServerPlayer player, BlockPos target, TileEntityTeleporter teleporter) {
151+
private static float alignPlayer(ServerPlayer player, BlockPos target, TileEntityTeleporter teleporter) {
150152
Direction side = null;
151153
if (teleporter.frameDirection != null && teleporter.frameDirection.getAxis().isHorizontal()) {
152154
//If the frame is horizontal always face towards the other portion of the frame
153155
side = teleporter.frameDirection;
154156
} else {
155157
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
158+
Level level = teleporter.getWorldNN();
156159
for (Direction iterSide : EnumUtils.HORIZONTAL_DIRECTIONS) {
157160
mutable.setWithOffset(target, iterSide);
158-
if (player.level().isEmptyBlock(mutable)) {
161+
if (level.isEmptyBlock(mutable)) {
159162
side = iterSide;
160163
break;
161164
}
162165
}
163166
}
164-
float yaw = player.getYRot();
165-
if (side != null) {
166-
switch (side) {
167-
case NORTH -> yaw = 180;
168-
case SOUTH -> yaw = 0;
169-
case WEST -> yaw = 90;
170-
case EAST -> yaw = 270;
171-
}
172-
}
173-
player.connection.teleport(player.getX(), player.getY(), player.getZ(), yaw, player.getXRot());
167+
return switch (side) {
168+
case NORTH -> 180;
169+
case SOUTH -> 0;
170+
case WEST -> 90;
171+
case EAST -> 270;
172+
case null, default -> player.getYRot();
173+
};
174174
}
175175

176176
@Override
@@ -264,7 +264,7 @@ private TeleportInfo canTeleport(@Nullable TeleporterFrequency frequency) {
264264
return NO_LINK;
265265
}
266266
targetWorld = server.getLevel(closestCoords.dimension());
267-
if (targetWorld == null) {//In theory should not happen
267+
if (targetWorld == null || !server.isLevelEnabled(targetWorld)) {//In theory should not happen
268268
return NO_LINK;
269269
}
270270
}
@@ -337,11 +337,9 @@ private void teleport(TeleporterFrequency frequency, TeleportInfo teleportInfo)
337337
double oldX = entity.getX();
338338
double oldY = entity.getY();
339339
double oldZ = entity.getZ();
340-
Entity teleportedEntity = teleportEntityTo(entity, teleWorld, event, true);
341-
if (teleportedEntity instanceof ServerPlayer player) {
342-
alignPlayer(player, event, teleporter);
343-
MekanismCriteriaTriggers.TELEPORT.value().trigger(player);
344-
}
340+
Entity teleportedEntity = teleportEntityTo(entity, teleWorld, teleporter, event, true, AWARD_ADVANCEMENT);
341+
//Note: The below logic isn't part of a PostDimensionTransition as the transition applies to all entities and passengers,
342+
// and we want the below logic to only happen once
345343
for (GlobalPos coords : activeCoords) {
346344
Level world = level.dimension() == coords.dimension() ? level : currentServer.getLevel(coords.dimension());
347345
TileEntityTeleporter tile = WorldUtils.getTileEntity(TileEntityTeleporter.class, world, coords.pos());
@@ -351,13 +349,7 @@ private void teleport(TeleporterFrequency frequency, TeleportInfo teleportInfo)
351349
}
352350
energyContainer.extract(energyCost, Action.EXECUTE, AutomationType.INTERNAL);
353351
if (teleportedEntity != null) {
354-
SoundEvent sound = switch (teleportedEntity) {
355-
case Player player -> SoundEvents.PLAYER_TELEPORT;
356-
case Fox fox -> SoundEvents.FOX_TELEPORT;
357-
case Shulker shulker -> SoundEvents.SHULKER_TELEPORT;
358-
//Fall back to enderman teleporting sound
359-
default -> SoundEvents.ENDERMAN_TELEPORT;
360-
};
352+
SoundEvent sound = getTeleportSound(teleportedEntity);
361353
if (level != teleportedEntity.level() || teleportedEntity.distanceToSqr(oldX, oldY, oldZ) >= 25) {
362354
//If the entity teleported over 5 blocks, play the sound at both the destination and the source
363355
level.playSound(null, oldX, oldY, oldZ, sound, entity.getSoundSource());
@@ -369,6 +361,16 @@ private void teleport(TeleporterFrequency frequency, TeleportInfo teleportInfo)
369361
}
370362
}
371363

364+
private static SoundEvent getTeleportSound(Entity entity) {
365+
return switch (entity) {
366+
case Player player -> SoundEvents.PLAYER_TELEPORT;
367+
case Fox fox -> SoundEvents.FOX_TELEPORT;
368+
case Shulker shulker -> SoundEvents.SHULKER_TELEPORT;
369+
//Fall back to enderman teleporting sound
370+
default -> SoundEvents.ENDERMAN_TELEPORT;
371+
};
372+
}
373+
372374
private void markTeleported(TileEntityTeleporter teleporter, Entity entity, boolean sameDimension, Level destinationWorld) {
373375
if (sameDimension || entity.canChangeDimensions(entity.level(), destinationWorld)) {
374376
//Only mark the entity as teleported if it will teleport, it is in the same dimension or is able to change dimensions
@@ -381,11 +383,23 @@ private void markTeleported(TileEntityTeleporter teleporter, Entity entity, bool
381383
}
382384

383385
@Nullable
384-
public static Entity teleportEntityTo(Entity entity, Level targetWorld, MekanismTeleportEvent.Teleporter event, boolean persistMovement) {
386+
public static Entity teleportEntityTo(Entity entity, Level targetWorld, TileEntityTeleporter target, MekanismTeleportEvent.Teleporter event, boolean persistMovement,
387+
PostDimensionTransition transition) {
385388
Vec3 destination = event.getTarget();
389+
float yRot = entity.getYRot();
390+
if (entity instanceof ServerPlayer player) {
391+
//Align players with the output teleporter
392+
yRot = alignPlayer(player, BlockPos.containing(destination), target);
393+
}
386394
if (!event.isTransDimensional()) {
387395
Vec3 deltaMovement = entity.getDeltaMovement();
388-
entity.teleportTo(destination.x, destination.y, destination.z);
396+
if (entity instanceof ServerPlayer player) {
397+
//Note: We can't use the normal teleportTo method for server players as they override it to not actually sync rotation
398+
// to the client
399+
player.connection.teleport(destination.x, destination.y, destination.z, yRot, entity.getXRot());
400+
} else {
401+
entity.teleportTo(destination.x, destination.y, destination.z);
402+
}
389403
if (!entity.getPassengers().isEmpty()) {
390404
//Force re-apply any passengers so that players don't get "stuck" outside what they may be riding
391405
((ServerChunkCache) entity.level().getChunkSource()).broadcast(entity, new ClientboundSetPassengersPacket(entity));
@@ -404,41 +418,17 @@ public static Entity teleportEntityTo(Entity entity, Level targetWorld, Mekanism
404418
//Force sync the delta movement to the client so that they don't stop moving due to the teleport and movement being client sided
405419
PacketDistributor.sendToPlayer(player, new PacketSetDeltaMovement(deltaMovement));
406420
}
407-
return entity;
408-
}
409-
//Note: We grab the passengers here instead of in placeEntity as changeDimension starts by removing any passengers
410-
List<Entity> passengers = entity.getPassengers();
411-
Level fromWorld = entity.level();
412-
ServerLevel serverLevel = (ServerLevel) targetWorld;
413-
return entity.changeDimension(new DimensionTransition(serverLevel, destination, entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), target -> {
414-
//Teleport all passengers to the other dimension and then make them start riding the entity again
415-
for (Entity passenger : passengers) {
416-
teleportPassenger(fromWorld, serverLevel, destination, target, passenger);
421+
//Handle transition logic even though we didn't change dimensions
422+
if (transition != DimensionTransition.DO_NOTHING) {
423+
for (Entity passenger : entity.getIndirectPassengers()) {
424+
transition.onTransition(passenger);
425+
}
426+
transition.onTransition(entity);
417427
}
418-
}));
419-
}
420-
421-
private static void teleportPassenger(Level fromWorld, ServerLevel destWorld, Vec3 destination, Entity repositionedEntity, Entity passenger) {
422-
if (!passenger.canChangeDimensions(fromWorld, destWorld)) {
423-
//If the passenger can't change dimensions just let it peacefully stay after dismounting rather than trying to teleport it
424-
return;
428+
return entity;
425429
}
426-
//Note: We grab the passengers here instead of in placeEntity as changeDimension starts by removing any passengers
427-
List<Entity> passengers = passenger.getPassengers();
428-
passenger.changeDimension(new DimensionTransition(destWorld, destination, passenger.getDeltaMovement(), passenger.getYRot(), passenger.getXRot(), target -> {
429-
//TODO - 1.21: Test if this logic for making the entity not take damage works or if the post transition thing, is well past teleport and past damage
430-
boolean invulnerable = target.isInvulnerable();
431-
//Make the entity invulnerable so that when we teleport it, it doesn't take damage
432-
// we revert this state to the previous state after teleporting
433-
target.setInvulnerable(true);
434-
//Force our passenger to start riding the new entity again
435-
target.startRiding(repositionedEntity, true);
436-
//Teleport "nested" passengers
437-
for (Entity p : passengers) {
438-
teleportPassenger(fromWorld, destWorld, destination, target, p);
439-
}
440-
target.setInvulnerable(invulnerable);
441-
}));
430+
//player.connection.teleport(player.getX(), player.getY(), player.getZ(), yaw, player.getXRot());
431+
return entity.changeDimension(new DimensionTransition((ServerLevel) targetWorld, destination, entity.getDeltaMovement(), yRot, entity.getXRot(), transition));
442432
}
443433

444434
private List<Entity> getToTeleport(boolean sameDimension, Level destinationLevel) {

0 commit comments

Comments
 (0)