use of org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge in project SpongeCommon by SpongePowered.
the class TrackingUtil method tickTileEntity.
@SuppressWarnings({ "unused", "try" })
public static void tickTileEntity(final TrackedWorldBridge mixinWorldServer, final TickableBlockEntity tile) {
checkArgument(tile instanceof BlockEntity, "ITickable %s is not a TileEntity!", tile);
checkNotNull(tile, "Cannot capture on a null ticking tile entity!");
final net.minecraft.world.level.block.entity.BlockEntity tileEntity = (net.minecraft.world.level.block.entity.BlockEntity) tile;
final BlockEntityBridge mixinTileEntity = (BlockEntityBridge) tile;
final BlockPos pos = tileEntity.getBlockPos();
final LevelChunkBridge chunk = ((ActiveChunkReferantBridge) tile).bridge$getActiveChunk();
if (!((TrackableBridge) tileEntity).bridge$shouldTick()) {
return;
}
if (chunk == null) {
((ActiveChunkReferantBridge) tile).bridge$setActiveChunk((TrackedLevelChunkBridge) tileEntity.getLevel().getChunkAt(tileEntity.getBlockPos()));
}
final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext(PhaseTracker.SERVER).source(mixinTileEntity);
try (final PhaseContext<?> phaseContext = context) {
if (tile instanceof CreatorTrackedBridge) {
// Add notifier and owner so we don't have to perform lookups during the phases and other processing
((CreatorTrackedBridge) tile).tracker$getNotifierUUID().ifPresent(phaseContext::notifier);
// Allow the tile entity to validate the owner of itself. As long as the tile entity
// chunk is already loaded and activated, and the tile entity has already loaded
// the owner of itself.
((CreatorTrackedBridge) tile).tracker$getCreatorUUID().ifPresent(phaseContext::creator);
}
// Finally, switch the context now that we have the owner and notifier
phaseContext.buildAndSwitch();
try (final Timing timing = ((TimingBridge) tileEntity.getType()).bridge$timings().startTiming()) {
tile.tick();
}
// otherwise the viewing players update this during their ticking
if (tileEntity instanceof ViewableInventoryBridge) {
final Set<ServerPlayer> players = ((ViewableInventoryBridge) tileEntity).viewableBridge$getViewers();
if (players.size() > 0) {
players.forEach(player -> player.containerMenu.broadcastChanges());
}
}
} catch (final Exception e) {
PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, context);
}
// We delay clearing active chunk if TE is invalidated during tick so we must remove it after
if (tileEntity.isRemoved()) {
((ActiveChunkReferantBridge) tileEntity).bridge$setActiveChunk(null);
}
}
use of org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge in project SpongeCommon by SpongePowered.
the class HopperBlockEntityMixin method impl$trackNotifierWhenTransferring.
@Inject(method = "addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/entity/item/ItemEntity;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;getItem()Lnet/minecraft/world/item/ItemStack;"))
private static void impl$trackNotifierWhenTransferring(final Container inventory, final ItemEntity entityItem, final CallbackInfoReturnable<Boolean> callbackInfo) {
if (entityItem instanceof CreatorTrackedBridge) {
((CreatorTrackedBridge) entityItem).tracker$getCreatorUUID().ifPresent(creator -> {
if (inventory instanceof ActiveChunkReferantBridge && inventory instanceof BlockEntity) {
final BlockEntity te = (BlockEntity) inventory;
final LevelChunkBridge spongeChunk = ((ActiveChunkReferantBridge) inventory).bridge$getActiveChunk();
spongeChunk.bridge$addTrackedBlockPosition(te.getBlockState().getBlock(), te.getBlockPos(), creator, PlayerTracker.Type.NOTIFIER);
}
});
}
}
use of org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge in project SpongeCommon by SpongePowered.
the class EntityActivationRange method checkIfActive.
/**
* Checks if the entity is active for this tick.
*
* @param entity The entity to check for activity
* @return Whether the given entity should be active
*/
public static boolean checkIfActive(final Entity entity) {
// Never safe to skip fireworks or entities not yet added to chunk
if (entity instanceof Player || entity.level.isClientSide() || !entity.inChunk || entity instanceof FireworkRocketEntity) {
return true;
}
final LevelChunkBridge activeChunk = ((ActiveChunkReferantBridge) entity).bridge$getActiveChunk();
if (activeChunk == null) {
// Should never happen but just in case for mods, always tick
return true;
}
if (!activeChunk.bridge$isActive()) {
return false;
}
// If in forced chunk or is player
if (activeChunk.bridge$isPersistedChunk() || ((PlatformEntityBridge) entity).bridge$isFakePlayer() && entity instanceof ServerPlayer) {
return true;
}
final long currentTick = SpongeCommon.server().getTickCount();
final ActivationCapabilityBridge spongeEntity = (ActivationCapabilityBridge) entity;
boolean isActive = spongeEntity.activation$getActivatedTick() >= currentTick || spongeEntity.activation$getDefaultActivationState();
// Should this entity tick?
if (!isActive) {
if ((currentTick - spongeEntity.activation$getActivatedTick() - 1) % 20 == 0) {
// Check immunities every 20 ticks.
if (EntityActivationRange.checkEntityImmunities(entity)) {
// Triggered some sort of immunity, give 20 full ticks before we check again.
spongeEntity.activation$setActivatedTick(currentTick + 20);
}
isActive = true;
}
// Add a little performance juice to active entities. Skip 1/4 if not immune.
} else if (!spongeEntity.activation$getDefaultActivationState() && entity.tickCount % 4 == 0 && !EntityActivationRange.checkEntityImmunities(entity)) {
isActive = false;
}
if (isActive && !activeChunk.bridge$areNeighborsLoaded()) {
isActive = false;
}
return isActive;
}
use of org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method handleCollideBlockEvent.
public static boolean handleCollideBlockEvent(final Block block, final Level world, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState state, final net.minecraft.world.entity.Entity entity, final Direction direction, final CollisionType type) {
if (world.isClientSide() || pos.getY() <= 0) {
return false;
}
try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
frame.pushCause(entity);
if (entity instanceof CreatorTrackedBridge) {
final CreatorTrackedBridge spongeEntity = (CreatorTrackedBridge) entity;
spongeEntity.tracker$getCreatorUUID().ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user));
}
// TODO: Add target side support
final ServerLocation loc = ServerLocation.of((ServerWorld) world, VecHelper.toVector3d(pos));
final CollideBlockEvent event;
switch(type) {
case MOVE:
event = SpongeEventFactory.createCollideBlockEventMove(frame.currentCause(), (BlockState) state, loc, direction);
break;
case FALL:
event = SpongeEventFactory.createCollideBlockEventFall(frame.currentCause(), (BlockState) state, loc, direction);
break;
case STEP_ON:
event = SpongeEventFactory.createCollideBlockEventStepOn(frame.currentCause(), (BlockState) state, loc, direction);
break;
case INSIDE:
event = SpongeEventFactory.createCollideBlockEventInside(frame.currentCause(), (BlockState) state, loc, direction);
break;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
final boolean cancelled = SpongeCommon.post(event);
if (!cancelled) {
final EntityBridge spongeEntity = (EntityBridge) entity;
if (!pos.equals(spongeEntity.bridge$getLastCollidedBlockPos())) {
final PhaseContext<?> context = PhaseTracker.getInstance().getPhaseContext();
context.applyNotifierIfAvailable(notifier -> {
LevelChunkBridge spongeChunk = ((ActiveChunkReferantBridge) entity).bridge$getActiveChunk();
if (spongeChunk == null) {
spongeChunk = (LevelChunkBridge) world.getChunkAt(pos);
}
spongeChunk.bridge$addTrackedBlockPosition(block, pos, notifier, PlayerTracker.Type.NOTIFIER);
});
}
}
return cancelled;
}
}
Aggregations