1515import net .minecraft .util .math .BlockPos ;
1616import net .minecraft .util .math .MathHelper ;
1717import net .minecraft .util .math .Vec3d ;
18+ import net .minecraft .world .World ;
1819import net .minecraft .world .WorldProviderEnd ;
1920import net .minecraft .world .WorldServer ;
2021import net .minecraft .world .end .DragonFightManager ;
2122import net .minecraftforge .common .ForgeHooks ;
2223import net .minecraftforge .common .util .FakePlayer ;
24+ import net .minecraftforge .common .util .ITeleporter ;
2325import net .minecraftforge .fml .common .FMLCommonHandler ;
2426
2527import java .lang .reflect .Field ;
@@ -134,9 +136,8 @@ public static Entity teleport(Entity entity, int newDimension, double x, double
134136 if (entity instanceof FakePlayer ) return entity ;
135137 if (entity .world .isRemote || entity .isDead ) return null ; // dead means inactive, not a dead player
136138
137- yaw = MathHelper .wrapDegrees (yaw );
138- pitch = MathHelper .wrapDegrees (pitch );
139-
139+ float adjustedYaw = MathHelper .wrapDegrees (yaw );
140+ float adjustedPitch = MathHelper .wrapDegrees (pitch );
140141 entity .dismountRidingEntity (); // TODO: would be nice to teleport them too
141142 entity .removePassengers ();
142143
@@ -147,139 +148,25 @@ public static Entity teleport(Entity entity, int newDimension, double x, double
147148 // Workaround for https://bugs.mojang.com/browse/MC-123364. Disables player-in-block checking, but doesn't seem
148149 // to make the player actually noclip.
149150 entity .noClip = true ;
150-
151- // Prevent Minecraft from cancelling the position change being too big if the player is not in creative
152- // This has to be done when the teleport is done from the player moved function (so any block collision event too)
153- // Not doing this will cause the player to be invisible for others.
154151 setInvulnerableDimensionChange ((EntityPlayerMP ) entity , true );
155152 }
156153
157154 if (oldDimension == newDimension ) { // Based on CommandTeleport.doTeleport
158155 if (entity instanceof EntityPlayerMP ) {
159156 EntityPlayerMP player = (EntityPlayerMP ) entity ;
160- player .connection .setPlayerLocation (x , y , z , yaw , pitch , EnumSet .noneOf (SPacketPlayerPosLook .EnumFlags .class ));
157+ player .connection .setPlayerLocation (x , y , z , adjustedYaw , adjustedPitch , EnumSet .noneOf (SPacketPlayerPosLook .EnumFlags .class ));
161158 // Fix for https://bugs.mojang.com/browse/MC-98153. See this comment: https://bugs.mojang.com/browse/MC-98153#comment-411524
162159 captureCurrentPosition (player .connection );
163160 } else {
164- entity .setLocationAndAngles (x , y , z , yaw , pitch );
161+ entity .setLocationAndAngles (x , y , z , adjustedYaw , adjustedPitch );
165162 }
166- entity .setRotationYawHead (yaw );
167-
168- return entity ;
169- } else { // Based on Entity.changeDimension
170- MinecraftServer server = entity .getServer ();
171- WorldServer oldWorld = server .getWorld (oldDimension );
172- WorldServer newWorld = server .getWorld (newDimension );
173-
174- // Allow other mods to cancel the event
175- if (!ForgeHooks .onTravelToDimension (entity , newDimension )) return entity ;
176-
177- if (entity instanceof EntityPlayerMP ) {
178- EntityPlayerMP player = (EntityPlayerMP ) entity ;
179-
180- // Setting this field seems to be useful for advancments. Adjusted dimension checks for non-vanilla
181- // dimension support (entering the nether from any dimension should trigger it now).
182- if (newDimension == -1 ) {
183- setEnteredNetherPosition (player , new Vec3d (player .posX , player .posY , player .posZ ));
184- } else if (oldDimension != -1 && newDimension != 0 ) {
185- setEnteredNetherPosition (player , null );
186- }
187-
188- // Send respawn packets to the player
189- player .dimension = newDimension ;
190- player .connection .sendPacket (new SPacketRespawn (player .dimension , newWorld .getDifficulty (), newWorld .getWorldInfo ().getTerrainType (), player .interactionManager .getGameType ()));
191- player .server .getPlayerList ().updatePermissionLevel (player ); // Sends an SPacketEntityStatus
192-
193- // Remove player entity from the old world
194- oldWorld .removeEntityDangerously (player );
195-
196- // Move the player entity to new world
197- // We can't use PlayerList.transferEntityToWorld since for newDimension = 1, that would first teleport the
198- // player to the dimension's spawn before quickly teleporting the player to the correct position. Unlike the vanilla
199- // code, we don't use the world provider's moveFactor (ex. 8 blocks in the nether) and don't clip to the
200- // world border.
201- player .isDead = false ;
202- oldWorld .profiler .startSection ("moving" );
203- player .setLocationAndAngles (x , y , z , yaw , pitch );
204- // PlayerList.transferEntityToWorld does this for some reason when teleporting to the end, but it doesn't
205- // make any sense (without it, there seems to be some flickering between two positions):
206- if (entity .isEntityAlive ()) oldWorld .updateEntityWithOptionalForce (entity , false );
207- oldWorld .profiler .endSection ();
208-
209- oldWorld .profiler .startSection ("placing" );
210- newWorld .spawnEntity (player );
211- newWorld .updateEntityWithOptionalForce (player , false );
212- oldWorld .profiler .endSection ();
213- player .setWorld (newWorld );
214-
215- // Sync the player
216- player .server .getPlayerList ().preparePlayer (player , oldWorld );
217- player .connection .setPlayerLocation (player .posX , player .posY , player .posZ , player .rotationYaw , player .rotationPitch );
218- // Fix for https://bugs.mojang.com/browse/MC-98153. See this comment: https://bugs.mojang.com/browse/MC-98153#comment-411524
219- captureCurrentPosition (player .connection );
220- player .interactionManager .setWorld (newWorld );
221- player .connection .sendPacket (new SPacketPlayerAbilities (player .capabilities ));
222- player .server .getPlayerList ().updateTimeAndWeatherForPlayer (player , newWorld );
223- player .server .getPlayerList ().syncPlayerInventory (player );
224- for (PotionEffect potioneffect : player .getActivePotionEffects ()) {
225- player .connection .sendPacket (new SPacketEntityEffect (player .getEntityId (), potioneffect ));
226- }
227163
228- // Force WorldProviderEnd to check if end dragon bars should be removed. Duplicate end dragon bars even
229- // happen when leaving the end using an end portal while the dragon is alive, so this might be a vanilla
230- // or Forge bug (maybe the world is unloaded before checking players?). In vanilla, updateplayers is normally
231- // called every second.
232- if (oldWorld .provider instanceof WorldProviderEnd ) {
233- DragonFightManager dragonFightManager = ((WorldProviderEnd ) oldWorld .provider ).getDragonFightManager ();
234- updateplayers (dragonFightManager );
235- }
164+ entity .setRotationYawHead (adjustedYaw );
236165
237- // Vanilla also plays SoundEvents.BLOCK_PORTAL_TRAVEL, we won't do this.
238-
239- FMLCommonHandler .instance ().firePlayerChangedDimensionEvent (player , oldDimension , newDimension );
240-
241- //player.prevBlockpos = null; // For frost walk. Is this needed? What about other fields?
242- /*player.lastExperience = -1;
243- player.lastHealth = -1.0F;
244- player.lastFoodLevel = -1;*/
245-
246- return entity ;
247- } else {
248- if (entity instanceof EntityMinecartContainer ) ((EntityMinecartContainer ) entity ).dropContentsWhenDead = false ;
249- if (entity instanceof EntityEnderPearl ) setThrower ((EntityThrowable ) entity , null ); // Otherwise the player will be teleported to the hit position but in the same dimension
250-
251- entity .world .profiler .startSection ("changeDimension" );
252- entity .dimension = newDimension ;
253- entity .world .removeEntity (entity );
254- entity .isDead = false ;
255-
256- entity .world .profiler .startSection ("reposition" );
257- oldWorld .updateEntityWithOptionalForce (entity , false );
258-
259- entity .world .profiler .endStartSection ("reloading" );
260- Entity newEntity = EntityList .newEntity (entity .getClass (), newWorld );
261-
262- if (newEntity != null ) {
263- copyDataFromOld (newEntity , entity );
264- newEntity .setPositionAndRotation (x , y , z , yaw , pitch );
265- boolean oldForceSpawn = newEntity .forceSpawn ;
266- newEntity .forceSpawn = true ;
267- newWorld .spawnEntity (newEntity );
268- newEntity .forceSpawn = oldForceSpawn ;
269- newWorld .updateEntityWithOptionalForce (newEntity , false );
270- }
271-
272- entity .isDead = true ;
273- entity .world .profiler .endSection ();
274-
275- oldWorld .resetUpdateEntityTick ();
276- newWorld .resetUpdateEntityTick ();
277- entity .world .profiler .endSection ();
278-
279- if (newEntity instanceof EntityItem ) searchForOtherItemsNearby ((EntityItem ) newEntity ); // TODO: This isn't in same-dimension teleportation in vanilla, but why?
280-
281- return newEntity ;
282- }
166+ return entity ;
167+ } else {
168+ entity .changeDimension (newDimension , (w , e , newYaw ) -> e .moveToBlockPosAndAngles (new BlockPos (x , y , z ), adjustedYaw , adjustedPitch ));
169+ return entity ;
283170 }
284171 }
285172}
0 commit comments