use of org.spongepowered.api.event.entity.RotateEntityEvent in project SpongeCommon by SpongePowered.
the class ServerPlayerMixin method teleportTo.
/*
@Inject(method = "markPlayerActive()V", at = @At("HEAD"))
private void impl$onPlayerActive(final CallbackInfo ci) {
((ServerPlayNetHandlerBridge) this.connection).bridge$resendLatestResourcePackRequest();
}
*/
/**
* @author zidane - November 21st, 2020 - Minecraft 1.15
* @reason Ensure that the teleport hook honors our events
*/
@Overwrite
public void teleportTo(final net.minecraft.server.level.ServerLevel world, final double x, final double y, final double z, final float yaw, final float pitch) {
final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this;
double actualX = x;
double actualY = y;
double actualZ = z;
double actualYaw = yaw;
double actualPitch = pitch;
final boolean hasMovementContext = PhaseTracker.getCauseStackManager().currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE);
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
if (!hasMovementContext) {
frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN);
}
if (world == player.level) {
@Nullable final Vector3d destination = this.impl$fireMoveEvent(PhaseTracker.SERVER, new Vector3d(x, y, z));
if (destination == null) {
return;
}
actualX = destination.x();
actualY = destination.y();
actualZ = destination.z();
if (ShouldFire.ROTATE_ENTITY_EVENT) {
final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) player, new Vector3d(actualPitch, actualYaw, 0), new Vector3d(pitch, yaw, 0));
SpongeCommon.post(rotateEvent);
actualYaw = rotateEvent.isCancelled() ? player.yRot : rotateEvent.toRotation().y();
actualPitch = rotateEvent.isCancelled() ? player.xRot : rotateEvent.toRotation().x();
}
this.shadow$setCamera(player);
this.shadow$stopRiding();
if (player.isSleeping()) {
player.stopSleepInBed(true, true);
}
player.connection.teleport(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch);
player.setYHeadRot((float) actualYaw);
final ChunkPos chunkpos = new ChunkPos(new BlockPos(actualX, actualY, actualZ));
world.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkpos, 1, player.getId());
} else {
final ChangeEntityWorldEvent.Pre preEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre(player, world);
if (SpongeCommon.post(preEvent)) {
return;
}
if (ShouldFire.MOVE_ENTITY_EVENT) {
final MoveEntityEvent posEvent = SpongeEventFactory.createChangeEntityWorldEventReposition(frame.currentCause(), (org.spongepowered.api.entity.Entity) player, preEvent.originalWorld(), VecHelper.toVector3d(player.position()), new Vector3d(x, y, z), preEvent.originalDestinationWorld(), new Vector3d(x, y, z), preEvent.destinationWorld());
if (SpongeCommon.post(posEvent)) {
return;
}
actualX = posEvent.destinationPosition().x();
actualY = posEvent.destinationPosition().y();
actualZ = posEvent.destinationPosition().z();
}
this.shadow$setPos(actualX, actualY, actualZ);
if (ShouldFire.ROTATE_ENTITY_EVENT) {
final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) player, new Vector3d(actualYaw, actualPitch, 0), new Vector3d(yaw, pitch, 0));
if (!SpongeCommon.post(rotateEvent)) {
actualYaw = (float) rotateEvent.toRotation().x();
actualPitch = (float) rotateEvent.toRotation().y();
}
}
this.yRot = (float) actualYaw;
this.xRot = (float) actualPitch;
EntityUtil.performPostChangePlayerWorldLogic(player, (net.minecraft.server.level.ServerLevel) preEvent.originalWorld(), (net.minecraft.server.level.ServerLevel) preEvent.originalDestinationWorld(), (net.minecraft.server.level.ServerLevel) preEvent.destinationWorld(), false);
}
}
}
use of org.spongepowered.api.event.entity.RotateEntityEvent in project SpongeCommon by SpongePowered.
the class TeleportCommandMixin method performTeleport.
/**
* @author Zidane
* @reason Have the teleport command respect our events
*/
@Overwrite
private static void performTeleport(CommandSourceStack source, Entity entityIn, ServerLevel worldIn, double x, double y, double z, Set<ClientboundPlayerPositionPacket.RelativeArgument> relativeList, float yaw, float pitch, @Nullable TeleportCommand.LookAt facing) {
double actualX = x;
double actualY = y;
double actualZ = z;
double actualYaw = yaw;
double actualPitch = pitch;
if (!(entityIn instanceof ServerPlayer)) {
actualYaw = Mth.wrapDegrees(yaw);
actualPitch = Mth.wrapDegrees(pitch);
actualPitch = Mth.clamp(actualPitch, -90.0F, 90.0F);
}
if (worldIn == entityIn.level) {
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND);
if (ShouldFire.MOVE_ENTITY_EVENT) {
final MoveEntityEvent posEvent = SpongeEventFactory.createMoveEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) entityIn, VecHelper.toVector3d(entityIn.position()), new Vector3d(x, y, z), new Vector3d(x, y, z));
if (SpongeCommon.post(posEvent)) {
return;
}
actualX = posEvent.destinationPosition().x();
actualY = posEvent.destinationPosition().y();
actualZ = posEvent.destinationPosition().z();
}
if (ShouldFire.ROTATE_ENTITY_EVENT) {
final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) entityIn, new Vector3d(actualPitch, actualYaw, 0), new Vector3d(pitch, yaw, 0));
SpongeCommon.post(rotateEvent);
actualYaw = rotateEvent.isCancelled() ? entityIn.yRot : rotateEvent.toRotation().y();
actualPitch = rotateEvent.isCancelled() ? entityIn.xRot : rotateEvent.toRotation().x();
}
if (entityIn instanceof ServerPlayer) {
ChunkPos chunkpos = new ChunkPos(new BlockPos(actualX, actualY, actualZ));
worldIn.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkpos, 1, entityIn.getId());
entityIn.stopRiding();
if (((ServerPlayer) entityIn).isSleeping()) {
((ServerPlayer) entityIn).stopSleepInBed(true, true);
}
((ServerPlayer) entityIn).connection.teleport(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch, relativeList);
} else {
entityIn.moveTo(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch);
}
entityIn.setYHeadRot((float) actualYaw);
}
} else {
if (entityIn instanceof ServerPlayer) {
// To ensure mod code is caught, handling the world change for players happens in teleport
// Teleport will create a frame but we want to ensure it'll be the command movement type
// TODO check if this is still correct
PhaseTracker.getCauseStackManager().addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND);
((ServerPlayer) entityIn).teleportTo(worldIn, x, y, z, yaw, pitch);
PhaseTracker.getCauseStackManager().removeContext(EventContextKeys.MOVEMENT_TYPE);
} else {
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND);
final ServerLevel fromWorld = (ServerLevel) entityIn.getCommandSenderWorld();
final ChangeEntityWorldEvent.Pre preEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre(entityIn, worldIn);
if (SpongeCommon.post(preEvent)) {
return;
}
final ChangeEntityWorldEvent.Reposition posEvent = SpongeEventFactory.createChangeEntityWorldEventReposition(frame.currentCause(), (org.spongepowered.api.entity.Entity) entityIn, (org.spongepowered.api.world.server.ServerWorld) entityIn.getCommandSenderWorld(), VecHelper.toVector3d(entityIn.position()), new Vector3d(x, y, z), preEvent.originalDestinationWorld(), new Vector3d(x, y, z), preEvent.destinationWorld());
if (SpongeCommon.post(posEvent)) {
return;
}
entityIn.unRide();
final Entity result = entityIn.getType().create(worldIn);
if (result == null) {
return;
}
if (ShouldFire.ROTATE_ENTITY_EVENT) {
final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), (org.spongepowered.api.entity.Entity) entityIn, new Vector3d(entityIn.xRot, entityIn.yRot, 0), new Vector3d(actualPitch, actualYaw, 0));
if (!SpongeCommon.post(rotateEvent)) {
actualYaw = Mth.wrapDegrees(rotateEvent.toRotation().y());
actualPitch = Mth.wrapDegrees(rotateEvent.toRotation().x());
actualPitch = Mth.clamp(actualPitch, -90.0F, 90.0F);
} else {
actualYaw = entityIn.yRot;
actualPitch = entityIn.xRot;
}
}
result.restoreFrom(entityIn);
result.moveTo(posEvent.destinationPosition().x(), posEvent.destinationPosition().y(), posEvent.destinationPosition().z(), (float) actualYaw, (float) actualPitch);
result.setYHeadRot((float) actualYaw);
worldIn.addFromAnotherDimension(result);
entityIn.removed = true;
Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost(PhaseTracker.getCauseStackManager().currentCause(), (org.spongepowered.api.entity.Entity) result, (ServerWorld) fromWorld, preEvent.originalDestinationWorld(), preEvent.destinationWorld()));
}
}
}
if (facing != null) {
facing.perform(source, entityIn);
}
if (!(entityIn instanceof LivingEntity) || !((LivingEntity) entityIn).isFallFlying()) {
entityIn.setDeltaMovement(entityIn.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D));
entityIn.setOnGround(true);
}
if (entityIn instanceof PathfinderMob) {
((PathfinderMob) entityIn).getNavigation().stop();
}
}
use of org.spongepowered.api.event.entity.RotateEntityEvent in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method callNaturalRotateEntityEvent.
/**
* Performs the logic necessary to post the {@link RotateEntityEvent rotation event} for an {@link Entity}.
*
* @param entity The event
*/
public static void callNaturalRotateEntityEvent(final net.minecraft.world.entity.Entity entity) {
if (entity.removed || (entity.xRot == entity.xRotO && entity.yRot == entity.yRotO)) {
return;
}
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
frame.pushCause(entity);
final RotateEntityEvent event = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), (Entity) entity, new Vector3d(entity.xRotO, entity.yRotO, 0), new Vector3d(entity.xRot, entity.yRot, 0));
if (SpongeCommon.post(event)) {
entity.xRot = entity.xRotO;
entity.yRot = entity.yRotO;
} else {
entity.xRot = (float) event.toRotation().x();
entity.yRot = (float) event.toRotation().y();
}
}
}
use of org.spongepowered.api.event.entity.RotateEntityEvent in project SpongeCommon by SpongePowered.
the class ServerGamePacketListenerImplMixin method impl$callMoveEntityEvent.
/**
* Effectively, hooking into the following code block:
* <pre>
* if (isMovePlayerPacketInvalid(packetIn)) {
* this.disconnect(new TranslationTextComponent("multiplayer.disconnect.invalid_player_movement"));
* } else {
* ServerWorld serverworld = this.server.world(this.player.dimension);
* if (!this.player.queuedEndExit) { // <---- Here is where we're injecting
* if (this.networkTickCount == 0) {
* this.captureCurrentPosition();
* }
* </pre>
* we can effectively short circuit the method to handle movement code where
* returning {@code true} will escape the packet being processed further entirely and
* {@code false} will allow the remaining processing of the method run.
*
* @param packetIn The movement packet
*/
@Inject(method = "handleMovePlayer", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;awaitingPositionFromClient:Lnet/minecraft/world/phys/Vec3;"), slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerPlayer;wonGame:Z"), to = @At(value = "FIELD", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;tickCount:I", ordinal = 1)), cancellable = true)
private void impl$callMoveEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) {
// If the movement is modified we pretend that the player has queuedEndExit = true
// so that vanilla wont process that packet further
final ServerboundMovePlayerPacketAccessor packetInAccessor = (ServerboundMovePlayerPacketAccessor) packetIn;
// We don't fire an event to avoid confusing plugins.
if (!packetInAccessor.accessor$hasPos() && !packetInAccessor.accessor$hasRot()) {
return;
}
final boolean goodMovementPacket = this.receivedMovePacketCount - this.knownMovePacketCount <= 5;
final boolean fireMoveEvent = goodMovementPacket && packetInAccessor.accessor$hasPos() && ShouldFire.MOVE_ENTITY_EVENT;
final boolean fireRotationEvent = goodMovementPacket && packetInAccessor.accessor$hasRot() && ShouldFire.ROTATE_ENTITY_EVENT;
final ServerPlayer player = (ServerPlayer) this.player;
final Vector3d fromRotation = new Vector3d(this.player.yRot, this.player.xRot, 0);
// Use the position of the last movement with an event or the current player position if never called
// We need this because we ignore very small position changes as to not spam as many move events.
final Vector3d fromPosition = player.position();
Vector3d toPosition = new Vector3d(packetIn.getX(this.player.getX()), packetIn.getY(this.player.getY()), packetIn.getZ(this.player.getZ()));
Vector3d toRotation = new Vector3d(packetIn.getYRot(this.player.yRot), packetIn.getXRot(this.player.xRot), 0);
final boolean significantRotation = fromRotation.distanceSquared(toRotation) > (.15f * .15f);
final Vector3d originalToPosition = toPosition;
boolean cancelMovement = false;
boolean cancelRotation = false;
// Call move & rotate event as needed...
if (fireMoveEvent) {
final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(PhaseTracker.getCauseStackManager().currentCause(), (ServerPlayer) this.player, fromPosition, toPosition, toPosition);
if (SpongeCommon.post(event)) {
cancelMovement = true;
} else {
toPosition = event.destinationPosition();
}
}
if (significantRotation && fireRotationEvent) {
final RotateEntityEvent event = SpongeEventFactory.createRotateEntityEvent(PhaseTracker.getCauseStackManager().currentCause(), (ServerPlayer) this.player, fromRotation, toRotation);
if (SpongeCommon.post(event)) {
cancelRotation = true;
toRotation = fromRotation;
} else {
toRotation = event.toRotation();
}
}
// player position and update the player's relation in the chunk manager.
if (cancelMovement) {
if (fromPosition.distanceSquared(toPosition) > 0) {
// Set the location, as if the player was teleporting
this.awaitingTeleportTime = this.tickCount;
this.shadow$teleport(fromPosition.x(), fromPosition.y(), fromPosition.z(), (float) toRotation.x(), (float) toRotation.y());
} else {
// If this is only rotation do not teleport back
this.player.absMoveTo(fromPosition.x(), fromPosition.y(), fromPosition.z(), (float) toRotation.x(), (float) toRotation.y());
}
ci.cancel();
return;
}
// Handle event results
if (!toPosition.equals(originalToPosition)) {
// Check if we have to say it's a "teleport" vs a standard move
final double d4 = packetIn.getX(this.player.getX());
final double d5 = packetIn.getY(this.player.getY());
final double d6 = packetIn.getZ(this.player.getZ());
final double d7 = d4 - this.firstGoodX;
final double d8 = d5 - this.firstGoodY;
final double d9 = d6 - this.firstGoodZ;
final double d10 = this.player.getDeltaMovement().lengthSqr();
final double d11 = d7 * d7 + d8 * d8 + d9 * d9;
final float f2 = this.player.isFallFlying() ? 300.0F : 100.0F;
final int i = this.receivedMovePacketCount - this.knownMovePacketCount;
if (d11 - d10 > (double) (f2 * (float) i) && !this.shadow$isSingleplayerOwner()) {
// At this point, we need to set the target position so the teleport code forces it
this.awaitingPositionFromClient = VecHelper.toVanillaVector3d(toPosition);
((EntityAccessor) this.player).invoker$setRot((float) toRotation.x(), (float) toRotation.y());
// And reset the position update so the force set is done.
this.awaitingTeleportTime = this.tickCount - Constants.Networking.MAGIC_TRIGGER_TELEPORT_CONFIRM_DIFF;
} else {
// otherwise, set the data back onto the packet
packetInAccessor.accessor$hasPos(true);
packetInAccessor.accessor$x(toPosition.x());
packetInAccessor.accessor$y(toPosition.y());
packetInAccessor.accessor$z(toPosition.z());
}
}
}
Aggregations