Search in sources :

Example 1 with IMixinTileEntity

use of org.spongepowered.common.interfaces.block.tile.IMixinTileEntity in project SpongeCommon by SpongePowered.

the class TrackingUtil method tickTileEntity.

@SuppressWarnings({ "unused", "try" })
public static void tickTileEntity(IMixinWorldServer mixinWorldServer, ITickable tile) {
    checkArgument(tile instanceof TileEntity, "ITickable %s is not a TileEntity!", tile);
    checkNotNull(tile, "Cannot capture on a null ticking tile entity!");
    final net.minecraft.tileentity.TileEntity tileEntity = (net.minecraft.tileentity.TileEntity) tile;
    final IMixinTileEntity mixinTileEntity = (IMixinTileEntity) tile;
    final BlockPos pos = tileEntity.getPos();
    final IMixinChunk chunk = ((IMixinTileEntity) tile).getActiveChunk();
    if (!mixinTileEntity.shouldTick()) {
        return;
    }
    final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext().source(tile);
    try (final StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame();
        final PhaseContext<?> phaseContext = context) {
        Sponge.getCauseStackManager().pushCause(tile);
        // Add notifier and owner so we don't have to perform lookups during the phases and other processing
        chunk.getBlockNotifier(pos).ifPresent(notifier -> {
            Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
            phaseContext.notifier(notifier);
        });
        User blockOwner = mixinTileEntity.getSpongeOwner();
        if (!mixinTileEntity.hasSetOwner()) {
            blockOwner = chunk.getBlockOwner(pos).orElse(null);
            mixinTileEntity.setSpongeOwner(blockOwner);
        }
        if (blockOwner != null) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, blockOwner);
            phaseContext.owner(blockOwner);
        }
        phaseContext.owner = blockOwner;
        // Add the block snapshot of the tile entity for caches to avoid creating multiple snapshots during processing
        // This is a lazy evaluating snapshot to avoid the overhead of snapshot creation
        // Finally, switch the context now that we have the owner and notifier
        phaseContext.buildAndSwitch();
        try (Timing timing = mixinTileEntity.getTimingsHandler().startTiming()) {
            tile.update();
        }
    } catch (Exception e) {
        PhaseTracker.getInstance().printExceptionFromPhase(e, context);
    }
}
Also used : User(org.spongepowered.api.entity.living.player.User) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) BlockPos(net.minecraft.util.math.BlockPos) Timing(co.aikar.timings.Timing) TileEntityTickContext(org.spongepowered.common.event.tracking.phase.tick.TileEntityTickContext)

Example 2 with IMixinTileEntity

use of org.spongepowered.common.interfaces.block.tile.IMixinTileEntity in project SpongeCommon by SpongePowered.

the class TileEntityTickPhaseState method spawnEntityOrCapture.

@Override
public boolean spawnEntityOrCapture(TileEntityTickContext context, Entity entity, int chunkX, int chunkZ) {
    final TileEntity tickingTile = context.getSource(TileEntity.class).orElseThrow(TrackingUtil.throwWithContext("Not ticking on a TileEntity!", context));
    final Optional<User> notifier = context.getNotifier();
    final Optional<User> owner = context.getOwner();
    final User entityCreator = notifier.orElseGet(() -> owner.orElse(null));
    final IMixinTileEntity mixinTileEntity = (IMixinTileEntity) tickingTile;
    // Separate experience from other entities
    if (entity instanceof EntityXPOrb) {
        try (StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
            Sponge.getCauseStackManager().pushCause(tickingTile.getLocatableBlock());
            Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.EXPERIENCE);
            context.addNotifierAndOwnerToCauseStack();
            final ArrayList<Entity> exp = new ArrayList<>();
            exp.add(entity);
            final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), exp);
            SpongeImpl.postEvent(event);
            if (!event.isCancelled()) {
                for (Entity anEntity : event.getEntities()) {
                    if (entityCreator != null) {
                        EntityUtil.toMixin(anEntity).setCreator(entityCreator.getUniqueId());
                    }
                    EntityUtil.getMixinWorld(entity).forceSpawnEntity(anEntity);
                }
                return true;
            }
        }
        return false;
    }
    final List<Entity> nonExpEntities = new ArrayList<>(1);
    nonExpEntities.add(entity);
    try (StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(tickingTile.getLocatableBlock());
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, mixinTileEntity.getTickedSpawnType());
        context.addNotifierAndOwnerToCauseStack();
        final SpawnEntityEvent spawnEntityEvent = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), nonExpEntities);
        SpongeImpl.postEvent(spawnEntityEvent);
        if (!spawnEntityEvent.isCancelled()) {
            for (Entity anEntity : spawnEntityEvent.getEntities()) {
                if (entityCreator != null) {
                    EntityUtil.toMixin(anEntity).setCreator(entityCreator.getUniqueId());
                }
                EntityUtil.getMixinWorld(entity).forceSpawnEntity(anEntity);
            }
            return true;
        }
    }
    return false;
}
Also used : IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) Entity(org.spongepowered.api.entity.Entity) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) User(org.spongepowered.api.entity.living.player.User) IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) ArrayList(java.util.ArrayList) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) EntityXPOrb(net.minecraft.entity.item.EntityXPOrb)

