Search in sources :

Example 16 with IMixinEntity

use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeForge by SpongePowered.

the class MixinBlockRailBase method onMinecartRailPass.

// Used to transfer tracking information from minecarts to block positions
@Inject(method = "onMinecartPass", at = @At(value = "HEAD"))
public void onMinecartRailPass(World world, net.minecraft.entity.item.EntityMinecart cart, BlockPos pos, CallbackInfo ci) {
    IMixinEntity spongeEntity = (IMixinEntity) cart;
    Optional<User> notifier = spongeEntity.getNotifierUser();
    Optional<User> owner = spongeEntity.getCreatorUser();
    if (owner.isPresent() || notifier.isPresent()) {
        IMixinChunk spongeChunk = (IMixinChunk) world.getChunkFromBlockCoords(pos);
        if (notifier.isPresent()) {
            spongeChunk.addTrackedBlockPosition(world.getBlockState(pos).getBlock(), pos, notifier.get(), PlayerTracker.Type.NOTIFIER);
        } else {
            spongeChunk.addTrackedBlockPosition(world.getBlockState(pos).getBlock(), pos, owner.get(), PlayerTracker.Type.NOTIFIER);
        }
    }
}
Also used : User(org.spongepowered.api.entity.living.player.User) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 17 with IMixinEntity

use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.

the class PhaseTracker method spawnEntity.

/**
 * This is the replacement of {@link WorldServer#spawnEntity(net.minecraft.entity.Entity)}
 * where it captures into phases. The causes and relations are processed by the phases.
 *
 * The difference between {@link #spawnEntityWithCause(World, Entity)} is that it bypasses
 * any phases and directly throws a spawn entity event.
 *
 * @param world The world
 * @param entity The entity
 * @return True if the entity spawn was successful
 */
public boolean spawnEntity(World world, Entity entity) {
    checkNotNull(entity, "Entity cannot be null!");
    // Sponge Start - handle construction phases
    if (((IMixinEntity) entity).isInConstructPhase()) {
        ((IMixinEntity) entity).firePostConstructEvents();
    }
    final net.minecraft.entity.Entity minecraftEntity = EntityUtil.toNative(entity);
    final WorldServer minecraftWorld = (WorldServer) world;
    final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) minecraftWorld;
    final PhaseData phaseData = this.stack.peek();
    final IPhaseState<?> phaseState = phaseData.state;
    final PhaseContext<?> context = phaseData.context;
    final boolean isForced = minecraftEntity.forceSpawn || minecraftEntity instanceof EntityPlayer;
    // Certain phases disallow entity spawns (such as block restoration)
    if (!isForced && !phaseState.allowEntitySpawns()) {
        return false;
    }
    // Sponge End - continue with vanilla mechanics
    final int chunkX = MathHelper.floor(minecraftEntity.posX / 16.0D);
    final int chunkZ = MathHelper.floor(minecraftEntity.posZ / 16.0D);
    if (!isForced && !mixinWorldServer.isMinecraftChunkLoaded(chunkX, chunkZ, true)) {
        return false;
    }
    if (minecraftEntity instanceof EntityPlayer) {
        EntityPlayer entityplayer = (EntityPlayer) minecraftEntity;
        minecraftWorld.playerEntities.add(entityplayer);
        minecraftWorld.updateAllPlayersSleepingFlag();
        SpongeImplHooks.firePlayerJoinSpawnEvent((EntityPlayerMP) entityplayer);
    } else {
        // Sponge start - check for vanilla owner
        if (minecraftEntity instanceof IEntityOwnable) {
            IEntityOwnable ownable = (IEntityOwnable) entity;
            net.minecraft.entity.Entity owner = ownable.getOwner();
            if (owner != null && owner instanceof EntityPlayer) {
                context.owner = (User) owner;
                entity.setCreator(ownable.getOwnerId());
            }
        } else if (minecraftEntity instanceof EntityThrowable) {
            EntityThrowable throwable = (EntityThrowable) minecraftEntity;
            EntityLivingBase thrower = throwable.getThrower();
            if (thrower != null) {
                User user = null;
                if (!(thrower instanceof EntityPlayer)) {
                    user = ((IMixinEntity) thrower).getCreatorUser().orElse(null);
                } else {
                    user = (User) thrower;
                }
                if (user != null) {
                    context.owner = user;
                    entity.setCreator(user.getUniqueId());
                }
            }
        }
    // Sponge end
    }
    // capture all entities until the phase is marked for completion.
    if (!isForced) {
        try {
            return ((IPhaseState) phaseState).spawnEntityOrCapture(context, entity, chunkX, chunkZ);
        } catch (Exception | NoClassDefFoundError e) {
            // Just in case something really happened, we should print a nice exception for people to
            // paste us
            this.printExceptionSpawningEntity(context, e);
            return false;
        }
    }
    // Sponge end - continue on with the checks.
    minecraftWorld.getChunkFromChunkCoords(chunkX, chunkZ).addEntity(minecraftEntity);
    minecraftWorld.loadedEntityList.add(minecraftEntity);
    // Sponge - Cannot add onEntityAdded to the access transformer because forge makes it public
    mixinWorldServer.onSpongeEntityAdded(minecraftEntity);
    return true;
}
Also used : EntityThrowable(net.minecraft.entity.projectile.EntityThrowable) User(org.spongepowered.api.entity.living.player.User) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) ReportedException(net.minecraft.util.ReportedException) EntityLivingBase(net.minecraft.entity.EntityLivingBase) EntityPlayer(net.minecraft.entity.player.EntityPlayer) IEntityOwnable(net.minecraft.entity.IEntityOwnable)

