Search in sources :

Example 21 with IMixinEntity

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);
}
Also used : PotionEffect(net.minecraft.potion.PotionEffect) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) IMixinEntityPlayerMP(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP) SPacketRespawn(net.minecraft.network.play.server.SPacketRespawn) SPacketEntityStatus(net.minecraft.network.play.server.SPacketEntityStatus) SPacketEntityEffect(net.minecraft.network.play.server.SPacketEntityEffect)

Example 22 with IMixinEntity

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);
}
Also used : Vector3d(com.flowpowered.math.vector.Vector3d) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) World(org.spongepowered.api.world.World)

Example 23 with IMixinEntity

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;
    }
}
Also used : IMixinPlayerList(org.spongepowered.common.interfaces.IMixinPlayerList) WorldProviderEnd(net.minecraft.world.WorldProviderEnd) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) IMixinTeleporter(org.spongepowered.common.interfaces.world.IMixinTeleporter) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) World(org.spongepowered.api.world.World) MinecraftServer(net.minecraft.server.MinecraftServer) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Vector3i(com.flowpowered.math.vector.Vector3i) WorldProviderHell(net.minecraft.world.WorldProviderHell) TeleportingContext(org.spongepowered.common.event.tracking.phase.entity.TeleportingContext) BlockPos(net.minecraft.util.math.BlockPos) WorldProperties(org.spongepowered.api.world.storage.WorldProperties) Nullable(javax.annotation.Nullable)

Example 24 with IMixinEntity

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);
}
Also used : Vector3d(com.flowpowered.math.vector.Vector3d) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) World(org.spongepowered.api.world.World)

Example 25 with IMixinEntity

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;
}
Also used : MixinEntity(org.spongepowered.common.mixin.core.entity.MixinEntity) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) Entity(net.minecraft.entity.Entity) Vector3d(com.flowpowered.math.vector.Vector3d) Vector3i(com.flowpowered.math.vector.Vector3i) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) World(org.spongepowered.api.world.World) Nullable(javax.annotation.Nullable)

Aggregations

IMixinEntity (org.spongepowered.common.interfaces.entity.IMixinEntity)30 World (org.spongepowered.api.world.World)10 Entity (net.minecraft.entity.Entity)7 EntityPlayer (net.minecraft.entity.player.EntityPlayer)7 IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)7 Vector3d (com.flowpowered.math.vector.Vector3d)6 User (org.spongepowered.api.entity.living.player.User)6 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)6 ArrayList (java.util.ArrayList)5 BlockPos (net.minecraft.util.math.BlockPos)5 WorldServer (net.minecraft.world.WorldServer)5 Overwrite (org.spongepowered.asm.mixin.Overwrite)5 EntityPlayerMP (net.minecraft.entity.player.EntityPlayerMP)4 NBTTagCompound (net.minecraft.nbt.NBTTagCompound)4 Nullable (javax.annotation.Nullable)3 ItemStack (net.minecraft.item.ItemStack)3 TileEntity (org.spongepowered.api.block.tileentity.TileEntity)3 Entity (org.spongepowered.api.entity.Entity)3 Player (org.spongepowered.api.entity.living.player.Player)3 CauseStackManager (org.spongepowered.api.event.CauseStackManager)3