Example 3 with IMixinTileEntity

use of org.spongepowered.common.interfaces.block.tile.IMixinTileEntity in project SpongeCommon by SpongePowered.

the class MixinWorld method updateEntities.

/**
 ********************* TIMINGS **********************
 */
/**
 * @author blood
 * @author gabizou - Ported to 1.9.4 - replace direct field calls to overriden methods in MixinWorldServer
 *
 * @reason Add timing hooks in various areas. This method shouldn't be touched by mods/forge alike
 */
@Overwrite
public void updateEntities() {
    // this.profiler.startSection("entities"); // Sponge - Don't use the profiler
    // this.profiler.startSection("global"); // Sponge - Don't use the profiler
    // Sponge
    this.startEntityGlobalTimings();
    for (int i = 0; i < this.weatherEffects.size(); ++i) {
        net.minecraft.entity.Entity entity = this.weatherEffects.get(i);
        try {
            ++entity.ticksExisted;
            entity.onUpdate();
        } catch (Throwable throwable2) {
            // Sponge - end the entity timing
            this.stopTimingForWeatherEntityTickCrash(entity);
            CrashReport crashreport = CrashReport.makeCrashReport(throwable2, "Ticking entity");
            CrashReportCategory crashreportcategory = crashreport.makeCategory("Entity being ticked");
            if (entity == null) {
                crashreportcategory.addCrashSection("Entity", "~~NULL~~");
            } else {
                entity.addEntityCrashInfo(crashreportcategory);
            }
            SpongeImplHooks.onEntityError(entity, crashreport);
        }
        if (entity.isDead) {
            this.weatherEffects.remove(i--);
        }
    }
    // Sponge
    this.stopEntityTickTimingStartEntityRemovalTiming();
    // this.profiler.endStartSection("remove"); // Sponge - Don't use the profiler
    this.loadedEntityList.removeAll(this.unloadedEntityList);
    for (int k = 0; k < this.unloadedEntityList.size(); ++k) {
        net.minecraft.entity.Entity entity1 = this.unloadedEntityList.get(k);
        // Sponge start - use cached chunk
        // int j = entity1.chunkCoordX;
        // int k1 = entity1.chunkCoordZ;
        final net.minecraft.world.chunk.Chunk activeChunk = (net.minecraft.world.chunk.Chunk) ((IMixinEntity) entity1).getActiveChunk();
        if (activeChunk != null) {
            activeChunk.removeEntity(entity1);
        }
    // Sponge end
    }
    for (int l = 0; l < this.unloadedEntityList.size(); ++l) {
        this.onEntityRemoved(this.unloadedEntityList.get(l));
    }
    this.unloadedEntityList.clear();
    // Sponge
    this.stopEntityRemovalTiming();
    this.tickPlayers();
    // this.profiler.endStartSection("regular"); // Sponge - Don't use the profiler
    this.entityActivationCheck();
    for (int i1 = 0; i1 < this.loadedEntityList.size(); ++i1) {
        net.minecraft.entity.Entity entity2 = this.loadedEntityList.get(i1);
        net.minecraft.entity.Entity entity3 = entity2.getRidingEntity();
        if (entity3 != null) {
            if (!entity3.isDead && entity3.isPassenger(entity2)) {
                continue;
            }
            entity2.dismountRidingEntity();
        }
        // this.profiler.startSection("tick"); // Sponge - Don't use the profiler
        // Sponge
        this.startEntityTickTiming();
        if (!entity2.isDead && !(entity2 instanceof EntityPlayerMP)) {
            try {
                this.updateEntity(entity2);
            } catch (Throwable throwable1) {
                // Sponge
                this.stopTimingTickEntityCrash(entity2);
                CrashReport crashreport1 = CrashReport.makeCrashReport(throwable1, "Ticking entity");
                CrashReportCategory crashreportcategory1 = crashreport1.makeCategory("Entity being ticked");
                entity2.addEntityCrashInfo(crashreportcategory1);
                SpongeImplHooks.onEntityError(entity2, crashreport1);
            }
        }
        // Sponge
        this.stopEntityTickSectionBeforeRemove();
        // this.profiler.endSection(); // Sponge - Don't use the profiler
        // this.profiler.startSection("remove"); // Sponge - Don't use the profiler
        // Sponge
        this.startEntityRemovalTick();
        if (entity2.isDead) {
            // Sponge start - use cached chunk
            // int l1 = entity2.chunkCoordX;
            // int i2 = entity2.chunkCoordZ;
            final net.minecraft.world.chunk.Chunk activeChunk = (net.minecraft.world.chunk.Chunk) ((IMixinEntity) entity2).getActiveChunk();
            if (activeChunk != null) {
                activeChunk.removeEntity(entity2);
            }
            // Sponge end
            this.loadedEntityList.remove(i1--);
            this.onEntityRemoved(entity2);
        }
        // Sponge
        this.stopEntityRemovalTiming();
    // this.profiler.endSection(); // Sponge - Don't use the profiler
    }
    // this.profiler.endStartSection("blockEntities"); // Sponge - Don't use the profiler
    spongeTileEntityActivation();
    this.processingLoadedTiles = true;
    Iterator<net.minecraft.tileentity.TileEntity> iterator = this.tickableTileEntities.iterator();
    while (iterator.hasNext()) {
        // Sponge
        this.startTileTickTimer();
        net.minecraft.tileentity.TileEntity tileentity = iterator.next();
        if (!tileentity.isInvalid() && tileentity.hasWorld()) {
            BlockPos blockpos = tileentity.getPos();
            if (((IMixinTileEntity) tileentity).shouldTick() && this.worldBorder.contains(blockpos)) {
                // Sponge
                try {
                    // this.profiler.startSection(tileentity.getClass().getSimpleName());
                    ((ITickable) tileentity).update();
                // this.profiler.endSection();
                } catch (Throwable throwable) {
                    // Sponge
                    this.stopTimingTickTileEntityCrash(tileentity);
                    CrashReport crashreport2 = CrashReport.makeCrashReport(throwable, "Ticking block entity");
                    CrashReportCategory crashreportcategory2 = crashreport2.makeCategory("Block entity being ticked");
                    tileentity.addInfoToCrashReport(crashreportcategory2);
                    SpongeImplHooks.onTileEntityError(tileentity, crashreport2);
                }
            }
        }
        // Sponge
        this.stopTileEntityAndStartRemoval();
        if (tileentity.isInvalid()) {
            iterator.remove();
            this.loadedTileEntityList.remove(tileentity);
            // Sponge start - use cached chunk
            final net.minecraft.world.chunk.Chunk activeChunk = (net.minecraft.world.chunk.Chunk) ((IMixinTileEntity) tileentity).getActiveChunk();
            if (activeChunk != null) {
                // Forge: Bugfix: If we set the tile entity it immediately sets it in the chunk, so we could be desynced
                if (activeChunk.getTileEntity(tileentity.getPos(), net.minecraft.world.chunk.Chunk.EnumCreateEntityType.CHECK) == tileentity) {
                    activeChunk.removeTileEntity(tileentity.getPos());
                }
            }
        // Sponge end
        }
        // Sponge
        this.stopTileEntityRemovelInWhile();
    }
    if (!this.tileEntitiesToBeRemoved.isEmpty()) {
        // Sponge start - use forge hook
        for (Object tile : this.tileEntitiesToBeRemoved) {
            SpongeImplHooks.onTileChunkUnload(((net.minecraft.tileentity.TileEntity) tile));
        }
        // Sponge end
        // forge: faster "contains" makes this removal much more efficient
        java.util.Set<net.minecraft.tileentity.TileEntity> remove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>());
        remove.addAll(this.tileEntitiesToBeRemoved);
        this.tickableTileEntities.removeAll(remove);
        this.loadedTileEntityList.removeAll(remove);
        this.tileEntitiesToBeRemoved.clear();
    }
    if (!this.isRemote) {
        try (final PhaseContext<?> context = BlockPhase.State.TILE_CHUNK_UNLOAD.createPhaseContext().source(this).buildAndSwitch()) {
            // Sponge
            this.startPendingTileEntityTimings();
        }
    }
    // FML Move below remove to prevent CMEs
    this.processingLoadedTiles = false;
    if (!this.addedTileEntityList.isEmpty()) {
        for (int j1 = 0; j1 < this.addedTileEntityList.size(); ++j1) {
            net.minecraft.tileentity.TileEntity tileentity1 = this.addedTileEntityList.get(j1);
            if (!tileentity1.isInvalid()) {
                if (!this.loadedTileEntityList.contains(tileentity1)) {
                    this.addTileEntity(tileentity1);
                }
                if (this.isBlockLoaded(tileentity1.getPos())) {
                    net.minecraft.world.chunk.Chunk chunk = this.getChunkFromBlockCoords(tileentity1.getPos());
                    IBlockState iblockstate = chunk.getBlockState(tileentity1.getPos());
                    chunk.addTileEntity(tileentity1.getPos(), tileentity1);
                    this.notifyBlockUpdate(tileentity1.getPos(), iblockstate, iblockstate, 3);
                }
            }
        }
        this.addedTileEntityList.clear();
    }
    // Sponge
    this.endPendingTileEntities();