Example 18 with IMixinEntity

use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.

the class PhaseTracker method spawnEntityWithCause.

/**
 * The core implementation of {@link World#spawnEntity(Entity)} that
 * bypasses any sort of cause tracking and throws an event directly
 *
 * @param world The world
 * @param entity The entity
 * @return True if entity was spawned, false if not
 */
public boolean spawnEntityWithCause(World world, Entity entity) {
    checkNotNull(entity, "Entity cannot be null!");
    // Sponge Start - handle construction phases
    if (((IMixinEntity) entity).isInConstructPhase()) {
        ((IMixinEntity) entity).firePostConstructEvents();
    }
    final net.minecraft.entity.Entity minecraftEntity = EntityUtil.toNative(entity);
    final WorldServer worldServer = (WorldServer) world;
    final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) worldServer;
    // Sponge End - continue with vanilla mechanics
    final int chunkX = MathHelper.floor(minecraftEntity.posX / 16.0D);
    final int chunkZ = MathHelper.floor(minecraftEntity.posZ / 16.0D);
    final boolean isForced = minecraftEntity.forceSpawn || minecraftEntity instanceof EntityPlayer;
    if (!isForced && !mixinWorldServer.isMinecraftChunkLoaded(chunkX, chunkZ, true)) {
        return false;
    }
    // Sponge Start - throw an event
    // We need to use an arraylist so that filtering will work.
    final List<Entity> entities = new ArrayList<>(1);
    entities.add(entity);
    final SpawnEntityEvent.Custom event = SpongeEventFactory.createSpawnEntityEventCustom(Sponge.getCauseStackManager().getCurrentCause(), entities);
    SpongeImpl.postEvent(event);
    if (entity instanceof EntityPlayer || !event.isCancelled()) {
        mixinWorldServer.forceSpawnEntity(entity);
    }
    return true;
}
Also used : IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) Entity(org.spongepowered.api.entity.Entity) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) EntityPlayer(net.minecraft.entity.player.EntityPlayer)

Example 19 with IMixinEntity

use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method callDestructEntityEventDeath.

public static DestructEntityEvent.Death callDestructEntityEventDeath(EntityLivingBase entity, DamageSource source) {
    final MessageEvent.MessageFormatter formatter = new MessageEvent.MessageFormatter();
    MessageChannel originalChannel;
    MessageChannel channel;
    Text originalMessage;
    Optional<User> sourceCreator = Optional.empty();
    boolean messageCancelled = false;
    if (entity instanceof EntityPlayerMP) {
        originalChannel = channel = ((IMixinEntityPlayerMP) entity).getDeathMessageChannel();
    } else {
        originalChannel = MessageChannel.TO_NONE;
        channel = MessageChannel.TO_NONE;
    }
    if (source instanceof EntityDamageSource) {
        EntityDamageSource damageSource = (EntityDamageSource) source;
        IMixinEntity spongeEntity = (IMixinEntity) damageSource.getImmediateSource();
        if (spongeEntity != null) {
            sourceCreator = spongeEntity.getCreatorUser();
        }
    }
    originalMessage = SpongeTexts.toText(entity.getCombatTracker().getDeathMessage());
    formatter.getBody().add(new MessageEvent.DefaultBodyApplier(originalMessage));
    final boolean isMainThread = Sponge.isServerAvailable() && Sponge.getServer().isMainThread();
    // checks need to be made here since entities can die on the client world.
    try (final StackFrame frame = isMainThread ? Sponge.getCauseStackManager().pushCauseFrame() : null) {
        if (isMainThread) {
            Sponge.getCauseStackManager().pushCause(source);
            if (sourceCreator.isPresent()) {
                Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, sourceCreator.get());
            }
        }
        final Cause cause = isMainThread ? Sponge.getCauseStackManager().getCurrentCause() : Cause.of(EventContext.empty(), source);
        DestructEntityEvent.Death event = SpongeEventFactory.createDestructEntityEventDeath(cause, originalChannel, Optional.of(channel), formatter, (Living) entity, entity.world.getGameRules().getBoolean("keepInventory"), messageCancelled);
        SpongeImpl.postEvent(event);
        Text message = event.getMessage();
        if (!event.isMessageCancelled() && !message.isEmpty()) {
            event.getChannel().ifPresent(eventChannel -> eventChannel.send(entity, event.getMessage()));
        }
        return event;
    }
}
Also used : User(org.spongepowered.api.entity.living.player.User) MessageEvent(org.spongepowered.api.event.message.MessageEvent) Text(org.spongepowered.api.text.Text) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) IMixinEntityPlayerMP(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP) EntityDamageSource(net.minecraft.util.EntityDamageSource) MessageChannel(org.spongepowered.api.text.channel.MessageChannel) DestructEntityEvent(org.spongepowered.api.event.entity.DestructEntityEvent) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) Cause(org.spongepowered.api.event.cause.Cause) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) IMixinEntityPlayerMP(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP)

