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);
}
}
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;
}
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
}
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();
}
}
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;
}
Aggregations