use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.
the class EntityUtil method transferPlayerToDimension.
// Used by PlayerList#transferPlayerToDimension and EntityPlayerMP#changeDimension.
// This method should NOT fire a teleport event as that should always be handled by the caller.
public static void transferPlayerToDimension(MoveEntityEvent.Teleport.Portal event, EntityPlayerMP playerIn) {
WorldServer fromWorld = (WorldServer) event.getFromTransform().getExtent();
WorldServer toWorld = (WorldServer) event.getToTransform().getExtent();
playerIn.dimension = WorldManager.getClientDimensionId(playerIn, toWorld);
toWorld.getChunkProvider().loadChunk(event.getToTransform().getLocation().getChunkPosition().getX(), event.getToTransform().getLocation().getChunkPosition().getZ());
// Support vanilla clients teleporting to custom dimensions
final int dimensionId = playerIn.dimension;
// Send dimension registration
if (((IMixinEntityPlayerMP) playerIn).usesCustomClient()) {
WorldManager.sendDimensionRegistration(playerIn, toWorld.provider);
} else {
// Force vanilla client to refresh its chunk cache if same dimension type
if (fromWorld != toWorld && fromWorld.provider.getDimensionType() == toWorld.provider.getDimensionType()) {
playerIn.connection.sendPacket(new SPacketRespawn((dimensionId >= 0 ? -1 : 0), toWorld.getDifficulty(), toWorld.getWorldInfo().getTerrainType(), playerIn.interactionManager.getGameType()));
}
}
playerIn.connection.sendPacket(new SPacketRespawn(dimensionId, toWorld.getDifficulty(), toWorld.getWorldInfo().getTerrainType(), playerIn.interactionManager.getGameType()));
fromWorld.removeEntityDangerously(playerIn);
playerIn.isDead = false;
// we do not need to call transferEntityToWorld as we already have the correct transform and created the portal in handleDisplaceEntityPortalEvent
((IMixinEntity) playerIn).setLocationAndAngles(event.getToTransform());
playerIn.setWorld(toWorld);
toWorld.spawnEntity(playerIn);
toWorld.updateEntityWithOptionalForce(playerIn, false);
SpongeImpl.getServer().getPlayerList().preparePlayer(playerIn, fromWorld);
playerIn.connection.setPlayerLocation(playerIn.posX, playerIn.posY, playerIn.posZ, playerIn.rotationYaw, playerIn.rotationPitch);
playerIn.interactionManager.setWorld(toWorld);
SpongeImpl.getServer().getPlayerList().updateTimeAndWeatherForPlayer(playerIn, toWorld);
SpongeImpl.getServer().getPlayerList().syncPlayerInventory(playerIn);
// Update reducedDebugInfo game rule
playerIn.connection.sendPacket(new SPacketEntityStatus(playerIn, toWorld.getGameRules().getBoolean(DefaultGameRules.REDUCED_DEBUG_INFO) ? (byte) 22 : 23));
for (PotionEffect potioneffect : playerIn.getActivePotionEffects()) {
playerIn.connection.sendPacket(new SPacketEntityEffect(playerIn.getEntityId(), potioneffect));
}
((IMixinEntityPlayerMP) playerIn).refreshXpHealthAndFood();
SpongeImplHooks.handlePostChangeDimensionEvent(playerIn, fromWorld, toWorld);
}
use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.
the class EntityUtil method handleDisplaceEntityTeleportEvent.
public static MoveEntityEvent.Teleport handleDisplaceEntityTeleportEvent(Entity entityIn, double posX, double posY, double posZ, float yaw, float pitch) {
Transform<World> fromTransform = ((IMixinEntity) entityIn).getTransform();
Transform<World> toTransform = fromTransform.setPosition(new Vector3d(posX, posY, posZ)).setRotation(new Vector3d(pitch, yaw, 0));
return handleDisplaceEntityTeleportEvent(entityIn, fromTransform, toTransform, false);
}
use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.
the class EntityUtil method handleDisplaceEntityPortalEvent.
@Nullable
public static MoveEntityEvent.Teleport.Portal handleDisplaceEntityPortalEvent(Entity entityIn, int targetDimensionId, @Nullable Teleporter teleporter) {
SpongeImplHooks.registerPortalAgentType(teleporter);
final MinecraftServer mcServer = SpongeImpl.getServer();
final IMixinPlayerList mixinPlayerList = (IMixinPlayerList) mcServer.getPlayerList();
final IMixinEntity mixinEntity = (IMixinEntity) entityIn;
final Transform<World> fromTransform = mixinEntity.getTransform();
final WorldServer fromWorld = ((WorldServer) entityIn.world);
final IMixinWorldServer fromMixinWorld = (IMixinWorldServer) fromWorld;
boolean sameDimension = entityIn.dimension == targetDimensionId;
// handle the end
if (targetDimensionId == 1 && fromWorld.provider instanceof WorldProviderEnd) {
targetDimensionId = 0;
}
WorldServer toWorld = mcServer.getWorld(targetDimensionId);
// not being loaded then short-circuit to prevent unnecessary logic from running
if (!sameDimension && fromWorld == toWorld) {
return null;
}
if (teleporter == null) {
teleporter = toWorld.getDefaultTeleporter();
}
final Map<String, String> portalAgents = fromMixinWorld.getActiveConfig().getConfig().getWorld().getPortalAgents();
String worldName = "";
String teleporterClassName = teleporter.getClass().getName();
// check for new destination in config
if (teleporterClassName.equals("net.minecraft.world.Teleporter")) {
worldName = portalAgents.get("minecraft:default_" + toWorld.provider.getDimensionType().getName().toLowerCase(Locale.ENGLISH));
if (worldName == null && toWorld.provider instanceof WorldProviderHell) {
worldName = portalAgents.get("minecraft:default_nether");
}
} else {
// custom
worldName = portalAgents.get("minecraft:" + teleporter.getClass().getSimpleName());
}
if (worldName != null && !worldName.equals("")) {
for (WorldProperties worldProperties : Sponge.getServer().getAllWorldProperties()) {
if (worldProperties.getWorldName().equalsIgnoreCase(worldName)) {
Optional<World> spongeWorld = Sponge.getServer().loadWorld(worldProperties);
if (spongeWorld.isPresent()) {
toWorld = (WorldServer) spongeWorld.get();
teleporter = toWorld.getDefaultTeleporter();
if (fromWorld.provider.isNether() || toWorld.provider.isNether()) {
((IMixinTeleporter) teleporter).setNetherPortalType(true);
} else {
((IMixinTeleporter) teleporter).setNetherPortalType(false);
}
}
}
}
}
adjustEntityPostionForTeleport(mixinPlayerList, entityIn, fromWorld, toWorld);
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame();
TeleportingContext context = EntityPhase.State.CHANGING_DIMENSION.createPhaseContext().setTargetWorld(toWorld).buildAndSwitch()) {
Sponge.getCauseStackManager().pushCause(teleporter);
Sponge.getCauseStackManager().pushCause(mixinEntity);
Sponge.getCauseStackManager().addContext(EventContextKeys.TELEPORT_TYPE, TeleportTypes.PORTAL);
if (entityIn.isEntityAlive() && !(fromWorld.provider instanceof WorldProviderEnd)) {
fromWorld.profiler.startSection("placing");
// Note: We must always use placeInPortal to support mods.
if (!((IMixinTeleporter) teleporter).isVanilla() || entityIn.getLastPortalVec() != null) {
teleporter.placeInPortal(entityIn, entityIn.rotationYaw);
}
fromWorld.profiler.endSection();
}
// Complete phases, just because we need to. The phases don't actually do anything, because the processing resides here.
// Grab the exit location of entity after being placed into portal
final Transform<World> portalExitTransform = mixinEntity.getTransform().setExtent((World) toWorld);
// Use setLocationAndAngles to avoid firing MoveEntityEvent to plugins
mixinEntity.setLocationAndAngles(fromTransform);
final MoveEntityEvent.Teleport.Portal event = SpongeEventFactory.createMoveEntityEventTeleportPortal(Sponge.getCauseStackManager().getCurrentCause(), fromTransform, portalExitTransform, (PortalAgent) teleporter, mixinEntity, true);
SpongeImpl.postEvent(event);
final Vector3i chunkPosition = mixinEntity.getLocation().getChunkPosition();
final IMixinTeleporter toMixinTeleporter = (IMixinTeleporter) teleporter;
final List<BlockSnapshot> capturedBlocks = context.getCapturedBlocks();
final Transform<World> toTransform = event.getToTransform();
if (event.isCancelled()) {
// We need to make sure to only restore the location if
if (!portalExitTransform.getExtent().getUniqueId().equals(mixinEntity.getLocation().getExtent().getUniqueId())) {
// update cache
((IMixinTeleporter) teleporter).removePortalPositionFromCache(ChunkPos.asLong(chunkPosition.getX(), chunkPosition.getZ()));
if (!capturedBlocks.isEmpty()) {
for (BlockSnapshot original : Lists.reverse(capturedBlocks)) {
original.restore(true, BlockChangeFlags.NONE);
}
capturedBlocks.clear();
}
mixinEntity.setLocationAndAngles(fromTransform);
} else {
// Call setTransform to let plugins know mods changed the position
// Guarantees plugins such as Nucleus can track changed locations properly
mixinEntity.setTransform(mixinEntity.getTransform());
}
return event;
}
if (!portalExitTransform.equals(toTransform)) {
// if plugin set to same world, just set the transform
if (fromWorld == toTransform.getExtent()) {
// force cancel so we know to skip remaining logic
event.setCancelled(true);
// update cache
toMixinTeleporter.removePortalPositionFromCache(ChunkPos.asLong(chunkPosition.getX(), chunkPosition.getZ()));
// Undo created portal
if (!capturedBlocks.isEmpty()) {
for (BlockSnapshot original : Lists.reverse(capturedBlocks)) {
original.restore(true, BlockChangeFlags.NONE);
}
}
capturedBlocks.clear();
mixinEntity.setLocationAndAngles(toTransform);
return event;
}
} else {
if (toWorld.provider instanceof WorldProviderEnd) {
BlockPos blockpos = entityIn.world.getTopSolidOrLiquidBlock(toWorld.getSpawnPoint());
entityIn.moveToBlockPosAndAngles(blockpos, entityIn.rotationYaw, entityIn.rotationPitch);
}
}
if (!capturedBlocks.isEmpty() && !TrackingUtil.processBlockCaptures(capturedBlocks, EntityPhase.State.CHANGING_DIMENSION, context)) {
toMixinTeleporter.removePortalPositionFromCache(ChunkPos.asLong(chunkPosition.getX(), chunkPosition.getZ()));
}
if (!event.getKeepsVelocity()) {
entityIn.motionX = 0;
entityIn.motionY = 0;
entityIn.motionZ = 0;
}
return event;
}
}
use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.
the class EntityUtil method handleDisplaceEntityTeleportEvent.
public static MoveEntityEvent.Teleport handleDisplaceEntityTeleportEvent(Entity entityIn, Location<World> location) {
Transform<World> fromTransform = ((IMixinEntity) entityIn).getTransform();
Transform<World> toTransform = fromTransform.setLocation(location).setRotation(new Vector3d(entityIn.rotationPitch, entityIn.rotationYaw, 0));
return handleDisplaceEntityTeleportEvent(entityIn, fromTransform, toTransform, false);
}
use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.
the class EntityUtil method transferEntityToDimension.
/**
* Called specifically from {@link MixinEntity#changeDimension(int)} to overwrite
* {@link Entity#changeDimension(int)}. This is mostly for debugging
* purposes, but as well as ensuring that the phases are entered and exited correctly.
*
* @param mixinEntity The mixin entity being called
* @param toSuggestedDimension The target dimension id suggested by mods and vanilla alike. The suggested
* dimension id can be erroneous and Vanilla will re-assign the variable to the overworld for
* silly things like entering an end portal while in the end.
* @return The entity, if the teleport was not cancelled or something.
*/
@Nullable
public static Entity transferEntityToDimension(IMixinEntity mixinEntity, int toSuggestedDimension) {
final Entity entity = toNative(mixinEntity);
// handle portal event
MoveEntityEvent.Teleport.Portal event = handleDisplaceEntityPortalEvent(entity, toSuggestedDimension, null);
if (event == null || event.isCancelled()) {
return null;
}
entity.world.profiler.startSection("changeDimension");
// use the world from event
final Transform<World> toTransform = event.getToTransform();
WorldServer toWorld = (WorldServer) toTransform.getExtent();
entity.world.removeEntity(entity);
entity.isDead = false;
entity.world.profiler.startSection("reposition");
final Vector3i toChunkPosition = toTransform.getLocation().getChunkPosition();
toWorld.getChunkProvider().loadChunk(toChunkPosition.getX(), toChunkPosition.getZ());
// Only need to update the entity location here as the portal is handled in SpongeCommonEventFactory
final Vector3d toPosition = toTransform.getPosition();
entity.setLocationAndAngles(toPosition.getX(), toPosition.getY(), toPosition.getZ(), (float) toTransform.getYaw(), (float) toTransform.getPitch());
entity.world = toWorld;
toWorld.spawnEntity(entity);
toWorld.updateEntityWithOptionalForce(entity, false);
entity.world.profiler.endSection();
entity.world.profiler.endSection();
entity.world.profiler.endSection();
return entity;
}
Aggregations