Example 20 with IMixinEntity

use of org.spongepowered.common.interfaces.entity.IMixinEntity in project SpongeCommon by SpongePowered.

the class EntityUtil method entityOnDropItem.

/**
 * A simple redirected static util method for {@link Entity#entityDropItem(ItemStack, float)}
 * for easy debugging.
 * @param entity
 * @param itemStack
 * @param offsetY
 * @return
 */
public static EntityItem entityOnDropItem(Entity entity, ItemStack itemStack, float offsetY) {
    final IMixinEntity mixinEntity = EntityUtil.toMixin(entity);
    final IMixinEntityPlayer mixinPlayer = entity instanceof Player ? (IMixinEntityPlayer) entity : null;
    // Now the real fun begins.
    final ItemStack item;
    final double posX = entity.posX;
    final double posY = entity.posY + offsetY;
    final double posZ = entity.posZ;
    if (itemStack.isEmpty()) {
        return null;
    }
    // FIRST we want to throw the DropItemEvent.PRE
    final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(itemStack);
    final List<ItemStackSnapshot> original = new ArrayList<>();
    original.add(snapshot);
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(entity);
        final DropItemEvent.Pre dropEvent = SpongeEventFactory.createDropItemEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of(snapshot), original);
        SpongeImpl.postEvent(dropEvent);
        if (dropEvent.isCancelled()) {
            if (mixinPlayer != null) {
                mixinPlayer.shouldRestoreInventory(true);
            }
            return null;
        }
        if (dropEvent.getDroppedItems().isEmpty()) {
            return null;
        }
        // SECOND throw the ConstructEntityEvent
        Transform<World> suggested = new Transform<>(mixinEntity.getWorld(), new Vector3d(posX, entity.posY + offsetY, posZ));
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
        ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.ITEM, suggested);
        SpongeImpl.postEvent(event);
        item = event.isCancelled() ? null : ItemStackUtil.fromSnapshotToNative(dropEvent.getDroppedItems().get(0));
        if (item == null) {
            if (mixinPlayer != null) {
                mixinPlayer.shouldRestoreInventory(true);
            }
            return null;
        }
        final PhaseData peek = PhaseTracker.getInstance().getCurrentPhaseData();
        final IPhaseState currentState = peek.state;
        final PhaseContext<?> phaseContext = peek.context;
        if (item.isEmpty()) {
            return null;
        }
        if (!currentState.ignoresItemPreMerging() && SpongeImpl.getGlobalConfig().getConfig().getOptimizations().doDropsPreMergeItemDrops()) {
            if (currentState.tracksEntitySpecificDrops()) {
                final Multimap<UUID, ItemDropData> multimap = phaseContext.getCapturedEntityDropSupplier().get();
                final Collection<ItemDropData> itemStacks = multimap.get(entity.getUniqueID());
                SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).build());
                return null;
            }
            final List<ItemDropData> itemStacks = phaseContext.getCapturedItemStackSupplier().get();
            SpongeImplHooks.addItemStackToListForSpawning(itemStacks, ItemDropData.item(item).position(new Vector3d(posX, posY, posZ)).build());
            return null;
        }
        EntityItem entityitem = new EntityItem(entity.world, posX, posY, posZ, item);
        entityitem.setDefaultPickupDelay();
        // FIFTH - Capture the entity maybe?
        if (currentState.doesCaptureEntityDrops()) {
            if (currentState.tracksEntitySpecificDrops()) {
                // We are capturing per entity drop
                phaseContext.getCapturedEntityItemDropSupplier().get().put(entity.getUniqueID(), entityitem);
            } else {
                // We are adding to a general list - usually for EntityPhase.State.DEATH
                phaseContext.getCapturedItemsSupplier().get().add(entityitem);
            }
            // Return the item, even if it wasn't spawned in the world.
            return entityitem;
        }
        // FINALLY - Spawn the entity in the world if all else didn't fail
        entity.world.spawnEntity(entityitem);
        return entityitem;
    }
}
Also used : ArrayList(java.util.ArrayList) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) World(org.spongepowered.api.world.World) CauseStackManager(org.spongepowered.api.event.CauseStackManager) IMixinEntityPlayer(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayer) UUID(java.util.UUID) EntityItem(net.minecraft.entity.item.EntityItem) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) Player(org.spongepowered.api.entity.living.player.Player) IMixinEntityPlayer(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayer) EntityPlayer(net.minecraft.entity.player.EntityPlayer) ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) Vector3d(com.flowpowered.math.vector.Vector3d) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStack(net.minecraft.item.ItemStack) Transform(org.spongepowered.api.entity.Transform) ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData)

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