CreateMod/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java
simibubi ecfd43938f If you wanna be my lava
- Waterlogged belts and depots now wash contained items when targeted by a fan
- Fixed jump strength of lava diving suit in shallow lava
- Fixed crash when cycling bogey types on a server
- Fixed custom metal bars not able to be mined with a pickaxe
- Contraption mounted storage no longer interacts with modded ender chests (it didn't work correctly)
- Gui inputs no longer play more than one click when scrolled on very quickly
- Fixed Schematics loading with a snowy grass block when their lowest layer contained snow blocks
- Fixed Mechanical Rollers placing blocks into the train tracks when paving steep slopes
- Netherite backtank now depletes air in lava even when the players head is not fully submerged
- Fixed "Any" amount in filters' value settings screen not using a translatable lang entry
- Added dummy lang entries for mangrove windows for crowdin sync
2023-05-24 14:24:16 +02:00

255 lines
7.4 KiB
Java

package com.simibubi.create.content.schematics;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.BBHelper;
import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.AbstractFurnaceBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.ticks.BlackholeTickAccess;
import net.minecraft.world.ticks.LevelTickAccess;
import net.minecraftforge.registries.ForgeRegistries;
public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor {
protected Map<BlockPos, BlockState> blocks;
protected Map<BlockPos, BlockEntity> blockEntities;
protected List<BlockEntity> renderedBlockEntities;
protected List<Entity> entities;
protected BoundingBox bounds;
public BlockPos anchor;
public boolean renderMode;
public SchematicWorld(Level original) {
this(BlockPos.ZERO, original);
}
public SchematicWorld(BlockPos anchor, Level original) {
super(original);
setChunkSource(new SchematicChunkSource(this));
this.blocks = new HashMap<>();
this.blockEntities = new HashMap<>();
this.bounds = new BoundingBox(BlockPos.ZERO);
this.anchor = anchor;
this.entities = new ArrayList<>();
this.renderedBlockEntities = new ArrayList<>();
}
public Set<BlockPos> getAllPositions() {
return blocks.keySet();
}
@Override
public boolean addFreshEntity(Entity entityIn) {
if (entityIn instanceof ItemFrame itemFrame)
itemFrame.setItem(NBTProcessors.withUnsafeNBTDiscarded(itemFrame.getItem()));
if (entityIn instanceof ArmorStand armorStand)
for (EquipmentSlot equipmentSlot : EquipmentSlot.values())
armorStand.setItemSlot(equipmentSlot,
NBTProcessors.withUnsafeNBTDiscarded(armorStand.getItemBySlot(equipmentSlot)));
return entities.add(entityIn);
}
public Stream<Entity> getEntityStream() {
return entities.stream();
}
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
if (isOutsideBuildHeight(pos))
return null;
if (blockEntities.containsKey(pos))
return blockEntities.get(pos);
if (!blocks.containsKey(pos.subtract(anchor)))
return null;
BlockState blockState = getBlockState(pos);
if (blockState.hasBlockEntity()) {
try {
BlockEntity blockEntity = ((EntityBlock) blockState.getBlock()).newBlockEntity(pos, blockState);
if (blockEntity != null) {
onBEadded(blockEntity, pos);
blockEntities.put(pos, blockEntity);
renderedBlockEntities.add(blockEntity);
}
return blockEntity;
} catch (Exception e) {
Create.LOGGER.debug("Could not create BlockEntity of block " + blockState, e);
}
}
return null;
}
protected void onBEadded(BlockEntity blockEntity, BlockPos pos) {
blockEntity.setLevel(this);
}
@Override
public BlockState getBlockState(BlockPos globalPos) {
BlockPos pos = globalPos.subtract(anchor);
if (pos.getY() - bounds.minY() == -1 && !renderMode)
return Blocks.DIRT.defaultBlockState();
if (getBounds().isInside(pos) && blocks.containsKey(pos))
return processBlockStateForPrinting(blocks.get(pos));
return Blocks.AIR.defaultBlockState();
}
public Map<BlockPos, BlockState> getBlockMap() {
return blocks;
}
@Override
public FluidState getFluidState(BlockPos pos) {
return getBlockState(pos).getFluidState();
}
@Override
public Holder<Biome> getBiome(BlockPos pos) {
return ForgeRegistries.BIOMES.getHolder(Biomes.PLAINS.location())
.orElse(null);
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos pos) {
return 15;
}
@Override
public float getShade(Direction face, boolean hasShade) {
return 1f;
}
@Override
public LevelTickAccess<Block> getBlockTicks() {
return BlackholeTickAccess.emptyLevelList();
}
@Override
public LevelTickAccess<Fluid> getFluidTicks() {
return BlackholeTickAccess.emptyLevelList();
}
@Override
public List<Entity> getEntities(Entity arg0, AABB arg1, Predicate<? super Entity> arg2) {
return Collections.emptyList();
}
@Override
public <T extends Entity> List<T> getEntitiesOfClass(Class<T> arg0, AABB arg1, Predicate<? super T> arg2) {
return Collections.emptyList();
}
@Override
public List<? extends Player> players() {
return Collections.emptyList();
}
@Override
public int getSkyDarken() {
return 0;
}
@Override
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> predicate) {
return predicate.test(getBlockState(pos));
}
@Override
public boolean destroyBlock(BlockPos arg0, boolean arg1) {
return setBlock(arg0, Blocks.AIR.defaultBlockState(), 3);
}
@Override
public boolean removeBlock(BlockPos arg0, boolean arg1) {
return setBlock(arg0, Blocks.AIR.defaultBlockState(), 3);
}
@Override
public boolean setBlock(BlockPos pos, BlockState arg1, int arg2) {
pos = pos.immutable()
.subtract(anchor);
bounds = BBHelper.encapsulate(bounds, pos);
blocks.put(pos, arg1);
if (blockEntities.containsKey(pos)) {
BlockEntity blockEntity = blockEntities.get(pos);
if (!blockEntity.getType()
.isValid(arg1)) {
blockEntities.remove(pos);
renderedBlockEntities.remove(blockEntity);
}
}
BlockEntity blockEntity = getBlockEntity(pos);
if (blockEntity != null)
blockEntities.put(pos, blockEntity);
return true;
}
@Override
public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) {}
public BoundingBox getBounds() {
return bounds;
}
public Iterable<BlockEntity> getBlockEntities() {
return blockEntities.values();
}
public Iterable<BlockEntity> getRenderedBlockEntities() {
return renderedBlockEntities;
}
protected BlockState processBlockStateForPrinting(BlockState state) {
if (state.getBlock() instanceof AbstractFurnaceBlock && state.hasProperty(BlockStateProperties.LIT))
state = state.setValue(BlockStateProperties.LIT, false);
return state;
}
@Override
public ServerLevel getLevel() {
if (this.world instanceof ServerLevel) {
return (ServerLevel) this.world;
}
throw new IllegalStateException("Cannot use IServerWorld#getWorld in a client environment");
}
}