2140 lines
60 KiB
Java
2140 lines
60 KiB
Java
![]() |
package game.world;
|
||
|
|
||
|
import java.util.Collection;
|
||
|
import java.util.Iterator;
|
||
|
import java.util.List;
|
||
|
import java.util.Set;
|
||
|
import java.util.function.Predicate;
|
||
|
|
||
|
import game.ExtMath;
|
||
|
import game.biome.Biome;
|
||
|
import game.block.Block;
|
||
|
import game.block.BlockHopper;
|
||
|
import game.block.BlockLiquid;
|
||
|
import game.block.BlockSlab;
|
||
|
import game.block.BlockSnow;
|
||
|
import game.block.BlockStairs;
|
||
|
import game.block.LeavesType;
|
||
|
import game.collect.Lists;
|
||
|
import game.collect.Sets;
|
||
|
import game.dimension.Dimension;
|
||
|
import game.entity.Entity;
|
||
|
import game.entity.item.EntityExplosion;
|
||
|
import game.entity.npc.EntityNPC;
|
||
|
import game.init.BlockRegistry;
|
||
|
import game.init.Blocks;
|
||
|
import game.init.SoundEvent;
|
||
|
import game.item.ItemStack;
|
||
|
import game.material.Material;
|
||
|
import game.renderer.particle.ParticleType;
|
||
|
import game.rng.Random;
|
||
|
import game.tileentity.ITickable;
|
||
|
import game.tileentity.TileEntity;
|
||
|
|
||
|
public abstract class World implements IWorldAccess {
|
||
|
public static final float[][] BRIGHTNESS = new float[16][16];
|
||
|
static {
|
||
|
for(int l = 0; l < 16; l++) {
|
||
|
float f = (float)l / 15.0f;
|
||
|
for(int i = 0; i <= 15; ++i) {
|
||
|
float f1 = 1.0F - (float)i / 15.0F;
|
||
|
BRIGHTNESS[l][i] = (1.0F - f1) / (f1 * 3.0F + 1.0F) * (1.0F - f) + f;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
public static final float[] MOON_PHASES = new float[] {1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F};
|
||
|
public static final int MAX_SIZE = 67108864;
|
||
|
public static final int HEIGHT = 512;
|
||
|
public static final long START_TIME = 4385238000L;
|
||
|
public static final float ABSOLUTE_ZERO = -273.15f;
|
||
|
// private static final Calendar calendar = Calendar.getInstance();
|
||
|
// private static long lastUpdate;
|
||
|
|
||
|
public final boolean client;
|
||
|
public final boolean debug;
|
||
|
public double gravity = 1.0;
|
||
|
protected long timeFactor = 1L;
|
||
|
public final Random rand = new Random();
|
||
|
public final List<Entity> entities = Lists.<Entity>newArrayList();
|
||
|
protected final List<Entity> unloaded = Lists.<Entity>newArrayList();
|
||
|
protected final List<TileEntity> tiles = Lists.<TileEntity>newArrayList();
|
||
|
protected final List<TileEntity> tickable = Lists.<TileEntity>newArrayList();
|
||
|
protected final List<TileEntity> addedTiles = Lists.<TileEntity>newArrayList();
|
||
|
protected final List<TileEntity> removeTiles = Lists.<TileEntity>newArrayList();
|
||
|
public final List<EntityNPC> players = Lists.<EntityNPC>newArrayList();
|
||
|
public final List<Entity> effects = Lists.<Entity>newArrayList();
|
||
|
protected final IntHashMap<Entity> entityIds = new IntHashMap();
|
||
|
protected final Set<ChunkPos> active = Sets.<ChunkPos>newHashSet();
|
||
|
protected final int[] lightUpdate = new int[32768];
|
||
|
public final Dimension dimension;
|
||
|
|
||
|
protected boolean loadTiles;
|
||
|
protected int subtract;
|
||
|
protected float rain;
|
||
|
protected float darkness;
|
||
|
protected float fog;
|
||
|
protected float temp;
|
||
|
protected Weather weather;
|
||
|
protected long daytime;
|
||
|
|
||
|
// public static Calendar getCurrentDate() {
|
||
|
// long curTime = System.currentTimeMillis();
|
||
|
// if(curTime - lastUpdate >= 30000L) {
|
||
|
// lastUpdate = curTime;
|
||
|
// calendar.setTimeInMillis(curTime);
|
||
|
// }
|
||
|
// return calendar;
|
||
|
// }
|
||
|
|
||
|
public boolean isBlockSolid(BlockPos pos) {
|
||
|
return isSolidSurface(this.getState(pos));
|
||
|
}
|
||
|
|
||
|
public static boolean isSolidSurface(State state) {
|
||
|
Block block = state.getBlock();
|
||
|
return block.getMaterial().isOpaque() && block.isFullCube() ? true
|
||
|
: (block instanceof BlockStairs ? state.getValue(BlockStairs.HALF) == BlockStairs.EnumHalf.TOP
|
||
|
: (block instanceof BlockSlab ? (state.getValue(BlockSlab.DOUBLE) || state.getValue(BlockSlab.FACING) == Facing.UP)
|
||
|
: (block instanceof BlockHopper ? true
|
||
|
: (block instanceof BlockSnow ? ((Integer)state.getValue(BlockSnow.LAYERS)).intValue() == 7
|
||
|
: false))));
|
||
|
}
|
||
|
|
||
|
public static boolean isValid(BlockPos pos) {
|
||
|
return pos.getX() >= -MAX_SIZE && pos.getZ() >= -MAX_SIZE && pos.getX() < MAX_SIZE && pos.getZ() < MAX_SIZE &&
|
||
|
pos.getY() >= 0 && pos.getY() < 512;
|
||
|
}
|
||
|
|
||
|
public static boolean isValidXZ(BlockPos pos) {
|
||
|
return pos.getX() >= -MAX_SIZE && pos.getZ() >= -MAX_SIZE && pos.getX() < MAX_SIZE && pos.getZ() < MAX_SIZE;
|
||
|
}
|
||
|
|
||
|
protected World(Dimension dim, boolean client, boolean debug) {
|
||
|
// this.profiler = profiler;
|
||
|
// this.info = info;
|
||
|
// this.dimInfo = info.getDimension(dim.getDimensionId());
|
||
|
this.dimension = dim;
|
||
|
// this.storage = storage;
|
||
|
this.client = client;
|
||
|
this.debug = debug;
|
||
|
this.weather = dim.getWeather();
|
||
|
}
|
||
|
|
||
|
public void setGravity(float gravity) {
|
||
|
this.gravity = (double)this.dimension.getGravity() * 0.1 * gravity;
|
||
|
if(Math.abs(this.gravity) < 0.075)
|
||
|
this.gravity = Math.signum(this.gravity) * 0.075;
|
||
|
}
|
||
|
|
||
|
public Biome getBiomeGenForCoords(final BlockPos pos) {
|
||
|
if(this.isBlockLoaded(pos))
|
||
|
return this.getChunk(pos).getBiome(pos, null);
|
||
|
else
|
||
|
return Biome.DEF_BIOME;
|
||
|
}
|
||
|
|
||
|
public boolean isAirBlock(BlockPos pos) {
|
||
|
return this.getState(pos).getBlock().getMaterial() == Material.air;
|
||
|
}
|
||
|
|
||
|
public boolean isBlockLoaded(BlockPos pos) {
|
||
|
return this.isBlockLoaded(pos, true);
|
||
|
}
|
||
|
|
||
|
public boolean isBlockLoaded(BlockPos pos, boolean allowEmpty) {
|
||
|
return !isValid(pos) ? false : this.isLoaded(pos.getX() >> 4, pos.getZ() >> 4, allowEmpty);
|
||
|
}
|
||
|
|
||
|
public boolean isAreaLoaded(BlockPos center, int radius) {
|
||
|
return this.isAreaLoaded(center, radius, true);
|
||
|
}
|
||
|
|
||
|
public boolean isAreaLoaded(BlockPos center, int radius, boolean allowEmpty) {
|
||
|
return this.isAreaLoaded(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius,
|
||
|
center.getY() + radius, center.getZ() + radius, allowEmpty);
|
||
|
}
|
||
|
|
||
|
public boolean isAreaLoaded(BlockPos from, BlockPos to) {
|
||
|
return this.isAreaLoaded(from, to, true);
|
||
|
}
|
||
|
|
||
|
public boolean isAreaLoaded(BlockPos from, BlockPos to, boolean allowEmpty) {
|
||
|
return this.isAreaLoaded(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ(), allowEmpty);
|
||
|
}
|
||
|
|
||
|
private boolean isAreaLoaded(int xStart, int yStart, int zStart, int xEnd, int yEnd, int zEnd, boolean allowEmpty) {
|
||
|
if(yEnd >= 0 && yStart < 512) {
|
||
|
xStart = xStart >> 4;
|
||
|
zStart = zStart >> 4;
|
||
|
xEnd = xEnd >> 4;
|
||
|
zEnd = zEnd >> 4;
|
||
|
|
||
|
for(int i = xStart; i <= xEnd; ++i) {
|
||
|
for(int j = zStart; j <= zEnd; ++j) {
|
||
|
if(!this.isLoaded(i, j, allowEmpty)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected boolean isLoaded(int x, int z, boolean allowEmpty) {
|
||
|
return allowEmpty || !this.getChunk(x, z).isEmpty();
|
||
|
}
|
||
|
|
||
|
public Chunk getChunk(BlockPos pos) {
|
||
|
return this.getChunk(pos.getX() >> 4, pos.getZ() >> 4);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Flag 1 will cause a block update Flag 2 will send the change to clients Flag
|
||
|
* 4 prevents the block from being re-rendered on client worlds
|
||
|
*/
|
||
|
public boolean setState(BlockPos pos, State newState, int flags) {
|
||
|
if(!isValid(pos)) {
|
||
|
return false;
|
||
|
}
|
||
|
else if(!this.client && this.debug) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
Chunk chunk = this.getChunk(pos);
|
||
|
Block block = newState.getBlock();
|
||
|
State iblockstate = chunk.setState(pos, newState);
|
||
|
|
||
|
if(iblockstate == null) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
Block block1 = iblockstate.getBlock();
|
||
|
|
||
|
if(block.getLightOpacity() != block1.getLightOpacity() || block.getLightValue() != block1.getLightValue()) {
|
||
|
// this.profiler.start("checkLight");
|
||
|
this.checkLight(pos);
|
||
|
// this.profiler.end();
|
||
|
}
|
||
|
|
||
|
if((flags & 2) != 0 && (!this.client || (flags & 4) == 0) && chunk.isPopulated()) {
|
||
|
this.markBlockForUpdate(pos);
|
||
|
}
|
||
|
|
||
|
if(!this.client && (flags & 1) != 0) {
|
||
|
this.notifyNeighborsRespectDebug(pos, iblockstate.getBlock());
|
||
|
|
||
|
if(block.hasComparatorInputOverride()) {
|
||
|
this.updateComparatorOutputLevel(pos, block);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean setState(BlockPos pos, State state) {
|
||
|
return this.setState(pos, state, 3);
|
||
|
}
|
||
|
|
||
|
public boolean setBlockToAir(BlockPos pos) {
|
||
|
return this.setState(pos, Blocks.air.getState(), 3);
|
||
|
}
|
||
|
|
||
|
public boolean destroyBlock(BlockPos pos, boolean dropBlock) {
|
||
|
State iblockstate = this.getState(pos);
|
||
|
Block block = iblockstate.getBlock();
|
||
|
|
||
|
if(block.getMaterial() == Material.air) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
this.playAuxSFX(2001, pos, BlockRegistry.getStateId(iblockstate));
|
||
|
|
||
|
if(dropBlock) {
|
||
|
block.dropBlockAsItem(this, pos, iblockstate, 0);
|
||
|
}
|
||
|
|
||
|
return this.setState(pos, Blocks.air.getState(), 3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void notifyNeighborsRespectDebug(BlockPos pos, Block blockType) {
|
||
|
if(!this.debug) {
|
||
|
this.notifyNeighborsOfStateChange(pos, blockType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void markBlocksDirtyVertical(int x1, int z1, int x2, int z2) {
|
||
|
if(x2 > z2) {
|
||
|
int i = z2;
|
||
|
z2 = x2;
|
||
|
x2 = i;
|
||
|
}
|
||
|
|
||
|
if(!this.dimension.hasNoLight()) {
|
||
|
for(int j = x2; j <= z2; ++j) {
|
||
|
this.checkLightFor(LightType.SKY, new BlockPos(x1, j, z1));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.markBlockRangeForRenderUpdate(x1, x2, z1, x1, z2, z1);
|
||
|
}
|
||
|
|
||
|
public void markBlockRangeForRenderUpdate(BlockPos rangeMin, BlockPos rangeMax) {
|
||
|
this.markBlockRangeForRenderUpdate(rangeMin.getX(), rangeMin.getY(), rangeMin.getZ(), rangeMax.getX(), rangeMax.getY(), rangeMax.getZ());
|
||
|
}
|
||
|
|
||
|
public void notifyNeighborsOfStateChange(BlockPos pos, Block blockType) {
|
||
|
this.notifyBlockOfStateChange(pos.west(), blockType);
|
||
|
this.notifyBlockOfStateChange(pos.east(), blockType);
|
||
|
this.notifyBlockOfStateChange(pos.down(), blockType);
|
||
|
this.notifyBlockOfStateChange(pos.up(), blockType);
|
||
|
this.notifyBlockOfStateChange(pos.north(), blockType);
|
||
|
this.notifyBlockOfStateChange(pos.south(), blockType);
|
||
|
}
|
||
|
|
||
|
public void notifyNeighborsOfStateExcept(BlockPos pos, Block blockType, Facing skipSide) {
|
||
|
if(skipSide != Facing.WEST) {
|
||
|
this.notifyBlockOfStateChange(pos.west(), blockType);
|
||
|
}
|
||
|
|
||
|
if(skipSide != Facing.EAST) {
|
||
|
this.notifyBlockOfStateChange(pos.east(), blockType);
|
||
|
}
|
||
|
|
||
|
if(skipSide != Facing.DOWN) {
|
||
|
this.notifyBlockOfStateChange(pos.down(), blockType);
|
||
|
}
|
||
|
|
||
|
if(skipSide != Facing.UP) {
|
||
|
this.notifyBlockOfStateChange(pos.up(), blockType);
|
||
|
}
|
||
|
|
||
|
if(skipSide != Facing.NORTH) {
|
||
|
this.notifyBlockOfStateChange(pos.north(), blockType);
|
||
|
}
|
||
|
|
||
|
if(skipSide != Facing.SOUTH) {
|
||
|
this.notifyBlockOfStateChange(pos.south(), blockType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void notifyBlockOfStateChange(BlockPos pos, final Block blockIn) {
|
||
|
if(!this.client) {
|
||
|
State iblockstate = this.getState(pos);
|
||
|
|
||
|
iblockstate.getBlock().onNeighborBlockChange(this, pos, iblockstate, blockIn);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean canSeeSky(BlockPos pos) {
|
||
|
return this.getChunk(pos).canSeeSky(pos);
|
||
|
}
|
||
|
|
||
|
public int getLight(BlockPos pos) {
|
||
|
if(pos.getY() < 0) {
|
||
|
return 0;
|
||
|
}
|
||
|
else {
|
||
|
if(pos.getY() >= 512) {
|
||
|
pos = new BlockPos(pos.getX(), 511, pos.getZ());
|
||
|
}
|
||
|
|
||
|
return this.getChunk(pos).getLightSub(pos, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int getLightFromNeighbors(BlockPos pos) {
|
||
|
return this.getLight(pos, true);
|
||
|
}
|
||
|
|
||
|
private int getLight(BlockPos pos, boolean checkNeighbors) {
|
||
|
if(pos.getX() >= -MAX_SIZE && pos.getZ() >= -MAX_SIZE && pos.getX() < MAX_SIZE && pos.getZ() < MAX_SIZE) {
|
||
|
if(checkNeighbors && this.getState(pos).getBlock().getSumBrightness()) {
|
||
|
int i1 = this.getLight(pos.up(), false);
|
||
|
int i = this.getLight(pos.east(), false);
|
||
|
int j = this.getLight(pos.west(), false);
|
||
|
int k = this.getLight(pos.south(), false);
|
||
|
int l = this.getLight(pos.north(), false);
|
||
|
|
||
|
if(i > i1) {
|
||
|
i1 = i;
|
||
|
}
|
||
|
|
||
|
if(j > i1) {
|
||
|
i1 = j;
|
||
|
}
|
||
|
|
||
|
if(k > i1) {
|
||
|
i1 = k;
|
||
|
}
|
||
|
|
||
|
if(l > i1) {
|
||
|
i1 = l;
|
||
|
}
|
||
|
|
||
|
return i1;
|
||
|
}
|
||
|
else if(pos.getY() < 0) {
|
||
|
return 0;
|
||
|
}
|
||
|
else {
|
||
|
if(pos.getY() >= 512) {
|
||
|
pos = new BlockPos(pos.getX(), 511, pos.getZ());
|
||
|
}
|
||
|
|
||
|
Chunk chunk = this.getChunk(pos);
|
||
|
return chunk.getLightSub(pos, this.subtract);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
return 15;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public BlockPos getHeight(BlockPos pos) {
|
||
|
int i;
|
||
|
|
||
|
if(pos.getX() >= -MAX_SIZE && pos.getZ() >= -MAX_SIZE && pos.getX() < MAX_SIZE && pos.getZ() < MAX_SIZE) {
|
||
|
if(this.isLoaded(pos.getX() >> 4, pos.getZ() >> 4, true)) {
|
||
|
i = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4).getHeight(pos.getX() & 15, pos.getZ() & 15);
|
||
|
}
|
||
|
else {
|
||
|
i = 0;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
i = this.getSeaLevel() + 1;
|
||
|
}
|
||
|
|
||
|
return new BlockPos(pos.getX(), i, pos.getZ());
|
||
|
}
|
||
|
|
||
|
public int getChunksLowestHorizon(int x, int z) {
|
||
|
if(x >= -MAX_SIZE && z >= -MAX_SIZE && x < MAX_SIZE && z < MAX_SIZE) {
|
||
|
if(!this.isLoaded(x >> 4, z >> 4, true)) {
|
||
|
return 0;
|
||
|
}
|
||
|
else {
|
||
|
Chunk chunk = this.getChunk(x >> 4, z >> 4);
|
||
|
return chunk.getLowest();
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
return this.getSeaLevel() + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int getLightFromNeighborsFor(LightType type, BlockPos pos) {
|
||
|
if(this.dimension.hasNoLight() && type == LightType.SKY) {
|
||
|
return 0;
|
||
|
}
|
||
|
else {
|
||
|
if(pos.getY() < 0) {
|
||
|
pos = new BlockPos(pos.getX(), 0, pos.getZ());
|
||
|
}
|
||
|
|
||
|
if(!isValid(pos)) {
|
||
|
return type.defValue;
|
||
|
}
|
||
|
else if(!this.isBlockLoaded(pos)) {
|
||
|
return type.defValue;
|
||
|
}
|
||
|
else if(this.getState(pos).getBlock().getSumBrightness()) {
|
||
|
int i1 = this.getLightFor(type, pos.up());
|
||
|
int i = this.getLightFor(type, pos.east());
|
||
|
int j = this.getLightFor(type, pos.west());
|
||
|
int k = this.getLightFor(type, pos.south());
|
||
|
int l = this.getLightFor(type, pos.north());
|
||
|
|
||
|
if(i > i1) {
|
||
|
i1 = i;
|
||
|
}
|
||
|
|
||
|
if(j > i1) {
|
||
|
i1 = j;
|
||
|
}
|
||
|
|
||
|
if(k > i1) {
|
||
|
i1 = k;
|
||
|
}
|
||
|
|
||
|
if(l > i1) {
|
||
|
i1 = l;
|
||
|
}
|
||
|
|
||
|
return i1;
|
||
|
}
|
||
|
else {
|
||
|
Chunk chunk = this.getChunk(pos);
|
||
|
return chunk.getLight(type, pos);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int getLightFor(LightType type, BlockPos pos) {
|
||
|
if(pos.getY() < 0) {
|
||
|
pos = new BlockPos(pos.getX(), 0, pos.getZ());
|
||
|
}
|
||
|
|
||
|
if(!isValid(pos)) {
|
||
|
return type.defValue;
|
||
|
}
|
||
|
else if(!this.isBlockLoaded(pos)) {
|
||
|
return type.defValue;
|
||
|
}
|
||
|
else {
|
||
|
Chunk chunk = this.getChunk(pos);
|
||
|
return chunk.getLight(type, pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void setLightFor(LightType type, BlockPos pos, int lightValue) {
|
||
|
if(isValid(pos)) {
|
||
|
if(this.isBlockLoaded(pos)) {
|
||
|
Chunk chunk = this.getChunk(pos);
|
||
|
chunk.setLight(type, pos, lightValue);
|
||
|
this.notifyLightSet(pos);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int getCombinedLight(BlockPos pos, int lightValue) {
|
||
|
int i = this.getLightFromNeighborsFor(LightType.SKY, pos);
|
||
|
int j = this.getLightFromNeighborsFor(LightType.BLOCK, pos);
|
||
|
|
||
|
if(j < lightValue) {
|
||
|
j = lightValue;
|
||
|
}
|
||
|
|
||
|
return i << 20 | j << 4;
|
||
|
}
|
||
|
|
||
|
public float getLightBrightness(BlockPos pos) {
|
||
|
return BRIGHTNESS[this.dimension.getBrightness()][this.getLightFromNeighbors(pos)];
|
||
|
}
|
||
|
|
||
|
public State getState(BlockPos pos) {
|
||
|
if(!isValid(pos)) {
|
||
|
return Blocks.air.getState();
|
||
|
}
|
||
|
else {
|
||
|
Chunk chunk = this.getChunk(pos);
|
||
|
return chunk.getState(pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public BlockPos getBlockTrace(Entity entity, int distance) {
|
||
|
double range = (double)distance;
|
||
|
double theta = 0.2;
|
||
|
double yaw = (entity.rotYaw + 90) % 360;
|
||
|
double pitch = entity.rotPitch * -1;
|
||
|
double dist = 0.0;
|
||
|
double h = theta * Math.cos(Math.toRadians(pitch));
|
||
|
Vec3 offset = new Vec3(h * Math.cos(Math.toRadians(yaw)), theta * Math.sin(Math.toRadians(pitch)),
|
||
|
h * Math.sin(Math.toRadians(yaw)));
|
||
|
Vec3 shift = new Vec3(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
|
||
|
BlockPos target = new BlockPos(ExtMath.floord(shift.xCoord), ExtMath.floord(shift.yCoord), ExtMath.floord(shift.zCoord));
|
||
|
BlockPos prev = target;
|
||
|
while(true) {
|
||
|
prev = target;
|
||
|
do {
|
||
|
dist += theta;
|
||
|
shift = offset.addVector(shift.xCoord, shift.yCoord, shift.zCoord);
|
||
|
target = new BlockPos(ExtMath.floord(shift.xCoord), ExtMath.floord(shift.yCoord), ExtMath.floord(shift.zCoord));
|
||
|
}
|
||
|
while(dist <= range && target.getX() == prev.getX() && target.getY() == prev.getY() && target.getZ() == prev.getZ());
|
||
|
if(dist > range)
|
||
|
return null;
|
||
|
if(this.getState(new BlockPos(target.getX(), target.getY(), target.getZ()))
|
||
|
.getBlock().getMaterial().blocksMovement())
|
||
|
break;
|
||
|
List<Entity> ents = this.getEntitiesInAABBexcluding(entity, new BoundingBox(target, target.add(1, 1, 1)),
|
||
|
new Predicate<Entity>() {
|
||
|
public boolean test(Entity entity) {
|
||
|
return entity.canBeCollidedWith();
|
||
|
}
|
||
|
});
|
||
|
if(!ents.isEmpty())
|
||
|
break;
|
||
|
}
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
public HitPosition rayTraceBlocks(Vec3 p_72933_1_, Vec3 p_72933_2_) {
|
||
|
return this.rayTraceBlocks(p_72933_1_, p_72933_2_, false, false, false);
|
||
|
}
|
||
|
|
||
|
public HitPosition rayTraceBlocks(Vec3 start, Vec3 end, boolean stopOnLiquid) {
|
||
|
return this.rayTraceBlocks(start, end, stopOnLiquid, false, false);
|
||
|
}
|
||
|
|
||
|
public HitPosition rayTraceBlocks(Vec3 vec31, Vec3 vec32, boolean stopOnLiquid, boolean ignoreBlockWithoutBoundingBox,
|
||
|
boolean returnLastUncollidableBlock) {
|
||
|
if(!Double.isNaN(vec31.xCoord) && !Double.isNaN(vec31.yCoord) && !Double.isNaN(vec31.zCoord)) {
|
||
|
if(!Double.isNaN(vec32.xCoord) && !Double.isNaN(vec32.yCoord) && !Double.isNaN(vec32.zCoord)) {
|
||
|
int i = ExtMath.floord(vec32.xCoord);
|
||
|
int j = ExtMath.floord(vec32.yCoord);
|
||
|
int k = ExtMath.floord(vec32.zCoord);
|
||
|
int l = ExtMath.floord(vec31.xCoord);
|
||
|
int i1 = ExtMath.floord(vec31.yCoord);
|
||
|
int j1 = ExtMath.floord(vec31.zCoord);
|
||
|
BlockPos blockpos = new BlockPos(l, i1, j1);
|
||
|
State iblockstate = this.getState(blockpos);
|
||
|
Block block = iblockstate.getBlock();
|
||
|
|
||
|
if((!ignoreBlockWithoutBoundingBox || block.getCollisionBoundingBox(this, blockpos, iblockstate) != null)
|
||
|
&& block.canCollideCheck(iblockstate, stopOnLiquid)) {
|
||
|
HitPosition movingobjectposition = block.collisionRayTrace(this, blockpos, vec31, vec32);
|
||
|
|
||
|
if(movingobjectposition != null) {
|
||
|
return movingobjectposition;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HitPosition movingobjectposition2 = null;
|
||
|
int k1 = 200;
|
||
|
|
||
|
while(k1-- >= 0) {
|
||
|
if(Double.isNaN(vec31.xCoord) || Double.isNaN(vec31.yCoord) || Double.isNaN(vec31.zCoord)) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
if(l == i && i1 == j && j1 == k) {
|
||
|
return returnLastUncollidableBlock ? movingobjectposition2 : null;
|
||
|
}
|
||
|
|
||
|
boolean flag2 = true;
|
||
|
boolean flag = true;
|
||
|
boolean flag1 = true;
|
||
|
double d0 = 999.0D;
|
||
|
double d1 = 999.0D;
|
||
|
double d2 = 999.0D;
|
||
|
|
||
|
if(i > l) {
|
||
|
d0 = (double)l + 1.0D;
|
||
|
}
|
||
|
else if(i < l) {
|
||
|
d0 = (double)l + 0.0D;
|
||
|
}
|
||
|
else {
|
||
|
flag2 = false;
|
||
|
}
|
||
|
|
||
|
if(j > i1) {
|
||
|
d1 = (double)i1 + 1.0D;
|
||
|
}
|
||
|
else if(j < i1) {
|
||
|
d1 = (double)i1 + 0.0D;
|
||
|
}
|
||
|
else {
|
||
|
flag = false;
|
||
|
}
|
||
|
|
||
|
if(k > j1) {
|
||
|
d2 = (double)j1 + 1.0D;
|
||
|
}
|
||
|
else if(k < j1) {
|
||
|
d2 = (double)j1 + 0.0D;
|
||
|
}
|
||
|
else {
|
||
|
flag1 = false;
|
||
|
}
|
||
|
|
||
|
double d3 = 999.0D;
|
||
|
double d4 = 999.0D;
|
||
|
double d5 = 999.0D;
|
||
|
double d6 = vec32.xCoord - vec31.xCoord;
|
||
|
double d7 = vec32.yCoord - vec31.yCoord;
|
||
|
double d8 = vec32.zCoord - vec31.zCoord;
|
||
|
|
||
|
if(flag2) {
|
||
|
d3 = (d0 - vec31.xCoord) / d6;
|
||
|
}
|
||
|
|
||
|
if(flag) {
|
||
|
d4 = (d1 - vec31.yCoord) / d7;
|
||
|
}
|
||
|
|
||
|
if(flag1) {
|
||
|
d5 = (d2 - vec31.zCoord) / d8;
|
||
|
}
|
||
|
|
||
|
if(d3 == -0.0D) {
|
||
|
d3 = -1.0E-4D;
|
||
|
}
|
||
|
|
||
|
if(d4 == -0.0D) {
|
||
|
d4 = -1.0E-4D;
|
||
|
}
|
||
|
|
||
|
if(d5 == -0.0D) {
|
||
|
d5 = -1.0E-4D;
|
||
|
}
|
||
|
|
||
|
Facing enumfacing;
|
||
|
|
||
|
if(d3 < d4 && d3 < d5) {
|
||
|
enumfacing = i > l ? Facing.WEST : Facing.EAST;
|
||
|
vec31 = new Vec3(d0, vec31.yCoord + d7 * d3, vec31.zCoord + d8 * d3);
|
||
|
}
|
||
|
else if(d4 < d5) {
|
||
|
enumfacing = j > i1 ? Facing.DOWN : Facing.UP;
|
||
|
vec31 = new Vec3(vec31.xCoord + d6 * d4, d1, vec31.zCoord + d8 * d4);
|
||
|
}
|
||
|
else {
|
||
|
enumfacing = k > j1 ? Facing.NORTH : Facing.SOUTH;
|
||
|
vec31 = new Vec3(vec31.xCoord + d6 * d5, vec31.yCoord + d7 * d5, d2);
|
||
|
}
|
||
|
|
||
|
l = ExtMath.floord(vec31.xCoord) - (enumfacing == Facing.EAST ? 1 : 0);
|
||
|
i1 = ExtMath.floord(vec31.yCoord) - (enumfacing == Facing.UP ? 1 : 0);
|
||
|
j1 = ExtMath.floord(vec31.zCoord) - (enumfacing == Facing.SOUTH ? 1 : 0);
|
||
|
blockpos = new BlockPos(l, i1, j1);
|
||
|
State iblockstate1 = this.getState(blockpos);
|
||
|
Block block1 = iblockstate1.getBlock();
|
||
|
|
||
|
if(!ignoreBlockWithoutBoundingBox || block1.getCollisionBoundingBox(this, blockpos, iblockstate1) != null) {
|
||
|
if(block1.canCollideCheck(iblockstate1, stopOnLiquid)) {
|
||
|
HitPosition movingobjectposition1 = block1.collisionRayTrace(this, blockpos, vec31, vec32);
|
||
|
|
||
|
if(movingobjectposition1 != null) {
|
||
|
return movingobjectposition1;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
movingobjectposition2 = new HitPosition(HitPosition.ObjectType.MISS, vec31, enumfacing, blockpos);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return returnLastUncollidableBlock ? movingobjectposition2 : null;
|
||
|
}
|
||
|
else {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void playSoundAtEntity(Entity entityIn, SoundEvent name, float volume, float pitch) {
|
||
|
this.playSound(name, entityIn.posX, entityIn.posY, entityIn.posZ, volume, pitch);
|
||
|
}
|
||
|
|
||
|
public boolean spawnEntityInWorld(Entity entityIn) {
|
||
|
int i = ExtMath.floord(entityIn.posX / 16.0D);
|
||
|
int j = ExtMath.floord(entityIn.posZ / 16.0D);
|
||
|
boolean flag = entityIn.forceSpawn;
|
||
|
|
||
|
if(entityIn.isPlayer()) {
|
||
|
flag = true;
|
||
|
}
|
||
|
|
||
|
if(!flag && !this.isLoaded(i, j, true)) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
if(entityIn.isPlayer()) {
|
||
|
EntityNPC entityplayer = (EntityNPC)entityIn;
|
||
|
this.players.add(entityplayer);
|
||
|
// this.updateAllPlayersSleepingFlag();
|
||
|
}
|
||
|
|
||
|
this.getChunk(i, j).addEntity(entityIn);
|
||
|
this.entities.add(entityIn);
|
||
|
this.onEntityAdded(entityIn);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void removeEntity(Entity entityIn) {
|
||
|
if(entityIn.passenger != null) {
|
||
|
entityIn.passenger.mountEntity((Entity)null);
|
||
|
}
|
||
|
|
||
|
if(entityIn.vehicle != null) {
|
||
|
entityIn.mountEntity((Entity)null);
|
||
|
}
|
||
|
|
||
|
entityIn.setDead();
|
||
|
|
||
|
if(entityIn.isPlayer()) {
|
||
|
this.players.remove(entityIn);
|
||
|
// this.updateAllPlayersSleepingFlag();
|
||
|
this.onEntityRemoved(entityIn);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public List<BoundingBox> getCollidingBoundingBoxes(Entity entityIn, BoundingBox bb) {
|
||
|
List<BoundingBox> list = Lists.<BoundingBox>newArrayList();
|
||
|
int i = ExtMath.floord(bb.minX);
|
||
|
int j = ExtMath.floord(bb.maxX + 1.0D);
|
||
|
int k = ExtMath.floord(bb.minY);
|
||
|
int l = ExtMath.floord(bb.maxY + 1.0D);
|
||
|
int i1 = ExtMath.floord(bb.minZ);
|
||
|
int j1 = ExtMath.floord(bb.maxZ + 1.0D);
|
||
|
// Border worldborder = this.getWorldBorder();
|
||
|
boolean flag = entityIn.isOutsideBorder();
|
||
|
boolean flag1 = this.isInsideBorder(entityIn);
|
||
|
State iblockstate = Blocks.stone.getState();
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(int k1 = i; k1 < j; ++k1) {
|
||
|
for(int l1 = i1; l1 < j1; ++l1) {
|
||
|
if(this.isBlockLoaded(blockpos$mutableblockpos.set(k1, 64, l1))) {
|
||
|
for(int i2 = k - 1; i2 < l; ++i2) {
|
||
|
blockpos$mutableblockpos.set(k1, i2, l1);
|
||
|
|
||
|
if(flag && flag1) {
|
||
|
entityIn.setOutsideBorder(false);
|
||
|
}
|
||
|
else if(!flag && !flag1) {
|
||
|
entityIn.setOutsideBorder(true);
|
||
|
}
|
||
|
|
||
|
State iblockstate1 = iblockstate;
|
||
|
|
||
|
if(isValidXZ(blockpos$mutableblockpos) || !flag1) {
|
||
|
iblockstate1 = this.getState(blockpos$mutableblockpos);
|
||
|
}
|
||
|
|
||
|
iblockstate1.getBlock().addCollisionBoxesToList(this, blockpos$mutableblockpos, iblockstate1, bb, list, entityIn);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double d0 = 0.25D;
|
||
|
List<Entity> list1 = this.getEntitiesWithinAABBExcludingEntity(entityIn, bb.expand(d0, d0, d0));
|
||
|
|
||
|
for(int j2 = 0; j2 < list1.size(); ++j2) {
|
||
|
if(entityIn.passenger != list1 && entityIn.vehicle != list1) {
|
||
|
BoundingBox axisalignedbb = ((Entity)list1.get(j2)).getCollisionBoundingBox();
|
||
|
|
||
|
if(axisalignedbb != null && axisalignedbb.intersectsWith(bb)) {
|
||
|
list.add(axisalignedbb);
|
||
|
}
|
||
|
|
||
|
axisalignedbb = entityIn.getCollisionBox((Entity)list1.get(j2));
|
||
|
|
||
|
if(axisalignedbb != null && axisalignedbb.intersectsWith(bb)) {
|
||
|
list.add(axisalignedbb);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
private boolean isInsideBorder(Entity entityIn) {
|
||
|
double d0 = (double)-MAX_SIZE; // worldBorderIn.minX();
|
||
|
double d2 = (double)MAX_SIZE; // worldBorderIn.maxX();
|
||
|
|
||
|
if(entityIn.isOutsideBorder()) {
|
||
|
++d0;
|
||
|
--d2;
|
||
|
}
|
||
|
else {
|
||
|
--d0;
|
||
|
++d2;
|
||
|
}
|
||
|
|
||
|
return entityIn.posX > d0 && entityIn.posX < d2 && entityIn.posZ > d0 && entityIn.posZ < d2;
|
||
|
}
|
||
|
|
||
|
public List<BoundingBox> getCollisionBoxes(BoundingBox bb) {
|
||
|
List<BoundingBox> list = Lists.<BoundingBox>newArrayList();
|
||
|
int i = ExtMath.floord(bb.minX);
|
||
|
int j = ExtMath.floord(bb.maxX + 1.0D);
|
||
|
int k = ExtMath.floord(bb.minY);
|
||
|
int l = ExtMath.floord(bb.maxY + 1.0D);
|
||
|
int i1 = ExtMath.floord(bb.minZ);
|
||
|
int j1 = ExtMath.floord(bb.maxZ + 1.0D);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(int k1 = i; k1 < j; ++k1) {
|
||
|
for(int l1 = i1; l1 < j1; ++l1) {
|
||
|
if(this.isBlockLoaded(blockpos$mutableblockpos.set(k1, 64, l1))) {
|
||
|
for(int i2 = k - 1; i2 < l; ++i2) {
|
||
|
blockpos$mutableblockpos.set(k1, i2, l1);
|
||
|
State iblockstate;
|
||
|
|
||
|
if(k1 >= -MAX_SIZE && k1 < MAX_SIZE && l1 >= -MAX_SIZE && l1 < MAX_SIZE) {
|
||
|
iblockstate = this.getState(blockpos$mutableblockpos);
|
||
|
}
|
||
|
else {
|
||
|
iblockstate = Blocks.bedrock.getState();
|
||
|
}
|
||
|
|
||
|
iblockstate.getBlock().addCollisionBoxesToList(this, blockpos$mutableblockpos, iblockstate, bb, list, (Entity)null);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
private float calculateCelestialAngle(long worldTime, float partialTicks) {
|
||
|
int i = (int)(worldTime % this.dimension.getRotationalPeriod());
|
||
|
float f = ((float)i + partialTicks) / (float)this.dimension.getRotationalPeriod() - 0.5F;
|
||
|
|
||
|
if(f < 0.0F) {
|
||
|
++f;
|
||
|
}
|
||
|
|
||
|
if(f > 1.0F) {
|
||
|
--f;
|
||
|
}
|
||
|
|
||
|
f = 1.0F - (float)((Math.cos((double)f * Math.PI) + 1.0D) / 2.0D);
|
||
|
f = f + (f - f) / 3.0F;
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
public int calculateSkylightSubtracted(boolean current) {
|
||
|
float f = !this.dimension.getType().days ? 0.5f : this.calculateCelestialAngle(current ? this.daytime :
|
||
|
(this.dimension.getRotationalPeriod() / 4L), 1.0f);
|
||
|
float f1 = 1.0F - (ExtMath.cos(f * (float)Math.PI * 2.0F) * 2.0F + 0.5F);
|
||
|
f1 = ExtMath.clampf(f1, 0.0F, 1.0F);
|
||
|
f1 = 1.0F - f1;
|
||
|
f1 = (float)((double)f1 * (1.0D - (double)(this.getRainStrength() * 5.0F) / 16.0D));
|
||
|
f1 = (float)((double)f1 * (1.0D - (double)(this.getDarkness() * 5.0F) / 16.0D));
|
||
|
f1 = 1.0F - f1;
|
||
|
return (int)(f1 * 11.0F);
|
||
|
}
|
||
|
|
||
|
public float getCelestialAngle(float partialTicks) {
|
||
|
return !this.dimension.getType().days ? 0.5f : this.calculateCelestialAngle(this.daytime, partialTicks);
|
||
|
}
|
||
|
|
||
|
public int getMoonPhase() {
|
||
|
return (int)(this.daytime / this.dimension.getRotationalPeriod() % 8L + 8L) % 8;
|
||
|
}
|
||
|
|
||
|
public float getCurrentMoonPhaseFactor() {
|
||
|
return MOON_PHASES[this.getMoonPhase()];
|
||
|
}
|
||
|
|
||
|
public float getCelestialAngleRadians(float partialTicks) {
|
||
|
float f = this.getCelestialAngle(partialTicks);
|
||
|
return f * (float)Math.PI * 2.0F;
|
||
|
}
|
||
|
|
||
|
public BlockPos getPrecipitationHeight(BlockPos pos) {
|
||
|
return this.getChunk(pos).getPrecipitation(pos);
|
||
|
}
|
||
|
|
||
|
public void updateEntities() {
|
||
|
// this.profiler.start("entities");
|
||
|
// this.profiler.start("global");
|
||
|
|
||
|
for(int i = 0; i < this.effects.size(); ++i) {
|
||
|
Entity entity = (Entity)this.effects.get(i);
|
||
|
|
||
|
++entity.ticksExisted;
|
||
|
entity.onUpdate();
|
||
|
|
||
|
if(entity.dead) {
|
||
|
this.effects.remove(i--);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this.profiler.next("remove");
|
||
|
this.entities.removeAll(this.unloaded);
|
||
|
|
||
|
for(int k = 0; k < this.unloaded.size(); ++k) {
|
||
|
Entity entity1 = (Entity)this.unloaded.get(k);
|
||
|
int j = entity1.chunkCoordX;
|
||
|
int l1 = entity1.chunkCoordZ;
|
||
|
|
||
|
if(entity1.addedToChunk && this.isLoaded(j, l1, true)) {
|
||
|
this.getChunk(j, l1).removeEntity(entity1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for(int l = 0; l < this.unloaded.size(); ++l) {
|
||
|
this.onEntityRemoved((Entity)this.unloaded.get(l));
|
||
|
}
|
||
|
|
||
|
this.unloaded.clear();
|
||
|
// this.profiler.next("regular");
|
||
|
|
||
|
for(int i1 = 0; i1 < this.entities.size(); ++i1) {
|
||
|
Entity entity2 = this.entities.get(i1);
|
||
|
|
||
|
if(entity2.vehicle != null) {
|
||
|
if(!entity2.vehicle.dead && entity2.vehicle.passenger == entity2) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
entity2.vehicle.passenger = null;
|
||
|
entity2.vehicle = null;
|
||
|
}
|
||
|
|
||
|
// this.profiler.start("tick");
|
||
|
|
||
|
if(!entity2.dead) {
|
||
|
this.updateEntity(entity2, true);
|
||
|
}
|
||
|
|
||
|
// this.profiler.end();
|
||
|
}
|
||
|
|
||
|
// this.profiler.next("dead");
|
||
|
Iterator<Entity> ents = this.entities.iterator();
|
||
|
while(ents.hasNext()) {
|
||
|
Entity entity2 = ents.next();
|
||
|
|
||
|
if(entity2.dead) {
|
||
|
int k1 = entity2.chunkCoordX;
|
||
|
int i2 = entity2.chunkCoordZ;
|
||
|
|
||
|
if(entity2.addedToChunk && this.isLoaded(k1, i2, true)) {
|
||
|
this.getChunk(k1, i2).removeEntity(entity2);
|
||
|
}
|
||
|
|
||
|
ents.remove();
|
||
|
this.onEntityRemoved(entity2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this.profiler.next("blockEntities");
|
||
|
this.loadTiles = true;
|
||
|
Iterator<TileEntity> iterator = this.tickable.iterator();
|
||
|
|
||
|
while(iterator.hasNext()) {
|
||
|
TileEntity tileentity = (TileEntity)iterator.next();
|
||
|
|
||
|
if(!tileentity.isInvalid() && tileentity.hasWorldObj()) {
|
||
|
BlockPos blockpos = tileentity.getPos();
|
||
|
|
||
|
if(this.isBlockLoaded(blockpos)) { // && this.border.contains(blockpos)) {
|
||
|
((ITickable)tileentity).update();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(tileentity.isInvalid()) {
|
||
|
iterator.remove();
|
||
|
this.tiles.remove(tileentity);
|
||
|
|
||
|
if(this.isBlockLoaded(tileentity.getPos())) {
|
||
|
this.getChunk(tileentity.getPos()).removeTileEntity(tileentity.getPos());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.loadTiles = false;
|
||
|
|
||
|
if(!this.removeTiles.isEmpty()) {
|
||
|
this.tickable.removeAll(this.removeTiles);
|
||
|
this.tiles.removeAll(this.removeTiles);
|
||
|
this.removeTiles.clear();
|
||
|
}
|
||
|
|
||
|
// this.profiler.next("pendingBlockEntities");
|
||
|
|
||
|
if(!this.addedTiles.isEmpty()) {
|
||
|
for(int j1 = 0; j1 < this.addedTiles.size(); ++j1) {
|
||
|
TileEntity tileentity1 = (TileEntity)this.addedTiles.get(j1);
|
||
|
|
||
|
if(!tileentity1.isInvalid()) {
|
||
|
if(!this.tiles.contains(tileentity1)) {
|
||
|
this.addTileEntity(tileentity1);
|
||
|
}
|
||
|
|
||
|
if(this.isBlockLoaded(tileentity1.getPos())) {
|
||
|
this.getChunk(tileentity1.getPos()).addTileEntity(tileentity1.getPos(), tileentity1);
|
||
|
}
|
||
|
|
||
|
this.markBlockForUpdate(tileentity1.getPos());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.addedTiles.clear();
|
||
|
}
|
||
|
|
||
|
// this.profiler.end();
|
||
|
// this.profiler.end();
|
||
|
}
|
||
|
|
||
|
public boolean addTileEntity(TileEntity tile) {
|
||
|
boolean flag = this.tiles.add(tile);
|
||
|
|
||
|
if(flag && tile instanceof ITickable) {
|
||
|
this.tickable.add(tile);
|
||
|
}
|
||
|
|
||
|
return flag;
|
||
|
}
|
||
|
|
||
|
public void addTileEntities(Collection<TileEntity> tileEntityCollection) {
|
||
|
if(this.loadTiles) {
|
||
|
this.addedTiles.addAll(tileEntityCollection);
|
||
|
}
|
||
|
else {
|
||
|
for(TileEntity tileentity : tileEntityCollection) {
|
||
|
this.tiles.add(tileentity);
|
||
|
|
||
|
if(tileentity instanceof ITickable) {
|
||
|
this.tickable.add(tileentity);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void updateEntity(Entity entityIn, boolean forceUpdate) {
|
||
|
int i = ExtMath.floord(entityIn.posX);
|
||
|
int j = ExtMath.floord(entityIn.posZ);
|
||
|
int k = 32;
|
||
|
|
||
|
if(!forceUpdate || this.isAreaLoaded(i - k, 0, j - k, i + k, 0, j + k, true)) {
|
||
|
entityIn.lastTickPosX = entityIn.posX;
|
||
|
entityIn.lastTickPosY = entityIn.posY;
|
||
|
entityIn.lastTickPosZ = entityIn.posZ;
|
||
|
entityIn.prevYaw = entityIn.rotYaw;
|
||
|
entityIn.prevPitch = entityIn.rotPitch;
|
||
|
|
||
|
if(forceUpdate && entityIn.addedToChunk) {
|
||
|
++entityIn.ticksExisted;
|
||
|
|
||
|
if(entityIn.vehicle != null) {
|
||
|
entityIn.updateRidden();
|
||
|
}
|
||
|
else {
|
||
|
entityIn.onUpdate();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this.profiler.start("chunkCheck");
|
||
|
|
||
|
if(Double.isNaN(entityIn.posX) || Double.isInfinite(entityIn.posX)) {
|
||
|
entityIn.posX = entityIn.lastTickPosX;
|
||
|
}
|
||
|
|
||
|
if(Double.isNaN(entityIn.posY) || Double.isInfinite(entityIn.posY)) {
|
||
|
entityIn.posY = entityIn.lastTickPosY;
|
||
|
}
|
||
|
|
||
|
if(Double.isNaN(entityIn.posZ) || Double.isInfinite(entityIn.posZ)) {
|
||
|
entityIn.posZ = entityIn.lastTickPosZ;
|
||
|
}
|
||
|
|
||
|
if(Double.isNaN((double)entityIn.rotPitch) || Double.isInfinite((double)entityIn.rotPitch)) {
|
||
|
entityIn.rotPitch = entityIn.prevPitch;
|
||
|
}
|
||
|
|
||
|
if(Double.isNaN((double)entityIn.rotYaw) || Double.isInfinite((double)entityIn.rotYaw)) {
|
||
|
entityIn.rotYaw = entityIn.prevYaw;
|
||
|
}
|
||
|
|
||
|
int l = ExtMath.floord(entityIn.posX / 16.0D);
|
||
|
int i1 = ExtMath.floord(entityIn.posY / 16.0D);
|
||
|
int j1 = ExtMath.floord(entityIn.posZ / 16.0D);
|
||
|
|
||
|
if(!entityIn.addedToChunk || entityIn.chunkCoordX != l || entityIn.chunkCoordY != i1 || entityIn.chunkCoordZ != j1) {
|
||
|
if(entityIn.addedToChunk && this.isLoaded(entityIn.chunkCoordX, entityIn.chunkCoordZ, true)) {
|
||
|
this.getChunk(entityIn.chunkCoordX, entityIn.chunkCoordZ).removeEntity(entityIn); // fix red. method
|
||
|
}
|
||
|
|
||
|
if(this.isLoaded(l, j1, true)) {
|
||
|
entityIn.addedToChunk = true;
|
||
|
this.getChunk(l, j1).addEntity(entityIn);
|
||
|
}
|
||
|
else {
|
||
|
entityIn.addedToChunk = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this.profiler.end();
|
||
|
|
||
|
if(forceUpdate && entityIn.addedToChunk && entityIn.passenger != null) {
|
||
|
if(!entityIn.passenger.dead && entityIn.passenger.vehicle == entityIn) {
|
||
|
this.updateEntity(entityIn.passenger, true);
|
||
|
}
|
||
|
else {
|
||
|
entityIn.passenger.vehicle = null;
|
||
|
entityIn.passenger = null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean checkNoEntityCollision(BoundingBox bb) {
|
||
|
return this.checkNoEntityCollision(bb, (Entity)null);
|
||
|
}
|
||
|
|
||
|
public boolean checkNoEntityCollision(BoundingBox bb, Entity entityIn) {
|
||
|
List<Entity> list = this.getEntitiesWithinAABBExcludingEntity((Entity)null, bb);
|
||
|
|
||
|
for(int i = 0; i < list.size(); ++i) {
|
||
|
Entity entity = (Entity)list.get(i);
|
||
|
|
||
|
if(!entity.dead && entity.preventSpawning && entity != entityIn
|
||
|
&& (entityIn == null || entityIn.vehicle != entity && entityIn.passenger != entity)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public boolean isAnyLiquid(BoundingBox bb) {
|
||
|
int i = ExtMath.floord(bb.minX);
|
||
|
int j = ExtMath.floord(bb.maxX);
|
||
|
int k = ExtMath.floord(bb.minY);
|
||
|
int l = ExtMath.floord(bb.maxY);
|
||
|
int i1 = ExtMath.floord(bb.minZ);
|
||
|
int j1 = ExtMath.floord(bb.maxZ);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(int k1 = i; k1 <= j; ++k1) {
|
||
|
for(int l1 = k; l1 <= l; ++l1) {
|
||
|
for(int i2 = i1; i2 <= j1; ++i2) {
|
||
|
Block block = this.getState(blockpos$mutableblockpos.set(k1, l1, i2)).getBlock();
|
||
|
|
||
|
if(block.getMaterial().isLiquid()) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public boolean isFlammableWithin(BoundingBox bb) {
|
||
|
int i = ExtMath.floord(bb.minX);
|
||
|
int j = ExtMath.floord(bb.maxX + 1.0D);
|
||
|
int k = ExtMath.floord(bb.minY);
|
||
|
int l = ExtMath.floord(bb.maxY + 1.0D);
|
||
|
int i1 = ExtMath.floord(bb.minZ);
|
||
|
int j1 = ExtMath.floord(bb.maxZ + 1.0D);
|
||
|
|
||
|
if(this.isAreaLoaded(i, k, i1, j, l, j1, true)) {
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(int k1 = i; k1 < j; ++k1) {
|
||
|
for(int l1 = k; l1 < l; ++l1) {
|
||
|
for(int i2 = i1; i2 < j1; ++i2) {
|
||
|
Block block = this.getState(blockpos$mutableblockpos.set(k1, l1, i2)).getBlock();
|
||
|
|
||
|
if(block == Blocks.fire || block == Blocks.flowing_lava || block == Blocks.lava) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public boolean handleLiquidAcceleration(BoundingBox bb, Entity entityIn) {
|
||
|
int i = ExtMath.floord(bb.minX);
|
||
|
int j = ExtMath.floord(bb.maxX + 1.0D);
|
||
|
int k = ExtMath.floord(bb.minY);
|
||
|
int l = ExtMath.floord(bb.maxY + 1.0D);
|
||
|
int i1 = ExtMath.floord(bb.minZ);
|
||
|
int j1 = ExtMath.floord(bb.maxZ + 1.0D);
|
||
|
|
||
|
if(!this.isAreaLoaded(i, k, i1, j, l, j1, true)) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
boolean flag = false;
|
||
|
Vec3 vec3 = new Vec3(0.0D, 0.0D, 0.0D);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(int k1 = i; k1 < j; ++k1) {
|
||
|
for(int l1 = k; l1 < l; ++l1) {
|
||
|
for(int i2 = i1; i2 < j1; ++i2) {
|
||
|
blockpos$mutableblockpos.set(k1, l1, i2);
|
||
|
State iblockstate = this.getState(blockpos$mutableblockpos);
|
||
|
Block block = iblockstate.getBlock();
|
||
|
|
||
|
if(block.getMaterial().isColdLiquid()) {
|
||
|
double d0 = (double)((float)(l1 + 1)
|
||
|
- BlockLiquid.getLiquidHeightPercent(((Integer)iblockstate.getValue(BlockLiquid.LEVEL)).intValue()));
|
||
|
|
||
|
if((double)l >= d0) {
|
||
|
flag = true;
|
||
|
vec3 = block.modifyAcceleration(this, blockpos$mutableblockpos, entityIn, vec3);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(vec3.lengthVector() > 0.0D && entityIn.isPushedByWater()) {
|
||
|
vec3 = vec3.normalize();
|
||
|
double d1 = 0.014D;
|
||
|
entityIn.motionX += vec3.xCoord * d1;
|
||
|
entityIn.motionY += vec3.yCoord * d1;
|
||
|
entityIn.motionZ += vec3.zCoord * d1;
|
||
|
}
|
||
|
|
||
|
return flag;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean isMaterialInMolten(BoundingBox bb) {
|
||
|
int i = ExtMath.floord(bb.minX);
|
||
|
int j = ExtMath.floord(bb.maxX + 1.0D);
|
||
|
int k = ExtMath.floord(bb.minY);
|
||
|
int l = ExtMath.floord(bb.maxY + 1.0D);
|
||
|
int i1 = ExtMath.floord(bb.minZ);
|
||
|
int j1 = ExtMath.floord(bb.maxZ + 1.0D);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(int k1 = i; k1 < j; ++k1) {
|
||
|
for(int l1 = k; l1 < l; ++l1) {
|
||
|
for(int i2 = i1; i2 < j1; ++i2) {
|
||
|
if(this.getState(blockpos$mutableblockpos.set(k1, l1, i2)).getBlock().getMaterial().isHotLiquid()) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public boolean isAABBInLiquid(BoundingBox bb) {
|
||
|
int i = ExtMath.floord(bb.minX);
|
||
|
int j = ExtMath.floord(bb.maxX + 1.0D);
|
||
|
int k = ExtMath.floord(bb.minY);
|
||
|
int l = ExtMath.floord(bb.maxY + 1.0D);
|
||
|
int i1 = ExtMath.floord(bb.minZ);
|
||
|
int j1 = ExtMath.floord(bb.maxZ + 1.0D);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(int k1 = i; k1 < j; ++k1) {
|
||
|
for(int l1 = k; l1 < l; ++l1) {
|
||
|
for(int i2 = i1; i2 < j1; ++i2) {
|
||
|
State iblockstate = this.getState(blockpos$mutableblockpos.set(k1, l1, i2));
|
||
|
Block block = iblockstate.getBlock();
|
||
|
|
||
|
if(block.getMaterial().isColdLiquid()) {
|
||
|
int j2 = ((Integer)iblockstate.getValue(BlockLiquid.LEVEL)).intValue();
|
||
|
double d0 = (double)(l1 + 1);
|
||
|
|
||
|
if(j2 < 8) {
|
||
|
d0 = (double)(l1 + 1) - (double)j2 / 8.0D;
|
||
|
}
|
||
|
|
||
|
if(d0 >= bb.minY) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public Explosion createExplosion(Entity entityIn, double x, double y, double z, float strength, boolean isSmoking) {
|
||
|
return this.newExplosion(entityIn, x, y, z, strength, false, isSmoking, false);
|
||
|
}
|
||
|
|
||
|
public Explosion createAltExplosion(Entity entityIn, double x, double y, double z, float strength, boolean isSmoking) {
|
||
|
return this.newExplosion(entityIn, x, y, z, strength, false, isSmoking, true);
|
||
|
}
|
||
|
|
||
|
public Explosion newExplosion(Entity entityIn, double x, double y, double z, float strength, boolean isFlaming, boolean isSmoking, boolean altSound) {
|
||
|
Explosion explosion = new Explosion(this, entityIn, x, y, z, strength, isFlaming, isSmoking);
|
||
|
explosion.doExplosionA();
|
||
|
explosion.doExplosionB(true, altSound);
|
||
|
return explosion;
|
||
|
}
|
||
|
|
||
|
public EntityExplosion newExplosion(double x, double y, double z, int strength) {
|
||
|
EntityExplosion explosion = new EntityExplosion(this, x, y, z, strength);
|
||
|
this.spawnEntityInWorld(explosion);
|
||
|
return explosion;
|
||
|
}
|
||
|
|
||
|
public float getBlockDensity(Vec3 vec, BoundingBox bb) {
|
||
|
double d0 = 1.0D / ((bb.maxX - bb.minX) * 2.0D + 1.0D);
|
||
|
double d1 = 1.0D / ((bb.maxY - bb.minY) * 2.0D + 1.0D);
|
||
|
double d2 = 1.0D / ((bb.maxZ - bb.minZ) * 2.0D + 1.0D);
|
||
|
double d3 = (1.0D - Math.floor(1.0D / d0) * d0) / 2.0D;
|
||
|
double d4 = (1.0D - Math.floor(1.0D / d2) * d2) / 2.0D;
|
||
|
|
||
|
if(d0 >= 0.0D && d1 >= 0.0D && d2 >= 0.0D) {
|
||
|
int i = 0;
|
||
|
int j = 0;
|
||
|
|
||
|
for(float f = 0.0F; f <= 1.0F; f = (float)((double)f + d0)) {
|
||
|
for(float f1 = 0.0F; f1 <= 1.0F; f1 = (float)((double)f1 + d1)) {
|
||
|
for(float f2 = 0.0F; f2 <= 1.0F; f2 = (float)((double)f2 + d2)) {
|
||
|
double d5 = bb.minX + (bb.maxX - bb.minX) * (double)f;
|
||
|
double d6 = bb.minY + (bb.maxY - bb.minY) * (double)f1;
|
||
|
double d7 = bb.minZ + (bb.maxZ - bb.minZ) * (double)f2;
|
||
|
|
||
|
if(this.rayTraceBlocks(new Vec3(d5 + d3, d6, d7 + d4), vec) == null) {
|
||
|
++i;
|
||
|
}
|
||
|
|
||
|
++j;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (float)i / (float)j;
|
||
|
}
|
||
|
else {
|
||
|
return 0.0F;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean extinguishFire(EntityNPC player, BlockPos pos, Facing side) {
|
||
|
pos = pos.offset(side);
|
||
|
|
||
|
if(this.getState(pos).getBlock() == Blocks.fire) {
|
||
|
this.playAuxSFX(player, 1004, pos, 0);
|
||
|
this.setBlockToAir(pos);
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public TileEntity getTileEntity(BlockPos pos) {
|
||
|
if(!isValid(pos)) {
|
||
|
return null;
|
||
|
}
|
||
|
else {
|
||
|
TileEntity tileentity = null;
|
||
|
|
||
|
if(this.loadTiles) {
|
||
|
for(int i = 0; i < this.addedTiles.size(); ++i) {
|
||
|
TileEntity tileentity1 = (TileEntity)this.addedTiles.get(i);
|
||
|
|
||
|
if(!tileentity1.isInvalid() && tileentity1.getPos().equals(pos)) {
|
||
|
tileentity = tileentity1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(tileentity == null) {
|
||
|
tileentity = this.getChunk(pos).getTileEntity(pos, TileEntity.EnumCreateEntityType.IMMEDIATE);
|
||
|
}
|
||
|
|
||
|
if(tileentity == null) {
|
||
|
for(int j = 0; j < this.addedTiles.size(); ++j) {
|
||
|
TileEntity tileentity2 = (TileEntity)this.addedTiles.get(j);
|
||
|
|
||
|
if(!tileentity2.isInvalid() && tileentity2.getPos().equals(pos)) {
|
||
|
tileentity = tileentity2;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return tileentity;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void setTileEntity(BlockPos pos, TileEntity tileEntityIn) {
|
||
|
if(tileEntityIn != null && !tileEntityIn.isInvalid()) {
|
||
|
if(this.loadTiles) {
|
||
|
tileEntityIn.setPos(pos);
|
||
|
Iterator<TileEntity> iterator = this.addedTiles.iterator();
|
||
|
|
||
|
while(iterator.hasNext()) {
|
||
|
TileEntity tileentity = (TileEntity)iterator.next();
|
||
|
|
||
|
if(tileentity.getPos().equals(pos)) {
|
||
|
tileentity.invalidate();
|
||
|
iterator.remove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.addedTiles.add(tileEntityIn);
|
||
|
}
|
||
|
else {
|
||
|
this.addTileEntity(tileEntityIn);
|
||
|
this.getChunk(pos).addTileEntity(pos, tileEntityIn);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void removeTileEntity(BlockPos pos) {
|
||
|
TileEntity tileentity = this.getTileEntity(pos);
|
||
|
|
||
|
if(tileentity != null && this.loadTiles) {
|
||
|
tileentity.invalidate();
|
||
|
this.addedTiles.remove(tileentity);
|
||
|
}
|
||
|
else {
|
||
|
if(tileentity != null) {
|
||
|
this.addedTiles.remove(tileentity);
|
||
|
this.tiles.remove(tileentity);
|
||
|
this.tickable.remove(tileentity);
|
||
|
}
|
||
|
|
||
|
this.getChunk(pos).removeTileEntity(pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void markTileEntityForRemoval(TileEntity tileEntityIn) {
|
||
|
this.removeTiles.add(tileEntityIn);
|
||
|
}
|
||
|
|
||
|
protected void calculateInitialSkylight() {
|
||
|
int light = this.calculateSkylightSubtracted(false);
|
||
|
if(light != this.subtract)
|
||
|
this.subtract = light;
|
||
|
}
|
||
|
|
||
|
protected void calculateInitialWeather() {
|
||
|
this.rain = this.weather.hasDownfall() ? 1.0f : 0.0f;
|
||
|
this.darkness = this.weather.isDark() ? 1.0f : 0.0f;
|
||
|
this.fog = this.weather.getFogIntensity();
|
||
|
this.temp = this.getBaseTemperature() + this.weather.getTemperature();
|
||
|
}
|
||
|
|
||
|
protected void setActivePlayerChunksAndCheckLight(int l) {
|
||
|
this.active.clear();
|
||
|
// this.profiler.start("buildList");
|
||
|
|
||
|
for(int i = 0; i < this.players.size(); ++i) {
|
||
|
EntityNPC entityplayer = (EntityNPC)this.players.get(i);
|
||
|
int j = ExtMath.floord(entityplayer.posX / 16.0D);
|
||
|
int k = ExtMath.floord(entityplayer.posZ / 16.0D);
|
||
|
// int l = this.getRenderDistanceChunks();
|
||
|
|
||
|
for(int i1 = -l; i1 <= l; ++i1) {
|
||
|
for(int j1 = -l; j1 <= l; ++j1) {
|
||
|
this.active.add(new ChunkPos(i1 + j, j1 + k));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this.profiler.end();
|
||
|
//
|
||
|
// this.profiler.start("playerCheckLight");
|
||
|
|
||
|
if(!this.players.isEmpty()) {
|
||
|
int k1 = this.rand.zrange(this.players.size());
|
||
|
EntityNPC entityplayer1 = (EntityNPC)this.players.get(k1);
|
||
|
int l1 = ExtMath.floord(entityplayer1.posX) + this.rand.zrange(11) - 5;
|
||
|
int i2 = ExtMath.floord(entityplayer1.posY) + this.rand.zrange(11) - 5;
|
||
|
int j2 = ExtMath.floord(entityplayer1.posZ) + this.rand.zrange(11) - 5;
|
||
|
this.checkLight(new BlockPos(l1, i2, j2));
|
||
|
}
|
||
|
|
||
|
// this.profiler.end();
|
||
|
}
|
||
|
|
||
|
public float getTempOffset() {
|
||
|
return this.temp;
|
||
|
}
|
||
|
|
||
|
protected float getBaseTemperature() {
|
||
|
return this.dimension.getTemperature() + this.dimension.getOrbitOffset() *
|
||
|
ExtMath.sin((((float)(this.daytime % this.dimension.getOrbitalPeriod()) / (float)this.dimension.getOrbitalPeriod())
|
||
|
-0.125f) * (float)Math.PI * 2.0f);
|
||
|
}
|
||
|
|
||
|
public LeavesType getLeavesGen(BlockPos pos) {
|
||
|
return this.canFreezeAt(pos) ? LeavesType.SNOWY : ((!this.dimension.getType().days || this.dimension.getOrbitOffset() == 0.0f) ?
|
||
|
this.dimension.getLeavesType() : LeavesType.values()[(int)((this.daytime %
|
||
|
this.dimension.getOrbitalPeriod()) * (long)LeavesType.values().length / this.dimension.getOrbitalPeriod())]);
|
||
|
}
|
||
|
|
||
|
public float getTemperatureK(BlockPos pos) {
|
||
|
return this.temp + this.getBiomeGenForCoords(pos).getFloatTemperature(pos);
|
||
|
}
|
||
|
|
||
|
public float getTemperatureC(BlockPos pos) {
|
||
|
return World.ABSOLUTE_ZERO + this.getTemperatureK(pos);
|
||
|
}
|
||
|
|
||
|
public boolean canFreezeAt(BlockPos pos) {
|
||
|
return this.getTemperatureC(pos) <= 0.0F;
|
||
|
}
|
||
|
|
||
|
public boolean canBurnAt(BlockPos pos) {
|
||
|
return this.getTemperatureC(pos) >= 194.0f;
|
||
|
}
|
||
|
|
||
|
public boolean doesWaterVaporize(BlockPos pos) {
|
||
|
return this.getTemperatureC(pos) >= 100.0f;
|
||
|
}
|
||
|
|
||
|
public boolean isLavaFaster(BlockPos pos) {
|
||
|
return this.getTemperatureC(pos) >= 314.0f;
|
||
|
}
|
||
|
|
||
|
public boolean canSnowAt(BlockPos pos, boolean checkLight, boolean allowLayers) {
|
||
|
if(!this.canFreezeAt(pos)) {
|
||
|
return false;
|
||
|
}
|
||
|
else if(!checkLight) {
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
if(pos.getY() >= 0 && pos.getY() < 512 && this.getLightFor(LightType.BLOCK, pos) < 10) {
|
||
|
Block block = this.getState(pos).getBlock();
|
||
|
|
||
|
if((block.getMaterial() == Material.air || (allowLayers && block == Blocks.snow_layer))
|
||
|
&& Blocks.snow_layer.canPlaceBlockAt(this, pos)) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean checkLight(BlockPos pos) {
|
||
|
boolean flag = false;
|
||
|
|
||
|
if(!this.dimension.hasNoLight()) {
|
||
|
flag |= this.checkLightFor(LightType.SKY, pos);
|
||
|
}
|
||
|
|
||
|
flag = flag | this.checkLightFor(LightType.BLOCK, pos);
|
||
|
return flag;
|
||
|
}
|
||
|
|
||
|
private int getRawLight(BlockPos pos, LightType lightType) {
|
||
|
if(lightType == LightType.SKY && this.canSeeSky(pos)) {
|
||
|
return 15;
|
||
|
}
|
||
|
else {
|
||
|
Block block = this.getState(pos).getBlock();
|
||
|
int i = lightType == LightType.SKY ? 0 : block.getLightValue();
|
||
|
int j = block.getLightOpacity();
|
||
|
|
||
|
if(j >= 15 && block.getLightValue() > 0) {
|
||
|
j = 1;
|
||
|
}
|
||
|
|
||
|
if(j < 1) {
|
||
|
j = 1;
|
||
|
}
|
||
|
|
||
|
if(j >= 15) {
|
||
|
return 0;
|
||
|
}
|
||
|
else if(i >= 14) {
|
||
|
return i;
|
||
|
}
|
||
|
else {
|
||
|
for(Facing enumfacing : Facing.values()) {
|
||
|
BlockPos blockpos = pos.offset(enumfacing);
|
||
|
int k = this.getLightFor(lightType, blockpos) - j;
|
||
|
|
||
|
if(k > i) {
|
||
|
i = k;
|
||
|
}
|
||
|
|
||
|
if(i >= 14) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean checkLightFor(LightType lightType, BlockPos pos) {
|
||
|
if(!this.isAreaLoaded(pos, 17, false)) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
int i = 0;
|
||
|
int j = 0;
|
||
|
// this.profiler.start("getBrightness");
|
||
|
int k = this.getLightFor(lightType, pos);
|
||
|
int l = this.getRawLight(pos, lightType);
|
||
|
int i1 = pos.getX();
|
||
|
int j1 = pos.getY();
|
||
|
int k1 = pos.getZ();
|
||
|
|
||
|
if(l > k) {
|
||
|
this.lightUpdate[j++] = 133152;
|
||
|
}
|
||
|
else if(l < k) {
|
||
|
this.lightUpdate[j++] = 133152 | k << 18;
|
||
|
|
||
|
while(i < j) {
|
||
|
int l1 = this.lightUpdate[i++];
|
||
|
int i2 = (l1 & 63) - 32 + i1;
|
||
|
int j2 = (l1 >> 6 & 63) - 32 + j1;
|
||
|
int k2 = (l1 >> 12 & 63) - 32 + k1;
|
||
|
int l2 = l1 >> 18 & 15;
|
||
|
BlockPos blockpos = new BlockPos(i2, j2, k2);
|
||
|
int i3 = this.getLightFor(lightType, blockpos);
|
||
|
|
||
|
if(i3 == l2) {
|
||
|
this.setLightFor(lightType, blockpos, 0);
|
||
|
|
||
|
if(l2 > 0) {
|
||
|
int j3 = ExtMath.absi(i2 - i1);
|
||
|
int k3 = ExtMath.absi(j2 - j1);
|
||
|
int l3 = ExtMath.absi(k2 - k1);
|
||
|
|
||
|
if(j3 + k3 + l3 < 17) {
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
for(Facing enumfacing : Facing.values()) {
|
||
|
int i4 = i2 + enumfacing.getFrontOffsetX();
|
||
|
int j4 = j2 + enumfacing.getFrontOffsetY();
|
||
|
int k4 = k2 + enumfacing.getFrontOffsetZ();
|
||
|
blockpos$mutableblockpos.set(i4, j4, k4);
|
||
|
int l4 = Math.max(1, this.getState(blockpos$mutableblockpos).getBlock().getLightOpacity());
|
||
|
i3 = this.getLightFor(lightType, blockpos$mutableblockpos);
|
||
|
|
||
|
if(i3 == l2 - l4 && j < this.lightUpdate.length) {
|
||
|
this.lightUpdate[j++] = i4 - i1 + 32 | j4 - j1 + 32 << 6 | k4 - k1 + 32 << 12 | l2 - l4 << 18;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i = 0;
|
||
|
}
|
||
|
|
||
|
// this.profiler.end();
|
||
|
// this.profiler.start("checkedPosition < toCheckCount");
|
||
|
|
||
|
while(i < j) {
|
||
|
int i5 = this.lightUpdate[i++];
|
||
|
int j5 = (i5 & 63) - 32 + i1;
|
||
|
int k5 = (i5 >> 6 & 63) - 32 + j1;
|
||
|
int l5 = (i5 >> 12 & 63) - 32 + k1;
|
||
|
BlockPos blockpos1 = new BlockPos(j5, k5, l5);
|
||
|
int i6 = this.getLightFor(lightType, blockpos1);
|
||
|
int j6 = this.getRawLight(blockpos1, lightType);
|
||
|
|
||
|
if(j6 != i6) {
|
||
|
this.setLightFor(lightType, blockpos1, j6);
|
||
|
|
||
|
if(j6 > i6) {
|
||
|
int k6 = Math.abs(j5 - i1);
|
||
|
int l6 = Math.abs(k5 - j1);
|
||
|
int i7 = Math.abs(l5 - k1);
|
||
|
boolean flag = j < this.lightUpdate.length - 6;
|
||
|
|
||
|
if(k6 + l6 + i7 < 17 && flag) {
|
||
|
if(this.getLightFor(lightType, blockpos1.west()) < j6) {
|
||
|
this.lightUpdate[j++] = j5 - 1 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 - k1 + 32 << 12);
|
||
|
}
|
||
|
|
||
|
if(this.getLightFor(lightType, blockpos1.east()) < j6) {
|
||
|
this.lightUpdate[j++] = j5 + 1 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 - k1 + 32 << 12);
|
||
|
}
|
||
|
|
||
|
if(this.getLightFor(lightType, blockpos1.down()) < j6) {
|
||
|
this.lightUpdate[j++] = j5 - i1 + 32 + (k5 - 1 - j1 + 32 << 6) + (l5 - k1 + 32 << 12);
|
||
|
}
|
||
|
|
||
|
if(this.getLightFor(lightType, blockpos1.up()) < j6) {
|
||
|
this.lightUpdate[j++] = j5 - i1 + 32 + (k5 + 1 - j1 + 32 << 6) + (l5 - k1 + 32 << 12);
|
||
|
}
|
||
|
|
||
|
if(this.getLightFor(lightType, blockpos1.north()) < j6) {
|
||
|
this.lightUpdate[j++] = j5 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 - 1 - k1 + 32 << 12);
|
||
|
}
|
||
|
|
||
|
if(this.getLightFor(lightType, blockpos1.south()) < j6) {
|
||
|
this.lightUpdate[j++] = j5 - i1 + 32 + (k5 - j1 + 32 << 6) + (l5 + 1 - k1 + 32 << 12);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this.profiler.end();
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public List<Entity> getEntitiesWithinAABBExcludingEntity(Entity entityIn, BoundingBox bb) {
|
||
|
return this.getEntitiesInAABBexcluding(entityIn, bb, null);
|
||
|
}
|
||
|
|
||
|
public List<Entity> getEntitiesInAABBexcluding(Entity entityIn, BoundingBox boundingBox, Predicate<? super Entity> predicate) {
|
||
|
List<Entity> list = Lists.<Entity>newArrayList();
|
||
|
int i = ExtMath.floord((boundingBox.minX - 2.0D) / 16.0D);
|
||
|
int j = ExtMath.floord((boundingBox.maxX + 2.0D) / 16.0D);
|
||
|
int k = ExtMath.floord((boundingBox.minZ - 2.0D) / 16.0D);
|
||
|
int l = ExtMath.floord((boundingBox.maxZ + 2.0D) / 16.0D);
|
||
|
|
||
|
for(int i1 = i; i1 <= j; ++i1) {
|
||
|
for(int j1 = k; j1 <= l; ++j1) {
|
||
|
if(this.isLoaded(i1, j1, true)) {
|
||
|
this.getChunk(i1, j1).getEntities(entityIn, boundingBox, list, predicate);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
public <T extends Entity> List<T> getEntitiesWithinAABB(Class<? extends T> classEntity, BoundingBox bb) {
|
||
|
return this.<T>getEntitiesWithinAABB(classEntity, bb, null);
|
||
|
}
|
||
|
|
||
|
public <T extends Entity> List<T> getEntitiesWithinAABB(Class<? extends T> clazz, BoundingBox aabb, Predicate<? super T> filter) {
|
||
|
int i = ExtMath.floord((aabb.minX - 2.0D) / 16.0D);
|
||
|
int j = ExtMath.floord((aabb.maxX + 2.0D) / 16.0D);
|
||
|
int k = ExtMath.floord((aabb.minZ - 2.0D) / 16.0D);
|
||
|
int l = ExtMath.floord((aabb.maxZ + 2.0D) / 16.0D);
|
||
|
List<T> list = Lists.<T>newArrayList();
|
||
|
|
||
|
for(int i1 = i; i1 <= j; ++i1) {
|
||
|
for(int j1 = k; j1 <= l; ++j1) {
|
||
|
if(this.isLoaded(i1, j1, true)) {
|
||
|
this.getChunk(i1, j1).getEntities(clazz, aabb, list, filter);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
public Entity getEntityByID(int id) {
|
||
|
return (Entity)this.entityIds.lookup(id);
|
||
|
}
|
||
|
|
||
|
public void markChunkDirty(BlockPos pos, TileEntity unusedTileEntity) {
|
||
|
if(this.isBlockLoaded(pos)) {
|
||
|
this.getChunk(pos).setModified();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void loadEntities(Collection<Entity> entityCollection) {
|
||
|
this.entities.addAll(entityCollection);
|
||
|
|
||
|
for(Entity entity : entityCollection) {
|
||
|
this.onEntityAdded(entity);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void unloadEntities(Collection<Entity> entityCollection) {
|
||
|
this.unloaded.addAll(entityCollection);
|
||
|
}
|
||
|
|
||
|
public boolean canBlockBePlaced(Block blockIn, BlockPos pos, boolean p_175716_3_, Facing side, Entity entityIn, ItemStack itemStackIn) {
|
||
|
Block block = this.getState(pos).getBlock();
|
||
|
BoundingBox axisalignedbb = p_175716_3_ ? null : blockIn.getCollisionBoundingBox(this, pos, blockIn.getState());
|
||
|
return axisalignedbb != null && !this.checkNoEntityCollision(axisalignedbb, entityIn) ? false
|
||
|
: (block.getMaterial() == Material.circuits && blockIn == Blocks.anvil ? true
|
||
|
: block.getMaterial().isReplaceable() && blockIn.canReplace(this, pos, side, itemStackIn));
|
||
|
}
|
||
|
|
||
|
public int getSeaLevel() {
|
||
|
return 63;
|
||
|
}
|
||
|
|
||
|
private int getStrongPower(BlockPos pos, Facing direction) {
|
||
|
State iblockstate = this.getState(pos);
|
||
|
return iblockstate.getBlock().getStrongPower(this, pos, iblockstate, direction);
|
||
|
}
|
||
|
|
||
|
public int getStrongPower(BlockPos pos) {
|
||
|
int i = 0;
|
||
|
i = Math.max(i, this.getStrongPower(pos.down(), Facing.DOWN));
|
||
|
|
||
|
if(i >= 15) {
|
||
|
return i;
|
||
|
}
|
||
|
else {
|
||
|
i = Math.max(i, this.getStrongPower(pos.up(), Facing.UP));
|
||
|
|
||
|
if(i >= 15) {
|
||
|
return i;
|
||
|
}
|
||
|
else {
|
||
|
i = Math.max(i, this.getStrongPower(pos.north(), Facing.NORTH));
|
||
|
|
||
|
if(i >= 15) {
|
||
|
return i;
|
||
|
}
|
||
|
else {
|
||
|
i = Math.max(i, this.getStrongPower(pos.south(), Facing.SOUTH));
|
||
|
|
||
|
if(i >= 15) {
|
||
|
return i;
|
||
|
}
|
||
|
else {
|
||
|
i = Math.max(i, this.getStrongPower(pos.west(), Facing.WEST));
|
||
|
|
||
|
if(i >= 15) {
|
||
|
return i;
|
||
|
}
|
||
|
else {
|
||
|
i = Math.max(i, this.getStrongPower(pos.east(), Facing.EAST));
|
||
|
return i >= 15 ? i : i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean isSidePowered(BlockPos pos, Facing side) {
|
||
|
return this.getRedstonePower(pos, side) > 0;
|
||
|
}
|
||
|
|
||
|
public int getRedstonePower(BlockPos pos, Facing facing) {
|
||
|
State iblockstate = this.getState(pos);
|
||
|
Block block = iblockstate.getBlock();
|
||
|
return block.isNormalCube() ? this.getStrongPower(pos) : block.getWeakPower(this, pos, iblockstate, facing);
|
||
|
}
|
||
|
|
||
|
public boolean isBlockPowered(BlockPos pos) {
|
||
|
return this.getRedstonePower(pos.down(), Facing.DOWN) > 0 ? true
|
||
|
: (this.getRedstonePower(pos.up(), Facing.UP) > 0 ? true
|
||
|
: (this.getRedstonePower(pos.north(), Facing.NORTH) > 0 ? true
|
||
|
: (this.getRedstonePower(pos.south(), Facing.SOUTH) > 0 ? true
|
||
|
: (this.getRedstonePower(pos.west(), Facing.WEST) > 0 ? true
|
||
|
: this.getRedstonePower(pos.east(), Facing.EAST) > 0))));
|
||
|
}
|
||
|
|
||
|
public int isBlockIndirectlyGettingPowered(BlockPos pos) {
|
||
|
int i = 0;
|
||
|
|
||
|
for(Facing enumfacing : Facing.values()) {
|
||
|
int j = this.getRedstonePower(pos.offset(enumfacing), enumfacing);
|
||
|
|
||
|
if(j >= 15) {
|
||
|
return 15;
|
||
|
}
|
||
|
|
||
|
if(j > i) {
|
||
|
i = j;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
public EntityNPC getClosestPlayerToEntity(Entity entityIn, double distance) {
|
||
|
return this.getClosestPlayer(entityIn.posX, entityIn.posY, entityIn.posZ, distance);
|
||
|
}
|
||
|
|
||
|
public EntityNPC getClosestPlayer(double x, double y, double z, double distance) {
|
||
|
double d0 = -1.0D;
|
||
|
EntityNPC entityplayer = null;
|
||
|
|
||
|
for(int i = 0; i < this.players.size(); ++i) {
|
||
|
EntityNPC entityplayer1 = (EntityNPC)this.players.get(i);
|
||
|
|
||
|
// if(EntitySelectors.NOT_SPECTATING.apply(entityplayer1)) {
|
||
|
double d1 = entityplayer1.getDistanceSq(x, y, z);
|
||
|
|
||
|
if((distance < 0.0D || d1 < distance * distance) && (d0 == -1.0D || d1 < d0)) {
|
||
|
d0 = d1;
|
||
|
entityplayer = entityplayer1;
|
||
|
}
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
return entityplayer;
|
||
|
}
|
||
|
|
||
|
public boolean isAnyPlayerWithinRangeAt(double x, double y, double z, double range) {
|
||
|
for(int i = 0; i < this.players.size(); ++i) {
|
||
|
EntityNPC entityplayer = (EntityNPC)this.players.get(i);
|
||
|
|
||
|
// if(EntitySelectors.NOT_SPECTATING.apply(entityplayer)) {
|
||
|
double d0 = entityplayer.getDistanceSq(x, y, z);
|
||
|
|
||
|
if(range < 0.0D || d0 < range * range) {
|
||
|
return true;
|
||
|
}
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// public EntityNPC getPlayer(String name) {
|
||
|
// for(int i = 0; i < this.players.size(); ++i) {
|
||
|
// EntityNPC entityplayer = this.players.get(i);
|
||
|
//
|
||
|
// if(name.equalsIgnoreCase(entityplayer.getUser())) {
|
||
|
// return entityplayer;
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// return null;
|
||
|
// }
|
||
|
|
||
|
public void setTimeFactor(int factor) {
|
||
|
this.timeFactor = Math.max((long)factor, 1L);
|
||
|
// if(this.timeFactor > Constants.EARTH_DAY)
|
||
|
// this.timeFactor = (this.timeFactor - (this.timeFactor % Constants.EARTH_DAY)) + 1L;
|
||
|
}
|
||
|
|
||
|
public void setEntityState(Entity entityIn, byte state) {
|
||
|
}
|
||
|
|
||
|
public void addBlockEvent(BlockPos pos, Block blockIn, int eventID, int eventParam) {
|
||
|
blockIn.onBlockEventReceived(this, pos, this.getState(pos), eventID, eventParam);
|
||
|
}
|
||
|
|
||
|
public Weather getWeather() {
|
||
|
return this.weather;
|
||
|
}
|
||
|
|
||
|
public long getDayTime() {
|
||
|
return this.daytime;
|
||
|
}
|
||
|
|
||
|
public void setWeather(Weather weather) {
|
||
|
this.weather = weather;
|
||
|
}
|
||
|
|
||
|
public void setDayTime(long time) {
|
||
|
this.daytime = time;
|
||
|
}
|
||
|
|
||
|
public float getDarkness() {
|
||
|
return this.darkness;
|
||
|
}
|
||
|
|
||
|
public void setDarkness(float dark) {
|
||
|
this.darkness = dark;
|
||
|
}
|
||
|
|
||
|
public float getRainStrength() {
|
||
|
return this.rain;
|
||
|
}
|
||
|
|
||
|
public void setRainStrength(float strength) {
|
||
|
this.rain = strength;
|
||
|
}
|
||
|
|
||
|
public float getFogStrength() {
|
||
|
return this.fog;
|
||
|
}
|
||
|
|
||
|
public void setFogStrength(float strength) {
|
||
|
this.fog = strength;
|
||
|
}
|
||
|
|
||
|
public void setTemperature(float temp) {
|
||
|
this.temp = temp;
|
||
|
}
|
||
|
|
||
|
public boolean isDark() {
|
||
|
return this.darkness > 0.9f;
|
||
|
}
|
||
|
|
||
|
public boolean isThundering() {
|
||
|
return this.isDark() && this.weather.hasThunder() && (!this.weather.hasDownfall() || this.hasDownfall());
|
||
|
}
|
||
|
|
||
|
public boolean hasDownfall() {
|
||
|
return this.rain > 0.2f;
|
||
|
}
|
||
|
|
||
|
public boolean isRaining() {
|
||
|
return this.hasDownfall() && this.weather.canRain();
|
||
|
}
|
||
|
|
||
|
public boolean isRainingAt(BlockPos strikePosition, boolean wet) {
|
||
|
if(wet ? !this.isRaining() : !this.hasDownfall()) {
|
||
|
return false;
|
||
|
}
|
||
|
else if(!this.canSeeSky(strikePosition)) {
|
||
|
return false;
|
||
|
}
|
||
|
else if(this.getPrecipitationHeight(strikePosition).getY() > strikePosition.getY()) {
|
||
|
return false;
|
||
|
}
|
||
|
return !this.canSnowAt(strikePosition, false, false);
|
||
|
// else {
|
||
|
// Biome biomegenbase = this.getBiomeGenForCoords(strikePosition);
|
||
|
// return biomegenbase.isSnowyBiome() ? false : ( ? false : biomegenbase.canRain());
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
// public void setItemData(String dataID, WorldSavedData worldSavedDataIn) {
|
||
|
// }
|
||
|
//
|
||
|
// public WorldSavedData loadItemData(Class<? extends WorldSavedData> clazz, String dataID) {
|
||
|
// return null;
|
||
|
// }
|
||
|
//
|
||
|
// public int getNextMapId() {
|
||
|
// return 0;
|
||
|
// }
|
||
|
|
||
|
public final void playAuxSFX(int type, BlockPos pos, int data) {
|
||
|
this.playAuxSFX(null, type, pos, data);
|
||
|
}
|
||
|
|
||
|
public void updateComparatorOutputLevel(BlockPos pos, Block blockIn) {
|
||
|
for(Facing enumfacing : Facing.Plane.HORIZONTAL) {
|
||
|
BlockPos blockpos = pos.offset(enumfacing);
|
||
|
|
||
|
if(this.isBlockLoaded(blockpos)) {
|
||
|
State iblockstate = this.getState(blockpos);
|
||
|
|
||
|
if(Blocks.comparator.isAssociated(iblockstate.getBlock())) {
|
||
|
iblockstate.getBlock().onNeighborBlockChange(this, blockpos, iblockstate, blockIn);
|
||
|
}
|
||
|
else if(iblockstate.getBlock().isNormalCube()) {
|
||
|
blockpos = blockpos.offset(enumfacing);
|
||
|
iblockstate = this.getState(blockpos);
|
||
|
|
||
|
if(Blocks.comparator.isAssociated(iblockstate.getBlock())) {
|
||
|
iblockstate.getBlock().onNeighborBlockChange(this, blockpos, iblockstate, blockIn);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// public DifficultyInstance getDifficultyForLocation(BlockPos pos) {
|
||
|
// return null;
|
||
|
// }
|
||
|
|
||
|
public void scheduleUpdate(BlockPos pos, Block blockIn, int delay) {
|
||
|
}
|
||
|
|
||
|
public void spawnParticle(ParticleType particleType, double xCoord, double yCoord, double zCoord, double xOffset, double yOffset,
|
||
|
double zOffset, int... data) {
|
||
|
}
|
||
|
|
||
|
// public Difficulty getDifficulty() {
|
||
|
// return this.difficulty;
|
||
|
// }
|
||
|
|
||
|
// public void setDifficulty(Difficulty diff) {
|
||
|
// this.difficulty = diff;
|
||
|
// }
|
||
|
|
||
|
public abstract Chunk getChunk(int x, int z);
|
||
|
public abstract void markBlockForUpdate(BlockPos pos);
|
||
|
protected abstract void notifyLightSet(BlockPos pos);
|
||
|
public abstract void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2);
|
||
|
public abstract void playSound(SoundEvent sound, double x, double y, double z, float volume, float pitch);
|
||
|
protected abstract void onEntityAdded(Entity entityIn);
|
||
|
protected abstract void onEntityRemoved(Entity entityIn);
|
||
|
// public abstract void broadcastSound(int soundID, BlockPos pos, int data);
|
||
|
public abstract void playAuxSFX(EntityNPC player, int sfxType, BlockPos blockPosIn, int data);
|
||
|
public abstract void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress);
|
||
|
}
|