Search in sources :

Example 31 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class IPhaseState method spawnEntityOrCapture.

/**
 * This is Step 3 of entity spawning. It is used for the sole purpose of capturing an entity spawn
 * and doesn't actually spawn an entity into the world until the current phase is unwound.
 * The method itself should technically capture entity spawns, however, in the event it
 * is required that the entity cannot be captured, returning {@code false} will mark it
 * to spawn into the world, bypassing any of the bulk spawn events or capturing.
 *
 * <p>NOTE: This method should only be called and handled if and only if {@link IPhaseState#allowEntitySpawns()}
 * returns {@code true}. Violation of this will have unforseen consequences.</p>
 *
 * @param context The current context
 * @param entity The entity being captured
 * @param chunkX The chunk x position
 * @param chunkZ The chunk z position
 * @return True if the entity was successfully captured
 */
default boolean spawnEntityOrCapture(C context, org.spongepowered.api.entity.Entity entity, int chunkX, int chunkZ) {
    final User user = context.getNotifier().orElseGet(() -> context.getOwner().orElse(null));
    if (user != null) {
        entity.setCreator(user.getUniqueId());
    }
    final ArrayList<org.spongepowered.api.entity.Entity> entities = new ArrayList<>(1);
    entities.add(entity);
    final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
    SpongeImpl.postEvent(event);
    if (!event.isCancelled() && event.getEntities().size() > 0) {
        for (org.spongepowered.api.entity.Entity item : event.getEntities()) {
            ((IMixinWorldServer) item.getWorld()).forceSpawnEntity(item);
        }
        return true;
    }
    return false;
}
Also used : Entity(net.minecraft.entity.Entity) User(org.spongepowered.api.entity.living.player.User) ArrayList(java.util.ArrayList) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent)

Example 32 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class PhaseTracker method notifyBlockOfStateChange.

// --------------------- DELEGATED WORLD METHODS -------------------------
/**
 * Replacement of {@link net.minecraft.world.World#neighborChanged(BlockPos, Block, BlockPos)}
 * that adds tracking into play.
 *
 * @param mixinWorld THe world
 * @param notifyPos The original notification position
 * @param sourceBlock The source block type
 * @param sourcePos The source block position
 */
public void notifyBlockOfStateChange(final IMixinWorldServer mixinWorld, final BlockPos notifyPos, final Block sourceBlock, @Nullable final BlockPos sourcePos) {
    final IBlockState iblockstate = ((WorldServer) mixinWorld).getBlockState(notifyPos);
    try {
        // Sponge start - prepare notification
        final PhaseData peek = this.stack.peek();
        final IPhaseState<?> state = peek.state;
        ((IPhaseState) state).associateNeighborStateNotifier(peek.context, sourcePos, iblockstate.getBlock(), notifyPos, ((WorldServer) mixinWorld), PlayerTracker.Type.NOTIFIER);
        // Sponge End
        iblockstate.neighborChanged(((WorldServer) mixinWorld), notifyPos, sourceBlock, sourcePos);
    } catch (Throwable throwable) {
        CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception while updating neighbours");
        CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being updated");
        crashreportcategory.addDetail("Source block type", () -> {
            try {
                return String.format("ID #%d (%s // %s)", Block.getIdFromBlock(sourceBlock), sourceBlock.getUnlocalizedName(), sourceBlock.getClass().getCanonicalName());
            } catch (Throwable var2) {
                return "ID #" + Block.getIdFromBlock(sourceBlock);
            }
        });
        CrashReportCategory.addBlockInfo(crashreportcategory, notifyPos, iblockstate);
        throw new ReportedException(crashreport);
    }
}
Also used : IBlockState(net.minecraft.block.state.IBlockState) CrashReport(net.minecraft.crash.CrashReport) EntityThrowable(net.minecraft.entity.projectile.EntityThrowable) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) CrashReportCategory(net.minecraft.crash.CrashReportCategory) ReportedException(net.minecraft.util.ReportedException)

Example 33 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer 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 34 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer 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 35 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class TrackingUtil method updateTickBlock.

public static void updateTickBlock(IMixinWorldServer mixinWorld, Block block, BlockPos pos, IBlockState state, Random random) {
    final WorldServer minecraftWorld = mixinWorld.asMinecraftWorld();
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(minecraftWorld);
        if (ShouldFire.TICK_BLOCK_EVENT) {
            BlockSnapshot snapshot = mixinWorld.createSpongeBlockSnapshot(state, state, pos, BlockChangeFlags.NONE);
            final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(Sponge.getCauseStackManager().getCurrentCause(), snapshot);
            SpongeImpl.postEvent(event);
            if (event.isCancelled()) {
                return;
            }
        }
        final LocatableBlock locatable = LocatableBlock.builder().location(new Location<>(mixinWorld.asSpongeWorld(), pos.getX(), pos.getY(), pos.getZ())).state((BlockState) state).build();
        Sponge.getCauseStackManager().pushCause(locatable);
        IPhaseState<BlockTickContext> phase = ((IMixinBlock) block).requiresBlockCapture() ? TickPhase.Tick.BLOCK : TickPhase.Tick.NO_CAPTURE_BLOCK;
        final BlockTickContext phaseContext = phase.createPhaseContext().source(locatable);
        checkAndAssignBlockTickConfig(block, minecraftWorld, phaseContext);
        final PhaseTracker phaseTracker = PhaseTracker.getInstance();
        // We have to associate any notifiers in case of scheduled block updates from other sources
        final PhaseData current = phaseTracker.getCurrentPhaseData();
        final IPhaseState<?> currentState = current.state;
        ((IPhaseState) currentState).appendNotifierPreBlockTick(mixinWorld, pos, current.context, phaseContext);
        try (PhaseContext<?> context = phaseContext.buildAndSwitch()) {
            block.updateTick(minecraftWorld, pos, state, random);
        } catch (Exception | NoClassDefFoundError e) {
            phaseTracker.printExceptionFromPhase(e, phaseContext);
        }
    }
}
Also used : StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) TickBlockEvent(org.spongepowered.api.event.block.TickBlockEvent) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) BlockTickContext(org.spongepowered.common.event.tracking.phase.tick.BlockTickContext) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LocatableBlock(org.spongepowered.api.world.LocatableBlock)

Aggregations

IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)61 WorldServer (net.minecraft.world.WorldServer)25 BlockPos (net.minecraft.util.math.BlockPos)19 ArrayList (java.util.ArrayList)17 Entity (org.spongepowered.api.entity.Entity)15 World (org.spongepowered.api.world.World)15 IBlockState (net.minecraft.block.state.IBlockState)13 SpawnEntityEvent (org.spongepowered.api.event.entity.SpawnEntityEvent)13 CauseStackManager (org.spongepowered.api.event.CauseStackManager)11 Overwrite (org.spongepowered.asm.mixin.Overwrite)11 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)9 IMixinEntity (org.spongepowered.common.interfaces.entity.IMixinEntity)9 EntityItem (net.minecraft.entity.item.EntityItem)8 User (org.spongepowered.api.entity.living.player.User)8 LocatableBlock (org.spongepowered.api.world.LocatableBlock)8 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)7 Entity (net.minecraft.entity.Entity)6 EntityPlayer (net.minecraft.entity.player.EntityPlayer)6 Chunk (net.minecraft.world.chunk.Chunk)6 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)6