package mhfc.net.common.world.area; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; import mhfc.net.common.world.AreaTeleportation; import mhfc.net.common.world.controller.CornerPosition; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Vec3; import net.minecraft.world.IWorldAccess; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.util.ForgeDirection; public class DisplacedView implements IWorldView { private int chunkDeltaX, chunkDeltaZ; private int addX, addZ; private int dimensionX, dimensionZ; private World worldObj; public DisplacedView(CornerPosition chunkCorner, AreaConfiguration configuration, World world) { chunkDeltaX = chunkCorner.posX; chunkDeltaZ = chunkCorner.posY; dimensionX = configuration.getChunkSizeX(); dimensionZ = configuration.getChunkSizeZ(); worldObj = Objects.requireNonNull(world); addX = chunkDeltaX << 4; addZ = chunkDeltaZ << 4; } public int getChunkDeltaX() { return chunkDeltaX; } public int getChunkDeltaZ() { return chunkDeltaZ; } public int getAddX() { return addX; } public int getAddZ() { return addZ; } public int getDimensionX() { return dimensionX; } public int getDimensionZ() { return dimensionZ; } private boolean isInBoundary(double x, double y, double z) { return x >= 0 && y >= 0 && z >= 0 && x < dimensionX * 16 && z < dimensionZ * 16 && y < worldObj.getActualHeight(); } @Override public boolean isDaytime() { return worldObj.isDaytime(); } @Override public boolean isThundering() { return worldObj.isThundering(); } @Override public boolean isRaining() { return worldObj.isRaining(); } @Override public void markBlockForUpdate(int x, int y, int z) { worldObj.markBlockForUpdate(x + addX, y, z + addZ); } @Override public boolean isAirBlock(int x, int y, int z) { if (!isInBoundary(x, y, z)) return true; return worldObj.isAirBlock(x + addX, y, z + addZ); } @Override public boolean blockExists(int x, int y, int z) { if (!isInBoundary(x, y, z)) return false; return worldObj.blockExists(x + addX, y, z + addZ); } @Override public Chunk getChunkFromBlockCoords(int x, int z) { if (!isInBoundary(x, 0, z)) return null; return worldObj.getChunkFromBlockCoords(x + addX, z + addZ); } @Override public Block getTopBlock(int x, int z) { if (!isInBoundary(x, 0, z)) return Blocks.air; return worldObj.getTopBlock(x + addX, z + addZ); } @Override public int getTopSolidOrLiquidBlock(int x, int z) { if (!isInBoundary(x, 0, z)) return -1; return worldObj.getTopSolidOrLiquidBlock(x + addX, z + addZ); } @Override public Block getBlock(int x, int y, int z) { if (!isInBoundary(x, y, z)) return Blocks.air; return worldObj.getBlock(x + addX, y, z + addZ); } @Override public int getBlockMetadata(int x, int y, int z) { if (!isInBoundary(x, y, z)) return 0; return worldObj.getBlockMetadata(x + addX, y, z + addZ); } @Override public boolean setBlockToAir(int x, int y, int z) { if (!isInBoundary(x, y, z)) return false; return worldObj.setBlockToAir(x + addX, y, z + addZ); } @Override public boolean setBlock(int x, int y, int z, Block block) { if (!isInBoundary(x, y, z)) return false; return worldObj.setBlock(x + addX, y, z + addZ, block); } @Override public boolean setBlock(int x, int y, int z, Block block, int metadata, int flags) { if (!isInBoundary(x, y, z)) return false; return worldObj.setBlock(x + addX, y, z + addZ, block, metadata, flags); } @Override public void playSoundEffect(double x, double y, double z, String soundName, float p_72908_8_, float p_72908_9_) { if (!isInBoundary(x, y, z)) return; worldObj.playSoundEffect(x + addX, y, z + addZ, soundName, p_72908_8_, p_72908_9_); } @Override public void playSound( double x, double y, double z, String soundName, float volume, float p_72980_9_, boolean p_72980_10_) { if (!isInBoundary(x, y, z)) return; worldObj.playSound(x + addX, y, z + addZ, soundName, volume, p_72980_9_, p_72980_10_); } @Override public void spawnParticle( String particleName, double x, double y, double z, double velX, double velY, double velZ) { if (!isInBoundary(x, y, z)) return; worldObj.spawnParticle(particleName, x + addX, y, z + addZ, velX, velY, velZ); } @Override public void onEntityAdded(Entity entity) { worldObj.onEntityAdded(entity); } @Override public void onEntityRemoved(Entity entity) { worldObj.onEntityRemoved(entity); } @Override public void removeEntity(Entity entity) { worldObj.removeEntity(entity); } @Override public void addWorldAccess(IWorldAccess worldAccess) { worldObj.addWorldAccess(worldAccess); } @Override public void removeWorldAccess(IWorldAccess worldAccess) { worldObj.removeWorldAccess(worldAccess); } @Override public TileEntity getTileEntity(int x, int y, int z) { if (!isInBoundary(x, y, z)) return null; return worldObj.getTileEntity(x + addX, y, z + addZ); } @Override public void setTileEntity(int x, int y, int z, TileEntity tileEntity) { if (!isInBoundary(x, y, z)) return; worldObj.setTileEntity(x + addX, y, z + addZ, tileEntity); } @Override public void removeTileEntity(int x, int y, int z) { if (!isInBoundary(x, y, z)) return; worldObj.removeTileEntity(x + addX, y, z + addZ); } @Override public int countEntities(Class<? extends Entity> entityClass) { @SuppressWarnings("unchecked") Stream<Entity> entStream = worldObj.loadedEntityList.stream(); return entStream.filter((e) -> entityClass.isAssignableFrom(e.getClass())) .filter((e) -> isInBoundary(e.posX - addX, e.posY, e.posZ - addZ)).collect(Collectors.counting()) .intValue(); } @Override public int getBlockPowerInput(int x, int y, int z) { if (!isInBoundary(x, y, z)) return 0; return worldObj.getBlockPowerInput(x + addX, y, z + addZ); } @Override public boolean canMineBlock(EntityPlayer player, int x, int y, int z) { if (!isInBoundary(x, y, z)) return false; return worldObj.canMineBlock(player, x + addX, y, z + addZ); } @Override public void addTileEntity(TileEntity entity) { worldObj.addTileEntity(entity); entity.setWorldObj(worldObj); entity.xCoord += addX; entity.zCoord += addZ; } @Override public boolean isSideSolid(int x, int y, int z, ForgeDirection side) { if (!isInBoundary(x, y, z)) return false; return worldObj.isSideSolid(x + addX, y, z + addZ, side); } @Override public boolean isManaged(double relX, double relY, double relZ) { return isInBoundary(relX, relY, relZ); } @Override public boolean spawnEntityAt(Entity entity, double x, double y, double z) { entity.worldObj = worldObj; if (entity instanceof EntityLivingBase) { ((EntityLivingBase) entity).setPositionAndUpdate(x + addX, y, z + addZ); } else { entity.setLocationAndAngles(x + addX, y, z + addZ, 0, 0); } if (!worldObj.spawnEntityInWorld(entity)) return false; return true; } @Override public World getWorldObject() { return worldObj; } public void moveEntityTo(Entity entity, double posX, double posY, double posZ) { posX += addX; posZ += addZ; AreaTeleportation.moveEntityTo(entity, posX, posY, posZ); } @Override public Vec3 convertToLocal(Vec3 global) { return global.addVector(-addX, 0, -addZ); } @Override public Vec3 convertToGlobal(Vec3 local) { return local.addVector(addX, 0, addZ); } }