|
24 | 24 | */ |
25 | 25 | package org.spongepowered.common.mixin.core.server.commands; |
26 | 26 |
|
27 | | -import net.minecraft.commands.CommandSourceStack; |
28 | | -import net.minecraft.core.BlockPos; |
29 | | -import net.minecraft.server.commands.LookAt; |
| 27 | +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; |
| 28 | +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; |
30 | 29 | import net.minecraft.server.commands.TeleportCommand; |
31 | 30 | import net.minecraft.server.level.ServerLevel; |
32 | | -import net.minecraft.server.level.ServerPlayer; |
33 | | -import net.minecraft.server.level.TicketType; |
34 | | -import net.minecraft.util.Mth; |
35 | 31 | import net.minecraft.world.entity.Entity; |
36 | | -import net.minecraft.world.entity.EntitySpawnReason; |
37 | | -import net.minecraft.world.entity.LivingEntity; |
38 | | -import net.minecraft.world.entity.PathfinderMob; |
39 | | -import net.minecraft.world.entity.PositionMoveRotation; |
40 | 32 | import net.minecraft.world.entity.Relative; |
41 | | -import net.minecraft.world.level.ChunkPos; |
42 | | -import net.minecraft.world.phys.Vec3; |
43 | | -import org.checkerframework.checker.nullness.qual.Nullable; |
44 | | -import org.spongepowered.api.Sponge; |
45 | 33 | import org.spongepowered.api.event.CauseStackManager; |
46 | 34 | import org.spongepowered.api.event.EventContextKeys; |
47 | | -import org.spongepowered.api.event.SpongeEventFactory; |
48 | 35 | import org.spongepowered.api.event.cause.entity.MovementTypes; |
49 | | -import org.spongepowered.api.event.entity.ChangeEntityWorldEvent; |
50 | | -import org.spongepowered.api.event.entity.MoveEntityEvent; |
51 | | -import org.spongepowered.api.event.entity.RotateEntityEvent; |
52 | | -import org.spongepowered.api.world.server.ServerWorld; |
53 | 36 | import org.spongepowered.asm.mixin.Mixin; |
54 | | -import org.spongepowered.asm.mixin.Overwrite; |
55 | | -import org.spongepowered.common.SpongeCommon; |
56 | | -import org.spongepowered.common.event.ShouldFire; |
| 37 | +import org.spongepowered.asm.mixin.injection.At; |
57 | 38 | import org.spongepowered.common.event.tracking.PhaseTracker; |
58 | | -import org.spongepowered.common.hooks.PlatformHooks; |
59 | | -import org.spongepowered.common.util.VecHelper; |
60 | | -import org.spongepowered.math.vector.Vector3d; |
61 | 39 |
|
62 | 40 | import java.util.Set; |
63 | 41 |
|
64 | 42 | @Mixin(TeleportCommand.class) |
65 | 43 | public abstract class TeleportCommandMixin { |
66 | 44 |
|
67 | | - /** |
68 | | - * @author Zidane |
69 | | - * @reason Have the teleport command respect our events |
70 | | - */ |
71 | | - @Overwrite |
72 | | - // TODO check if this is still correct - check if we can get rid of the overwrite |
73 | | - private static void performTeleport(CommandSourceStack source, Entity entityIn, ServerLevel worldIn, double x, double y, double z, |
74 | | - Set<Relative> relativeList, float yaw, float pitch, @Nullable LookAt facing) { |
75 | | - |
76 | | - double actualX = x; |
77 | | - double actualY = y; |
78 | | - double actualZ = z; |
79 | | - double actualYaw = yaw; |
80 | | - double actualPitch = pitch; |
81 | | - |
82 | | - if (!(entityIn instanceof ServerPlayer)) { |
83 | | - actualYaw = Mth.wrapDegrees(yaw); |
84 | | - actualPitch = Mth.wrapDegrees(pitch); |
85 | | - actualPitch = Mth.clamp(actualPitch, -90.0F, 90.0F); |
86 | | - } |
87 | | - |
88 | | - if (worldIn == entityIn.level()) { |
89 | | - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { |
90 | | - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); |
91 | | - |
92 | | - // TODO Should honor the relative list before the event.. |
93 | | - |
94 | | - if (ShouldFire.MOVE_ENTITY_EVENT) { |
95 | | - final MoveEntityEvent posEvent = SpongeEventFactory.createMoveEntityEvent(frame.currentCause(), |
96 | | - (org.spongepowered.api.entity.Entity) entityIn, VecHelper.toVector3d(entityIn.position()), |
97 | | - new Vector3d(x, y, z), new Vector3d(x, y, z)); |
98 | | - |
99 | | - if (SpongeCommon.post(posEvent)) { |
100 | | - return; |
101 | | - } |
102 | | - |
103 | | - actualX = posEvent.destinationPosition().x(); |
104 | | - actualY = posEvent.destinationPosition().y(); |
105 | | - actualZ = posEvent.destinationPosition().z(); |
106 | | - } |
107 | | - |
108 | | - if (ShouldFire.ROTATE_ENTITY_EVENT) { |
109 | | - final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), |
110 | | - (org.spongepowered.api.entity.Entity) entityIn, new Vector3d(actualPitch, actualYaw, 0), |
111 | | - new Vector3d(pitch, yaw, 0)); |
112 | | - |
113 | | - SpongeCommon.post(rotateEvent); |
114 | | - actualYaw = rotateEvent.isCancelled() ? entityIn.getYRot() : rotateEvent.toRotation().y(); |
115 | | - actualPitch = rotateEvent.isCancelled() ? entityIn.getXRot() : rotateEvent.toRotation().x(); |
116 | | - } |
117 | | - |
118 | | - if (entityIn instanceof ServerPlayer sp) { |
119 | | - |
120 | | - ChunkPos chunkpos = new ChunkPos(new BlockPos((int) actualX, (int) actualY, (int) actualZ)); |
121 | | - worldIn.getChunkSource().addRegionTicket(TicketType.FORCED, chunkpos, 1, chunkpos); |
122 | | - |
123 | | - entityIn.stopRiding(); |
124 | | - |
125 | | - if (sp.isSleeping()) { |
126 | | - sp.stopSleepInBed(true, true); |
127 | | - } |
128 | | - |
129 | | - sp.connection.teleport( |
130 | | - new PositionMoveRotation(new Vec3( actualX, actualY, actualZ), Vec3.ZERO, (float) actualYaw, (float) actualPitch), relativeList); |
131 | | - } else { |
132 | | - entityIn.moveTo(actualX, actualY, actualZ, (float) actualYaw, (float) actualPitch); |
133 | | - } |
134 | | - |
135 | | - entityIn.setYHeadRot((float) actualYaw); |
136 | | - } |
137 | | - } else { |
138 | | - if (entityIn instanceof ServerPlayer sp) { |
139 | | - // To ensure mod code is caught, handling the world change for players happens in teleport |
140 | | - // Teleport will create a frame but we want to ensure it'll be the command movement type |
141 | | - // TODO check if this is still correct |
142 | | - PhaseTracker.getInstance().addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); |
143 | | - sp.teleportTo(worldIn, x, y, z, relativeList, yaw, pitch, true); |
144 | | - PhaseTracker.getInstance().removeContext(EventContextKeys.MOVEMENT_TYPE); |
145 | | - } else { |
146 | | - try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { |
147 | | - frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); |
148 | | - |
149 | | - final ServerLevel fromWorld = (ServerLevel) entityIn.getCommandSenderWorld(); |
150 | | - |
151 | | - final ChangeEntityWorldEvent.Pre preEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre(entityIn, |
152 | | - worldIn); |
153 | | - if (SpongeCommon.post(preEvent)) { |
154 | | - return; |
155 | | - } |
156 | | - |
157 | | - final ChangeEntityWorldEvent.Reposition posEvent = |
158 | | - SpongeEventFactory.createChangeEntityWorldEventReposition(frame.currentCause(), |
159 | | - (org.spongepowered.api.entity.Entity) entityIn, |
160 | | - (org.spongepowered.api.world.server.ServerWorld) entityIn.getCommandSenderWorld(), |
161 | | - VecHelper.toVector3d(entityIn.position()), new Vector3d(x, y, z), preEvent.originalDestinationWorld(), |
162 | | - new Vector3d(x, y, z), preEvent.destinationWorld()); |
163 | | - |
164 | | - if (SpongeCommon.post(posEvent)) { |
165 | | - return; |
166 | | - } |
167 | | - |
168 | | - entityIn.unRide(); |
169 | | - final Entity result = entityIn.getType().create(worldIn, EntitySpawnReason.DIMENSION_TRAVEL); |
170 | | - if (result == null) { |
171 | | - return; |
172 | | - } |
173 | | - |
174 | | - if (ShouldFire.ROTATE_ENTITY_EVENT) { |
175 | | - final RotateEntityEvent rotateEvent = SpongeEventFactory.createRotateEntityEvent(frame.currentCause(), |
176 | | - (org.spongepowered.api.entity.Entity) entityIn, new Vector3d(entityIn.getXRot(), entityIn.getYRot(), 0), |
177 | | - new Vector3d(actualPitch, actualYaw, 0)); |
178 | | - |
179 | | - if (!SpongeCommon.post(rotateEvent)) { |
180 | | - actualYaw = Mth.wrapDegrees(rotateEvent.toRotation().y()); |
181 | | - actualPitch = Mth.wrapDegrees(rotateEvent.toRotation().x()); |
182 | | - actualPitch = Mth.clamp(actualPitch, -90.0F, 90.0F); |
183 | | - } else { |
184 | | - actualYaw = entityIn.getYRot(); |
185 | | - actualPitch = entityIn.getXRot(); |
186 | | - } |
187 | | - } |
188 | | - |
189 | | - result.restoreFrom(entityIn); |
190 | | - result.moveTo(posEvent.destinationPosition().x(), posEvent.destinationPosition().y(), |
191 | | - posEvent.destinationPosition().z(), (float) actualYaw, (float) actualPitch); |
192 | | - result.setYHeadRot((float) actualYaw); |
193 | | - worldIn.addDuringTeleport(result); |
194 | | - entityIn.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); |
195 | | - |
196 | | - Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost( |
197 | | - PhaseTracker.getInstance().currentCause(), |
198 | | - (org.spongepowered.api.entity.Entity) result, |
199 | | - (ServerWorld) fromWorld, |
200 | | - preEvent.originalDestinationWorld(), |
201 | | - preEvent.destinationWorld() |
202 | | - )); |
203 | | - } |
204 | | - } |
205 | | - } |
206 | | - |
207 | | - if (facing != null) { |
208 | | - facing.perform(source, entityIn); |
209 | | - } |
210 | | - |
211 | | - if (!(entityIn instanceof LivingEntity) || !((LivingEntity)entityIn).isFallFlying()) { |
212 | | - entityIn.setDeltaMovement(entityIn.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); |
213 | | - entityIn.setOnGround(true); |
214 | | - } |
215 | | - |
216 | | - if (entityIn instanceof PathfinderMob) { |
217 | | - ((PathfinderMob)entityIn).getNavigation().stop(); |
| 45 | + @WrapOperation(method = "performTeleport", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FFZ)Z")) |
| 46 | + private static boolean impl$createCauseFrameForPerformTeleport( |
| 47 | + final Entity instance, final ServerLevel level, final double x, final double y, final double z, |
| 48 | + final Set<Relative> relativeMovements, final float yRot, final float xRot, final boolean setCamera, final Operation<Boolean> original) { |
| 49 | + try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) { |
| 50 | + frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.COMMAND); |
| 51 | + return original.call(instance, level, x, y, z, relativeMovements, yRot, xRot, setCamera); |
218 | 52 | } |
219 | 53 | } |
220 | 54 | } |
0 commit comments