// this.profiler.endSection(); // Sponge - Don't use the profiler
// this.profiler.endSection(); // Sponge - Don't use the profiler
}
Also used : CrashReport(net.minecraft.crash.CrashReport) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) BlockPos(net.minecraft.util.math.BlockPos) IMixinBlockPos(org.spongepowered.common.interfaces.util.math.IMixinBlockPos) IBlockState(net.minecraft.block.state.IBlockState) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) Chunk(org.spongepowered.api.world.Chunk) ITickable(net.minecraft.util.ITickable) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) CrashReportCategory(net.minecraft.crash.CrashReportCategory) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 4 with IMixinTileEntity

use of org.spongepowered.common.interfaces.block.tile.IMixinTileEntity in project SpongeCommon by SpongePowered.

the class MixinWorldServer method markChunkDirty.

@Override
public void markChunkDirty(BlockPos pos, net.minecraft.tileentity.TileEntity unusedTileEntity) {
    if (unusedTileEntity == null) {
        super.markChunkDirty(pos, unusedTileEntity);
        return;
    }
    final IMixinTileEntity spongeTileEntity = (IMixinTileEntity) unusedTileEntity;
    final IMixinChunk chunk = spongeTileEntity.getActiveChunk();
    if (chunk != null) {
        chunk.markChunkDirty();
    }
}
Also used : IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk)

