Search in sources :

Example 1 with LevelChunkBridge

use of org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge 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);
    }
}
Also used : CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) BlockEntityBridge(org.spongepowered.common.bridge.world.level.block.entity.BlockEntityBridge) ActiveChunkReferantBridge(org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge) ViewableInventoryBridge(org.spongepowered.common.bridge.world.inventory.ViewableInventoryBridge) ServerPlayer(net.minecraft.server.level.ServerPlayer) BlockPos(net.minecraft.core.BlockPos) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) TrackedLevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.TrackedLevelChunkBridge) Timing(co.aikar.timings.Timing) TileEntityTickContext(org.spongepowered.common.event.tracking.phase.tick.TileEntityTickContext) TickableBlockEntity(net.minecraft.world.level.block.entity.TickableBlockEntity) BlockEntity(org.spongepowered.api.block.entity.BlockEntity)

Example 2 with LevelChunkBridge

use of org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge in project SpongeCommon by SpongePowered.

the class TrackingUtil method getNotifierOrOwnerFromBlock.

@Nullable
public static UUID getNotifierOrOwnerFromBlock(final ServerLevel world, final BlockPos blockPos) {
    final LevelChunkBridge mixinChunk = (LevelChunkBridge) world.getChunkAt(blockPos);
    final UUID notifier = mixinChunk.bridge$getBlockNotifierUUID(blockPos).orElse(null);
    if (notifier != null) {
        return notifier;
    }
    return mixinChunk.bridge$getBlockCreatorUUID(blockPos).orElse(null);
}
Also used : LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) TrackedLevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.TrackedLevelChunkBridge) UUID(java.util.UUID) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 3 with LevelChunkBridge

use of org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge 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;
    }
}
Also used : CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) BlockState(org.spongepowered.api.block.BlockState) ServerLocation(org.spongepowered.api.world.server.ServerLocation) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) CollideBlockEvent(org.spongepowered.api.event.block.CollideBlockEvent) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) PlatformEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformEntityBridge) ActiveChunkReferantBridge(org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge)

Example 4 with LevelChunkBridge

use of org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge 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;
}
Also used : Player(net.minecraft.world.entity.player.Player) ServerPlayer(net.minecraft.server.level.ServerPlayer) ActivationCapabilityBridge(org.spongepowered.common.bridge.activation.ActivationCapabilityBridge) ServerPlayer(net.minecraft.server.level.ServerPlayer) FireworkRocketEntity(net.minecraft.world.entity.projectile.FireworkRocketEntity) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) PlatformEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformEntityBridge) ActiveChunkReferantBridge(org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge)

Example 5 with LevelChunkBridge

use of org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge in project SpongeCommon by SpongePowered.

the class ServerLocationData method register.

