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