Example 5 with IMixinTileEntity

use of org.spongepowered.common.interfaces.block.tile.IMixinTileEntity in project SpongeCommon by SpongePowered.

the class TileEntityActivation method checkIfActive.

/**
 * Checks if the tileentity is active for this tick.
 *
 * @param tileEntity The tileentity to check for activity
 * @return Whether the given tileentity should be active
 */
public static boolean checkIfActive(TileEntity tileEntity) {
    if (tileEntity.getWorld() == null || tileEntity.getWorld().isRemote || !(tileEntity instanceof ITickable)) {
        return true;
    }
    final World world = tileEntity.getWorld();
    final IMixinChunk activeChunk = ((IMixinTileEntity) tileEntity).getActiveChunk();
    if (activeChunk == null) {
        // Should never happen but just in case for mods, always tick
        return true;
    }
    long currentTick = SpongeImpl.getServer().getTickCounter();
    IModData_Activation spongeTileEntity = (IModData_Activation) tileEntity;
    boolean isActive = activeChunk.isPersistedChunk() || spongeTileEntity.getActivatedTick() >= currentTick || spongeTileEntity.getDefaultActivationState();
    // Should this entity tick?
    if (!isActive) {
        if (spongeTileEntity.getActivatedTick() == Integer.MIN_VALUE) {
            // Has not come across a player
            return false;
        }
    }
    // check tick rate
    if (isActive && world.getWorldInfo().getWorldTotalTime() % spongeTileEntity.getSpongeTickRate() != 0L) {
        isActive = false;
    }
    return isActive;
}
Also used : IModData_Activation(org.spongepowered.common.mixin.plugin.entityactivation.interfaces.IModData_Activation) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) ITickable(net.minecraft.util.ITickable) World(net.minecraft.world.World)

Aggregations

IMixinTileEntity (org.spongepowered.common.interfaces.block.tile.IMixinTileEntity)5 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)4 TileEntity (org.spongepowered.api.block.tileentity.TileEntity)3 ITickable (net.minecraft.util.ITickable)2 BlockPos (net.minecraft.util.math.BlockPos)2 User (org.spongepowered.api.entity.living.player.User)2 StackFrame (org.spongepowered.api.event.CauseStackManager.StackFrame)2 Timing (co.aikar.timings.Timing)1 ArrayList (java.util.ArrayList)1 IBlockState (net.minecraft.block.state.IBlockState)1 CrashReport (net.minecraft.crash.CrashReport)1 CrashReportCategory (net.minecraft.crash.CrashReportCategory)1 EntityXPOrb (net.minecraft.entity.item.EntityXPOrb)1 EntityPlayerMP (net.minecraft.entity.player.EntityPlayerMP)1 World (net.minecraft.world.World)1 Entity (org.spongepowered.api.entity.Entity)1 SpawnEntityEvent (org.spongepowered.api.event.entity.SpawnEntityEvent)1 Chunk (org.spongepowered.api.world.Chunk)1 Overwrite (org.spongepowered.asm.mixin.Overwrite)1 TileEntityTickContext (org.spongepowered.common.event.tracking.phase.tick.TileEntityTickContext)1