// @formatter:off
public static void register(final DataProviderRegistrator registrator) {
    registrator.asMutable(ServerLocation.class).create(Keys.BIOME_TEMPERATURE).get(h -> {
        final Level world = (Level) h.world();
        final BlockPos pos = VecHelper.toBlockPos(h);
        final Biome biome = world.getBiome(pos);
        return (double) biome.getBaseTemperature();
    }).create(Keys.BLOCK_LIGHT).get(h -> {
        final Level world = (Level) h.world();
        return world.getBrightness(LightLayer.BLOCK, VecHelper.toBlockPos(h));
    }).create(Keys.BLOCK_TEMPERATURE).get(h -> {
        final Level world = (Level) h.world();
        final BlockPos pos = VecHelper.toBlockPos(h);
        final Biome biome = world.getBiome(pos);
        return (double) biome.getTemperature(pos);
    }).create(Keys.SKY_LIGHT).get(h -> {
        final Level world = (Level) h.world();
        final BlockPos pos = VecHelper.toBlockPos(h);
        return world.getBrightness(LightLayer.SKY, pos);
    }).create(Keys.IS_FULL_BLOCK).get(h -> {
        final BlockState block = (BlockState) h.block();
        final Level world = (Level) h.world();
        final BlockPos pos = VecHelper.toBlockPos(h.position());
        return block.isSolidRender(world, pos);
    }).create(Keys.IS_INDIRECTLY_POWERED).get(h -> {
        final Level world = (Level) h.world();
        final BlockPos pos = VecHelper.toBlockPos(h);
        return world.getBestNeighborSignal(pos) > 0;
    }).create(Keys.DISPLAY_NAME).get(h -> SpongeAdventure.asAdventure(((Nameable) h.blockEntity().get()).getDisplayName())).supports(h -> h.blockEntity().isPresent() && h.blockEntity().get() instanceof NameableBlockEntity).create(Keys.CUSTOM_NAME).get(h -> {
        final BlockEntity blockEntity = h.blockEntity().get();
        return ((Nameable) blockEntity).hasCustomName() ? SpongeAdventure.asAdventure(((Nameable) blockEntity).getCustomName()) : null;
    }).set((h, v) -> (((CustomNameableBridge) h.blockEntity().get())).bridge$setCustomDisplayName(SpongeAdventure.asVanilla(v))).delete(h -> (((CustomNameableBridge) h.blockEntity().get())).bridge$setCustomDisplayName(null)).supports(h -> h.blockEntity().isPresent() && h.blockEntity().get() instanceof NameableBlockEntity).create(Keys.CREATOR).get(h -> ((LevelChunkBridge) h.world().chunk(h.chunkPosition())).bridge$getBlockCreatorUUID(VecHelper.toBlockPos(h.blockPosition())).orElse(null)).set((h, v) -> ((LevelChunkBridge) h.world().chunk(h.chunkPosition())).bridge$setBlockCreator(VecHelper.toBlockPos(h.blockPosition()), v)).delete(h -> ((LevelChunkBridge) h.world().chunk(h.chunkPosition())).bridge$setBlockCreator(VecHelper.toBlockPos(h.blockPosition()), null)).create(Keys.NOTIFIER).get(h -> ((LevelChunkBridge) h.world().chunk(h.chunkPosition())).bridge$getBlockNotifierUUID(VecHelper.toBlockPos(h.blockPosition())).orElse(null)).set((h, v) -> ((LevelChunkBridge) h.world().chunk(h.chunkPosition())).bridge$setBlockNotifier(VecHelper.toBlockPos(h.blockPosition()), v)).delete(h -> ((LevelChunkBridge) h.world().chunk(h.chunkPosition())).bridge$setBlockNotifier(VecHelper.toBlockPos(h.blockPosition()), null));
}
Also used : Nameable(net.minecraft.world.Nameable) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) BlockState(net.minecraft.world.level.block.state.BlockState) NameableBlockEntity(org.spongepowered.api.block.entity.NameableBlockEntity) SpongeAdventure(org.spongepowered.common.adventure.SpongeAdventure) Biome(net.minecraft.world.level.biome.Biome) Keys(org.spongepowered.api.data.Keys) BlockPos(net.minecraft.core.BlockPos) Nameable(net.minecraft.world.Nameable) DataProviderRegistrator(org.spongepowered.common.data.provider.DataProviderRegistrator) VecHelper(org.spongepowered.common.util.VecHelper) LightLayer(net.minecraft.world.level.LightLayer) Level(net.minecraft.world.level.Level) ServerLocation(org.spongepowered.api.world.server.ServerLocation) CustomNameableBridge(org.spongepowered.common.bridge.CustomNameableBridge) CustomNameableBridge(org.spongepowered.common.bridge.CustomNameableBridge) Biome(net.minecraft.world.level.biome.Biome) BlockState(net.minecraft.world.level.block.state.BlockState) Level(net.minecraft.world.level.Level) BlockPos(net.minecraft.core.BlockPos) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) NameableBlockEntity(org.spongepowered.api.block.entity.NameableBlockEntity) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) NameableBlockEntity(org.spongepowered.api.block.entity.NameableBlockEntity)

Aggregations

LevelChunkBridge (org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge)23 BlockPos (net.minecraft.core.BlockPos)9 LevelChunk (net.minecraft.world.level.chunk.LevelChunk)8 CreatorTrackedBridge (org.spongepowered.common.bridge.CreatorTrackedBridge)6 UUID (java.util.UUID)5 SpongeBlockSnapshot (org.spongepowered.common.block.SpongeBlockSnapshot)5 CompoundTag (net.minecraft.nbt.CompoundTag)4 ServerLocation (org.spongepowered.api.world.server.ServerLocation)4 ActiveChunkReferantBridge (org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge)4 TrackedLevelChunkBridge (org.spongepowered.common.bridge.world.level.chunk.TrackedLevelChunkBridge)4 ListTag (net.minecraft.nbt.ListTag)3 Block (net.minecraft.world.level.block.Block)3 CauseStackManager (org.spongepowered.api.event.CauseStackManager)3 Direction (org.spongepowered.api.util.Direction)3 Redirect (org.spongepowered.asm.mixin.injection.Redirect)3 Timing (co.aikar.timings.Timing)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Optional (java.util.Optional)2