Search in sources :

Example 1 with BlockEntity

use of org.spongepowered.api.block.entity.BlockEntity in project SpongeCommon by SpongePowered.

the class InventoryUtil method getPluginContainer.

public static PluginContainer getPluginContainer(Object inventory) {
    // TODO maybe caching?
    final PluginContainer container;
    if (inventory instanceof CustomInventory) {
        return ((CustomInventory) inventory).getPlugin();
    }
    if (inventory instanceof CarriedInventory) {
        final Optional<?> carrier = ((CarriedInventory<?>) inventory).carrier();
        if (carrier.isPresent()) {
            inventory = carrier.get();
        }
    }
    final Object base = inventory;
    if (base instanceof BlockEntity) {
        final ResourceKey key = Sponge.game().registry(RegistryTypes.BLOCK_ENTITY_TYPE).valueKey(((BlockEntity) base).type());
        final String pluginId = key.namespace();
        container = Sponge.pluginManager().plugin(pluginId).orElseThrow(() -> new AssertionError("Missing plugin " + pluginId + " for block " + key.namespace() + ":" + key.value()));
    } else if (base instanceof Entity) {
        final ResourceKey key = (ResourceKey) (Object) EntityType.getKey((EntityType<?>) ((Entity) base).type());
        final String pluginId = key.namespace();
        container = Sponge.pluginManager().plugin(pluginId).orElseGet(() -> {
            SpongeCommon.logger().debug("Unknown plugin for [{}]", base);
            return Launch.instance().minecraftPlugin();
        });
    } else if (base instanceof SpongeUserData) {
        container = Launch.instance().minecraftPlugin();
    } else {
        container = Sponge.pluginManager().plugin(PlatformHooks.INSTANCE.getInventoryHooks().getModIdFromInventory(base.getClass())).orElseGet(() -> {
            SpongeCommon.logger().debug("Unknown plugin for [{}]", base);
            return Launch.instance().minecraftPlugin();
        });
    }
    return container;
}
Also used : EntityType(net.minecraft.world.entity.EntityType) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) ChestBlockEntity(net.minecraft.world.level.block.entity.ChestBlockEntity) Entity(org.spongepowered.api.entity.Entity) PluginContainer(org.spongepowered.plugin.PluginContainer) CarriedInventory(org.spongepowered.api.item.inventory.type.CarriedInventory) SpongeUserData(org.spongepowered.common.entity.player.SpongeUserData) CustomInventory(org.spongepowered.common.inventory.custom.CustomInventory) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) ChestBlockEntity(net.minecraft.world.level.block.entity.ChestBlockEntity) ResourceKey(org.spongepowered.api.ResourceKey)

Example 2 with BlockEntity

use of org.spongepowered.api.block.entity.BlockEntity 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 3 with BlockEntity

use of org.spongepowered.api.block.entity.BlockEntity in project SpongeCommon by SpongePowered.

the class ServerLevelMixin_Tracker method shadow$setBlockEntity.

@SuppressWarnings({ "RedundantCast", "ConstantConditions" })
@Override
public void shadow$setBlockEntity(final BlockPos pos, final net.minecraft.world.level.block.entity.@Nullable BlockEntity proposed) {
    final BlockPos immutable = pos.immutable();
    if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) {
        // If we're fake or not on the server thread, well, we could effectively call
        // out whoever is trying to remove tile entities asynchronously....
        super.shadow$setBlockEntity(pos, proposed);
        return;
    }
    if (proposed != null) {
        if (proposed.getLevel() != (ServerLevel) (Object) this) {
            proposed.setLevelAndPosition((ServerLevel) (Object) this, immutable);
        } else {
            proposed.setPosition(pos);
        }
    }
    // Otherwise, let's go on and check if we're recording transactions,
    // and if so, log the tile entity removal (may associate with an existing transaction,
    // or create a new transaction.
    final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext();
    if (current.doesBlockEventTracking()) {
        final net.minecraft.world.level.block.entity.@Nullable BlockEntity existing = this.shadow$getChunkAt(immutable).getBlockEntity(immutable);
        if (current.getTransactor().logTileReplacement(immutable, existing, proposed, () -> (ServerLevel) (Object) this)) {
            final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable).addEffect(RemoveProposedTileEntitiesDuringSetIfWorldProcessingEffect.getInstance()).addEffect(ReplaceTileEntityInWorldEffect.getInstance()).build();
            pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), 0, immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
            return;
        }
    }
    super.shadow$setBlockEntity(immutable, proposed);
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) TickableBlockEntity(net.minecraft.world.level.block.entity.TickableBlockEntity) RemoveBlockEntity(org.spongepowered.common.event.tracking.context.transaction.block.RemoveBlockEntity) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) Entity(net.minecraft.world.entity.Entity) TileEntityPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline) PipelineCursor(org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor) BlockPos(net.minecraft.core.BlockPos) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 4 with BlockEntity

use of org.spongepowered.api.block.entity.BlockEntity 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)

Example 5 with BlockEntity

use of org.spongepowered.api.block.entity.BlockEntity in project SpongeCommon by SpongePowered.

the class TileEntityTickPhaseState method appendNotifierToBlockEvent.

@Override
public void appendNotifierToBlockEvent(final TileEntityTickContext context, final TrackedWorldBridge mixinWorldServer, final BlockPos pos, final TrackableBlockEventDataBridge blockEvent) {
    final BlockEntity tickingTile = context.getSource(BlockEntity.class).orElseThrow(TrackingUtil.throwWithContext("Not ticking on a TileEntity!", context));
    blockEvent.bridge$setTickingLocatable(tickingTile.locatableBlock());
    blockEvent.bridge$setTileEntity(tickingTile);
}
Also used : BlockEntity(org.spongepowered.api.block.entity.BlockEntity) SpawnerBlockEntity(net.minecraft.world.level.block.entity.SpawnerBlockEntity)

Aggregations

BlockEntity (org.spongepowered.api.block.entity.BlockEntity)12 BlockPos (net.minecraft.core.BlockPos)6 Nullable (org.checkerframework.checker.nullness.qual.Nullable)4 Entity (org.spongepowered.api.entity.Entity)4 Vector3i (org.spongepowered.math.vector.Vector3i)4 Tuple (net.minecraft.util.Tuple)3 Level (net.minecraft.world.level.Level)3 ChunkAccess (net.minecraft.world.level.chunk.ChunkAccess)3 MonotonicNonNull (org.checkerframework.checker.nullness.qual.MonotonicNonNull)3 ServerLocation (org.spongepowered.api.world.server.ServerLocation)3 Vector3d (org.spongepowered.math.vector.Vector3d)3 Collection (java.util.Collection)2 Optional (java.util.Optional)2 Component (net.kyori.adventure.text.Component)2 CompoundTag (net.minecraft.nbt.CompoundTag)2 TickableBlockEntity (net.minecraft.world.level.block.entity.TickableBlockEntity)2 LevelChunk (net.minecraft.world.level.chunk.LevelChunk)2 EntityType (org.spongepowered.api.entity.EntityType)2 Player (org.spongepowered.api.entity.living.player.Player)2 WorldChunk (org.spongepowered.api.world.chunk.WorldChunk)2