use of net.minecraft.server.management.DemoPlayerInteractionManager in project SpongeCommon by SpongePowered.
the class MixinPlayerList method recreatePlayerEntity.
/**
* @author Zidane - June 13th, 2015
* @author simon816 - June 24th, 2015
* @author Zidane - March 29th, 2016
* @author gabizou - June 5th, 2016 - Update for teleportation changes to keep the same player.
*
* @reason - Direct respawning players to use Sponge events
* and process appropriately.
*
* @param playerIn The player being respawned/created
* @param targetDimension The target dimension
* @param conqueredEnd Whether the end was conquered
* @return The new player
*/
@Overwrite
public EntityPlayerMP recreatePlayerEntity(EntityPlayerMP playerIn, int targetDimension, boolean conqueredEnd) {
// UNLESS comming back from the end.
if (!conqueredEnd && targetDimension == 0) {
targetDimension = playerIn.dimension;
}
if (playerIn.isBeingRidden()) {
playerIn.removePassengers();
}
if (playerIn.isRiding()) {
playerIn.dismountRidingEntity();
}
final Player player = (Player) playerIn;
final Transform<World> fromTransform = player.getTransform();
WorldServer worldServer = this.mcServer.getWorld(targetDimension);
Transform<World> toTransform = new Transform<>(EntityUtil.getPlayerRespawnLocation(playerIn, worldServer), Vector3d.ZERO, Vector3d.ZERO);
targetDimension = ((IMixinWorldServer) toTransform.getExtent()).getDimensionId();
Location<World> location = toTransform.getLocation();
// If coming from end, fire a teleport event for plugins
if (conqueredEnd) {
// When leaving the end, players are never placed inside the teleporter but instead "respawned" in the target world
MoveEntityEvent.Teleport teleportEvent = EntityUtil.handleDisplaceEntityTeleportEvent(playerIn, location);
if (teleportEvent.isCancelled()) {
playerIn.queuedEndExit = false;
return playerIn;
}
toTransform = teleportEvent.getToTransform();
location = toTransform.getLocation();
}
// Keep players out of blocks
Vector3d tempPos = player.getLocation().getPosition();
playerIn.setPosition(location.getX(), location.getY(), location.getZ());
while (!((WorldServer) location.getExtent()).getCollisionBoxes(playerIn, playerIn.getEntityBoundingBox()).isEmpty()) {
playerIn.setPosition(playerIn.posX, playerIn.posY + 1.0D, playerIn.posZ);
location = location.add(0, 1, 0);
}
playerIn.setPosition(tempPos.getX(), tempPos.getY(), tempPos.getZ());
// ### PHASE 2 ### Remove player from current dimension
playerIn.getServerWorld().getEntityTracker().removePlayerFromTrackers(playerIn);
playerIn.getServerWorld().getEntityTracker().untrack(playerIn);
playerIn.getServerWorld().getPlayerChunkMap().removePlayer(playerIn);
this.playerEntityList.remove(playerIn);
this.mcServer.getWorld(playerIn.dimension).removeEntityDangerously(playerIn);
final BlockPos bedPos = SpongeImplHooks.getBedLocation(playerIn, targetDimension);
// ### PHASE 3 ### Reset player (if applicable)
// Recreate the player object in order to support Forge's PlayerEvent.Clone
PlayerInteractionManager playerinteractionmanager;
if (this.mcServer.isDemo()) {
playerinteractionmanager = new DemoPlayerInteractionManager(this.mcServer.getWorld(targetDimension));
} else {
playerinteractionmanager = new PlayerInteractionManager(this.mcServer.getWorld(targetDimension));
}
EntityPlayerMP newPlayer = new EntityPlayerMP(SpongeImpl.getServer(), worldServer, playerIn.getGameProfile(), playerinteractionmanager);
newPlayer.connection = playerIn.connection;
newPlayer.copyFrom(playerIn, conqueredEnd);
// set player dimension for RespawnPlayerEvent
newPlayer.dimension = targetDimension;
newPlayer.setEntityId(playerIn.getEntityId());
newPlayer.setCommandStats(playerIn);
newPlayer.setPrimaryHand(playerIn.getPrimaryHand());
// over to the new player
if (bedPos != null) {
newPlayer.setSpawnPoint(bedPos, playerIn.isSpawnForced());
}
for (String s : playerIn.getTags()) {
newPlayer.addTag(s);
}
this.setPlayerGameTypeBasedOnOther(newPlayer, playerIn, worldServer);
newPlayer.setSneaking(false);
// update to safe location
toTransform = toTransform.setLocation(location);
// ### PHASE 4 ### Fire event and set new location on the player
Sponge.getCauseStackManager().pushCause(newPlayer);
final RespawnPlayerEvent event = SpongeEventFactory.createRespawnPlayerEvent(Sponge.getCauseStackManager().getCurrentCause(), fromTransform, toTransform, (Player) playerIn, (Player) newPlayer, EntityUtil.tempIsBedSpawn, !conqueredEnd);
EntityUtil.tempIsBedSpawn = false;
SpongeImpl.postEvent(event);
Sponge.getCauseStackManager().popCause();
((IMixinEntity) player).setLocationAndAngles(event.getToTransform());
toTransform = event.getToTransform();
location = toTransform.getLocation();
if (!(location.getExtent() instanceof WorldServer)) {
SpongeImpl.getLogger().warn("Location set in PlayerRespawnEvent was invalid, using original location instead");
location = event.getFromTransform().getLocation();
}
worldServer = (WorldServer) location.getExtent();
final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) worldServer;
// Set the dimension again in case a plugin changed the target world during RespawnPlayerEvent
newPlayer.dimension = mixinWorldServer.getDimensionId();
newPlayer.setWorld(worldServer);
newPlayer.interactionManager.setWorld(worldServer);
worldServer.getChunkProvider().loadChunk((int) location.getX() >> 4, (int) location.getZ() >> 4);
// ### PHASE 5 ### Respawn player in new world
// Support vanilla clients logging into custom dimensions
final int dimensionId = WorldManager.getClientDimensionId(newPlayer, worldServer);
// Send dimension registration
if (((IMixinEntityPlayerMP) newPlayer).usesCustomClient()) {
WorldManager.sendDimensionRegistration(newPlayer, worldServer.provider);
} else {
// Force vanilla client to refresh its chunk cache if same dimension type
if (fromTransform.getExtent() != worldServer && fromTransform.getExtent().getDimension().getType() == toTransform.getExtent().getDimension().getType()) {
newPlayer.connection.sendPacket(new SPacketRespawn((dimensionId >= 0 ? -1 : 0), worldServer.getDifficulty(), worldServer.getWorldInfo().getTerrainType(), newPlayer.interactionManager.getGameType()));
}
}
newPlayer.connection.sendPacket(new SPacketRespawn(dimensionId, worldServer.getDifficulty(), worldServer.getWorldInfo().getTerrainType(), newPlayer.interactionManager.getGameType()));
newPlayer.connection.setPlayerLocation(location.getX(), location.getY(), location.getZ(), (float) toTransform.getYaw(), (float) toTransform.getPitch());
final BlockPos spawnLocation = worldServer.getSpawnPoint();
newPlayer.connection.sendPacket(new SPacketSpawnPosition(spawnLocation));
newPlayer.connection.sendPacket(new SPacketSetExperience(newPlayer.experience, newPlayer.experienceTotal, newPlayer.experienceLevel));
this.updateTimeAndWeatherForPlayer(newPlayer, worldServer);
this.updatePermissionLevel(newPlayer);
worldServer.getPlayerChunkMap().addPlayer(newPlayer);
org.spongepowered.api.entity.Entity spongeEntity = (org.spongepowered.api.entity.Entity) newPlayer;
((org.spongepowered.api.world.World) worldServer).spawnEntity(spongeEntity);
this.playerEntityList.add(newPlayer);
this.uuidToPlayerMap.put(newPlayer.getUniqueID(), newPlayer);
newPlayer.addSelfToInternalCraftingInventory();
// Update reducedDebugInfo game rule
newPlayer.connection.sendPacket(new SPacketEntityStatus(newPlayer, worldServer.getGameRules().getBoolean(DefaultGameRules.REDUCED_DEBUG_INFO) ? (byte) 22 : 23));
for (PotionEffect potioneffect : newPlayer.getActivePotionEffects()) {
newPlayer.connection.sendPacket(new SPacketEntityEffect(newPlayer.getEntityId(), potioneffect));
}
((IMixinEntityPlayerMP) newPlayer).refreshScaledHealth();
return newPlayer;
}
Aggregations