use of cn.nukkit.level.format.generic.BaseFullChunk in project Nukkit by Nukkit.
the class Level method setChunk.
public void setChunk(int chunkX, int chunkZ, BaseFullChunk chunk, boolean unload) {
if (chunk == null) {
return;
}
long index = Level.chunkHash(chunkX, chunkZ);
FullChunk oldChunk = this.getChunk(chunkX, chunkZ, false);
if (unload && oldChunk != null) {
this.unloadChunk(chunkX, chunkZ, false, false);
this.provider.setChunk(chunkX, chunkZ, chunk);
} else {
Map<Long, Entity> oldEntities = oldChunk != null ? oldChunk.getEntities() : Collections.emptyMap();
Map<Long, BlockEntity> oldBlockEntities = oldChunk != null ? oldChunk.getBlockEntities() : Collections.emptyMap();
if (!oldEntities.isEmpty()) {
Iterator<Map.Entry<Long, Entity>> iter = oldEntities.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Long, Entity> entry = iter.next();
Entity entity = entry.getValue();
chunk.addEntity(entity);
if (oldChunk != null) {
iter.remove();
oldChunk.removeEntity(entity);
entity.chunk = chunk;
}
}
}
if (!oldBlockEntities.isEmpty()) {
Iterator<Map.Entry<Long, BlockEntity>> iter = oldBlockEntities.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Long, BlockEntity> entry = iter.next();
BlockEntity blockEntity = entry.getValue();
chunk.addBlockEntity(blockEntity);
if (oldChunk != null) {
iter.remove();
oldChunk.removeBlockEntity(blockEntity);
blockEntity.chunk = chunk;
}
}
}
this.provider.setChunk(chunkX, chunkZ, chunk);
}
chunk.setChanged();
if (!this.isChunkInUse(index)) {
this.unloadChunkRequest(chunkX, chunkZ);
} else {
for (ChunkLoader loader : this.getChunkLoaders(chunkX, chunkZ)) {
loader.onChunkChanged(chunk);
}
}
}
use of cn.nukkit.level.format.generic.BaseFullChunk in project Nukkit by Nukkit.
the class Level method getBlock.
public Block getBlock(int x, int y, int z) {
int fullState;
if (y >= 0 && y < 256) {
int cx = x >> 4;
int cz = z >> 4;
BaseFullChunk chunk = getChunk(cx, cz);
if (chunk != null) {
fullState = chunk.getFullBlock(x & 0xF, y, z & 0xF);
} else {
fullState = 0;
}
} else {
fullState = 0;
}
Block block = this.blockStates[fullState & 0xFFF].clone();
block.x = x;
block.y = y;
block.z = z;
block.level = this;
return block;
}
use of cn.nukkit.level.format.generic.BaseFullChunk in project Nukkit by Nukkit.
the class Level method updateBlockLight.
public void updateBlockLight(Map<Long, Map<Character, Object>> map) {
int size = map.size();
if (size == 0) {
return;
}
Queue<BlockVector3> lightPropagationQueue = new ConcurrentLinkedQueue<>();
Queue<Object[]> lightRemovalQueue = new ConcurrentLinkedQueue<>();
Map<BlockVector3, Object> visited = new ConcurrentHashMap<>(8, 0.9f, 1);
Map<BlockVector3, Object> removalVisited = new ConcurrentHashMap<>(8, 0.9f, 1);
Iterator<Map.Entry<Long, Map<Character, Object>>> iter = map.entrySet().iterator();
while (iter.hasNext() && size-- > 0) {
Map.Entry<Long, Map<Character, Object>> entry = iter.next();
iter.remove();
long index = entry.getKey();
Map<Character, Object> blocks = entry.getValue();
int chunkX = Level.getHashX(index);
int chunkZ = Level.getHashZ(index);
int bx = chunkX << 4;
int bz = chunkZ << 4;
for (char blockHash : blocks.keySet()) {
int hi = (byte) (blockHash >>> 8);
int lo = (byte) blockHash;
int y = lo & 0xFF;
int x = (hi & 0xF) + bx;
int z = ((hi >> 4) & 0xF) + bz;
BaseFullChunk chunk = getChunk(x >> 4, z >> 4, false);
if (chunk != null) {
int lcx = x & 0xF;
int lcz = z & 0xF;
int oldLevel = chunk.getBlockLight(lcx, y, lcz);
int newLevel = Block.light[chunk.getBlockId(lcx, y, lcz)];
if (oldLevel != newLevel) {
this.setBlockLightAt(x, y, z, newLevel);
if (newLevel < oldLevel) {
removalVisited.put(Level.blockHash(x, y, z), changeBlocksPresent);
lightRemovalQueue.add(new Object[] { new BlockVector3(x, y, z), oldLevel });
} else {
visited.put(Level.blockHash(x, y, z), changeBlocksPresent);
lightPropagationQueue.add(new BlockVector3(x, y, z));
}
}
}
}
}
while (!lightRemovalQueue.isEmpty()) {
Object[] val = lightRemovalQueue.poll();
BlockVector3 node = (BlockVector3) val[0];
int lightLevel = (int) val[1];
this.computeRemoveBlockLight((int) node.x - 1, (int) node.y, (int) node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
this.computeRemoveBlockLight((int) node.x + 1, (int) node.y, (int) node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
this.computeRemoveBlockLight((int) node.x, (int) node.y - 1, (int) node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
this.computeRemoveBlockLight((int) node.x, (int) node.y + 1, (int) node.z, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
this.computeRemoveBlockLight((int) node.x, (int) node.y, (int) node.z - 1, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
this.computeRemoveBlockLight((int) node.x, (int) node.y, (int) node.z + 1, lightLevel, lightRemovalQueue, lightPropagationQueue, removalVisited, visited);
}
while (!lightPropagationQueue.isEmpty()) {
BlockVector3 node = lightPropagationQueue.poll();
int lightLevel = this.getBlockLightAt((int) node.x, (int) node.y, (int) node.z) - Block.lightFilter[this.getBlockIdAt((int) node.x, (int) node.y, (int) node.z)];
if (lightLevel >= 1) {
this.computeSpreadBlockLight((int) node.x - 1, (int) node.y, (int) node.z, lightLevel, lightPropagationQueue, visited);
this.computeSpreadBlockLight((int) node.x + 1, (int) node.y, (int) node.z, lightLevel, lightPropagationQueue, visited);
this.computeSpreadBlockLight((int) node.x, (int) node.y - 1, (int) node.z, lightLevel, lightPropagationQueue, visited);
this.computeSpreadBlockLight((int) node.x, (int) node.y + 1, (int) node.z, lightLevel, lightPropagationQueue, visited);
this.computeSpreadBlockLight((int) node.x, (int) node.y, (int) node.z - 1, lightLevel, lightPropagationQueue, visited);
this.computeSpreadBlockLight(node.x, (int) node.y, (int) node.z + 1, lightLevel, lightPropagationQueue, visited);
}
}
}
use of cn.nukkit.level.format.generic.BaseFullChunk in project Nukkit by Nukkit.
the class Level method forceLoadChunk.
private BaseFullChunk forceLoadChunk(long index, int x, int z, boolean generate) {
this.timings.syncChunkLoadTimer.startTiming();
BaseFullChunk chunk = this.provider.getChunk(x, z, generate);
if (chunk == null) {
if (generate) {
throw new IllegalStateException("Could not create new Chunk");
}
this.timings.syncChunkLoadTimer.stopTiming();
return chunk;
}
if (chunk.getProvider() != null) {
this.server.getPluginManager().callEvent(new ChunkLoadEvent(chunk, !chunk.isGenerated()));
} else {
this.unloadChunk(x, z, false);
this.timings.syncChunkLoadTimer.stopTiming();
return chunk;
}
chunk.initChunk();
if (!chunk.isLightPopulated() && chunk.isPopulated() && (boolean) this.getServer().getConfig("chunk-ticking.light-updates", false)) {
this.getServer().getScheduler().scheduleAsyncTask(new LightPopulationTask(this, chunk));
}
if (this.isChunkInUse(index)) {
this.unloadQueue.remove(index);
for (ChunkLoader loader : this.getChunkLoaders(x, z)) {
loader.onChunkLoaded(chunk);
}
} else {
this.unloadQueue.put(index, (Long) System.currentTimeMillis());
}
this.timings.syncChunkLoadTimer.stopTiming();
return chunk;
}
use of cn.nukkit.level.format.generic.BaseFullChunk in project Nukkit by Nukkit.
the class Level method setBlock.
public boolean setBlock(int x, int y, int z, Block block, boolean direct, boolean update) {
if (y < 0 || y >= 256) {
return false;
}
BaseFullChunk chunk = this.getChunk(x >> 4, z >> 4, true);
Block blockPrevious;
// synchronized (chunk) {
blockPrevious = chunk.getAndSetBlock(x & 0xF, y, z & 0xF, block);
if (blockPrevious.getFullId() == block.getFullId()) {
return false;
}
// }
block.x = x;
block.y = y;
block.z = z;
block.level = this;
int cx = x >> 4;
int cz = z >> 4;
long index = Level.chunkHash(cx, cz);
if (direct) {
this.sendBlocks(this.getChunkPlayers(cx, cz).values().stream().toArray(Player[]::new), new Block[] { block }, UpdateBlockPacket.FLAG_ALL_PRIORITY);
} else {
addBlockChange(index, x, y, z);
}
for (ChunkLoader loader : this.getChunkLoaders(cx, cz)) {
loader.onBlockChanged(block);
}
if (update) {
if (blockPrevious.isTransparent() != block.isTransparent() || blockPrevious.getLightLevel() != block.getLightLevel()) {
addLightUpdate(x, y, z);
}
BlockUpdateEvent ev = new BlockUpdateEvent(block);
this.server.getPluginManager().callEvent(ev);
if (!ev.isCancelled()) {
for (Entity entity : this.getNearbyEntities(new SimpleAxisAlignedBB(x - 1, y - 1, z - 1, x + 1, y + 1, z + 1))) {
entity.scheduleUpdate();
}
block = ev.getBlock();
block.onUpdate(BLOCK_UPDATE_NORMAL);
this.updateAround(x, y, z);
}
}
return true;
}
Aggregations