use of net.minecraft.world.level.chunk.LevelChunk in project SpongeCommon by SpongePowered.
the class LevelChunkMixin_API method biomeStream.
@Override
public VolumeStream<WorldChunk, Biome> biomeStream(final Vector3i min, final Vector3i max, final StreamOptions options) {
VolumeStreamUtils.validateStreamArgs(Objects.requireNonNull(min, "min"), Objects.requireNonNull(max, "max"), Objects.requireNonNull(options, "options"));
final boolean shouldCarbonCopy = options.carbonCopy();
final Vector3i size = max.sub(min).add(1, 1, 1);
@MonotonicNonNull final ObjectArrayMutableBiomeBuffer backingVolume;
if (shouldCarbonCopy) {
final Registry<net.minecraft.world.level.biome.Biome> biomeRegistry = this.level.registryAccess().registry(Registry.BIOME_REGISTRY).map(wr -> ((Registry<net.minecraft.world.level.biome.Biome>) wr)).orElse(BuiltinRegistries.BIOME);
backingVolume = new ObjectArrayMutableBiomeBuffer(min, size, VolumeStreamUtils.nativeToSpongeRegistry(biomeRegistry));
} else {
backingVolume = null;
}
return VolumeStreamUtils.<WorldChunk, Biome, net.minecraft.world.level.biome.Biome, ChunkAccess, BlockPos>generateStream(options, // Ref
(WorldChunk) this, (LevelChunk) (Object) this, // Entity Accessor
VolumeStreamUtils.getBiomesForChunkByPos((LevelReader) (Object) this, min, max), // IdentityFunction
(pos, biome) -> {
if (shouldCarbonCopy) {
backingVolume.setBiome(pos, biome);
}
}, // Biome by block position
(key, biome) -> key, // Filtered Position Entity Accessor
(blockPos, world) -> {
final net.minecraft.world.level.biome.Biome biome = shouldCarbonCopy ? backingVolume.getNativeBiome(blockPos.getX(), blockPos.getY(), blockPos.getZ()) : ((LevelReader) world.world()).getBiome(blockPos);
return new Tuple<>(blockPos, biome);
});
}
use of net.minecraft.world.level.chunk.LevelChunk in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method bridge$startBlockChange.
@Override
public Optional<WorldPipeline.Builder> bridge$startBlockChange(final BlockPos pos, final BlockState newState, final int flags) {
if (net.minecraft.world.level.Level.isOutsideBuildHeight(pos)) {
return Optional.empty();
} else if (this.shadow$isDebug()) {
// isClientSide is always false since this is WorldServer
return Optional.empty();
}
// Sponge Start - Sanity check against the PhaseTracker for instances
if (this.bridge$isFake()) {
return Optional.empty();
}
final PhaseTracker instance = PhaseTracker.getInstance();
if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
}
final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags);
final LevelChunk chunk = this.shadow$getChunkAt(pos);
if (chunk.isEmpty()) {
return Optional.empty();
}
final net.minecraft.world.level.block.state.BlockState currentState = chunk.getBlockState(pos);
return Optional.of(this.bridge$makePipeline(pos, currentState, newState, chunk, spongeFlag, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
}
use of net.minecraft.world.level.chunk.LevelChunk in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method shadow$addBlockEntity.
@SuppressWarnings({ "ConstantConditions", "RedundantCast" })
@Override
public boolean shadow$addBlockEntity(final net.minecraft.world.level.block.entity.BlockEntity tileEntity) {
if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) {
// out whoever is trying to remove tile entities asynchronously....
return super.shadow$addBlockEntity(tileEntity);
}
// 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 BlockPos immutable = tileEntity.getBlockPos().immutable();
if (tileEntity.getLevel() != (ServerLevel) (Object) this) {
tileEntity.setLevelAndPosition((ServerLevel) (Object) this, immutable);
}
final ChunkAccess iChunk = this.shadow$getChunk(immutable.getX() >> 4, immutable.getZ() >> 4, ChunkStatus.FULL, false);
if (!(iChunk instanceof LevelChunk)) {
return super.shadow$addBlockEntity(tileEntity);
}
final LevelChunk chunk = this.shadow$getChunkAt(immutable);
if (current.getTransactor().logTileAddition(tileEntity, () -> (ServerLevel) (Object) this, chunk)) {
final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable).addEffect(AddTileEntityToWorldWhileProcessingEffect.getInstance()).addEffect(AddTileEntityToLoadedListInWorldEffect.getInstance()).addEffect(AddTileEntityToTickableListEffect.getInstance()).addEffect(TileOnLoadDuringAddToWorldEffect.getInstance()).build();
return pipeline.processEffects(current, new PipelineCursor(tileEntity.getBlockState(), 0, immutable, tileEntity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
}
}
return super.shadow$addBlockEntity(tileEntity);
}
use of net.minecraft.world.level.chunk.LevelChunk in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method destroyBlock.
@Override
public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final Entity p_241212_3_, final int limit) {
final BlockState currentState = this.shadow$getBlockState(pos);
if (currentState.isAir()) {
return false;
} else {
// Sponge Start - Sanity check against the PhaseTracker for instances
if (this.bridge$isFake()) {
return super.destroyBlock(pos, doDrops, p_241212_3_, limit);
}
final PhaseTracker instance = PhaseTracker.getInstance();
if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
}
final FluidState fluidstate = this.shadow$getFluidState(pos);
final BlockState emptyBlock = fluidstate.createLegacyBlock();
final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(3);
final LevelChunk chunk = this.shadow$getChunkAt(pos);
if (chunk.isEmpty()) {
return false;
}
final WorldPipeline.Builder pipelineBuilder = this.bridge$makePipeline(pos, currentState, emptyBlock, chunk, spongeFlag, limit).addEffect(WorldDestroyBlockLevelEffect.getInstance());
if (doDrops) {
pipelineBuilder.addEffect(PerformBlockDropsFromDestruction.getInstance());
}
final WorldPipeline pipeline = pipelineBuilder.addEffect(WorldBlockChangeCompleteEffect.getInstance()).build();
return pipeline.processEffects(instance.getPhaseContext(), currentState, emptyBlock, pos, p_241212_3_, spongeFlag, limit);
}
}
use of net.minecraft.world.level.chunk.LevelChunk in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method setBlock.
/**
* @author gabizou, March 12th, 2016
* <p>
* Move this into WorldServer as we should not be modifying the client world.
* <p>
* Purpose: Rewritten to support capturing blocks
*/
@Override
public boolean setBlock(final BlockPos pos, final net.minecraft.world.level.block.state.BlockState newState, final int flags, final int limit) {
if (net.minecraft.world.level.Level.isOutsideBuildHeight(pos)) {
return false;
} else if (this.shadow$isDebug()) {
// isClientSide is always false since this is WorldServer
return false;
}
// Sponge Start - Sanity check against the PhaseTracker for instances
if (this.bridge$isFake()) {
return super.setBlock(pos, newState, flags, limit);
}
final PhaseTracker instance = PhaseTracker.getInstance();
if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
}
final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags);
final LevelChunk chunk = this.shadow$getChunkAt(pos);
if (chunk.isEmpty()) {
return false;
}
final net.minecraft.world.level.block.state.BlockState currentState = chunk.getBlockState(pos);
// change of "don't do anything if the block is the same".
if (currentState == newState) {
return false;
}
final WorldPipeline pipeline = this.bridge$makePipeline(pos, currentState, newState, chunk, spongeFlag, limit).addEffect(WorldBlockChangeCompleteEffect.getInstance()).build();
return pipeline.processEffects(instance.getPhaseContext(), currentState, newState, pos, null, spongeFlag, limit);
}
Aggregations