@Override protected void freeChunk(Point p) { int x = (int) p.getX() >> Chunk.BLOCKS.BITS; int y = (int) p.getY() >> Chunk.BLOCKS.BITS; // + SEALEVEL_CHUNK; int z = (int) p.getZ() >> Chunk.BLOCKS.BITS; if (y < 0 || y >= p.getWorld().getHeight() >> Chunk.BLOCKS.BITS) { return; } TIntSet column = initializedChunks.get(x, z); CompressedChunkMessage CCMsg; if (column != null) { column.remove(y); if (column.isEmpty()) { if (initializedChunks.remove(x, z) != null) { activeChunks.remove(x, z); } CCMsg = new CompressedChunkMessage(x, z, true, null, null, null, true); } else { CCMsg = new CompressedChunkMessage(x, z, false, null, null, null, true); } session.send(false, CCMsg); } }
@Override protected boolean canSendChunk(Chunk c, Set<Chunk> unsendable) { if (!c.canSend()) { if (unsendable != null) { unsendable.add(c); } c.populate(true, true, true); return false; } if (activeChunks.contains(c.getX(), c.getZ())) { return true; } boolean canSend = true; Collection<Chunk> chunks = chunkInit.getChunks(c); for (Chunk cc : chunks) { if (!cc.canSend()) { if (unsendable != null) { unsendable.add(c); } canSend = false; cc.populate(true, true, true); } } return canSend; }
@Override public void preSnapshot() { super.preSnapshot(); Long key; while ((key = this.emptyColumns.poll()) != null) { int x = IntPairHashed.key1(key); int z = IntPairHashed.key2(key); TIntSet column = initializedChunks.get(x, z); if (column.isEmpty()) { column = initializedChunks.remove(x, z); activeChunks.remove(x, z); session.send( false, new ChunkDataMessage(x, z, true, null, null, null, true, player.getSession())); } } }
@Override public void sendChunk(Chunk c) { int x = c.getX(); int y = c.getY(); // + SEALEVEL_CHUNK; int z = c.getZ(); if (y < 0 || y >= c.getWorld().getHeight() >> Chunk.BLOCKS.BITS) { return; } initChunk(c.getBase()); if (activeChunks.add(x, z)) { Point p = c.getBase(); int[][] heights = getColumnHeights(p); BlockMaterial[][] materials = getColumnTopmostMaterials(p); byte[][] packetChunkData = new byte[16][]; for (int cube = 0; cube < 16; cube++) { packetChunkData[cube] = getChunkHeightMap(heights, materials, cube); } Chunk chunk = p.getWorld().getChunkFromBlock(p); byte[] biomeData = new byte[Chunk.BLOCKS.AREA]; for (int dx = x; dx < x + Chunk.BLOCKS.SIZE; ++dx) { for (int dz = z; dz < z + Chunk.BLOCKS.SIZE; ++dz) { Biome biome = chunk.getBiomeType(dx & Chunk.BLOCKS.MASK, 0, dz & Chunk.BLOCKS.MASK); if (biome instanceof VanillaBiome) { biomeData[(dz & Chunk.BLOCKS.MASK) << 4 | (dx & Chunk.BLOCKS.MASK)] = (byte) ((VanillaBiome) biome).getBiomeId(); } } } CompressedChunkMessage CCMsg = new CompressedChunkMessage(x, z, true, new boolean[16], packetChunkData, biomeData); owner.getSession().send(false, CCMsg); } ChunkSnapshot snapshot = c.getSnapshot(SnapshotType.BOTH, EntityType.NO_ENTITIES, ExtraData.NO_EXTRA_DATA); short[] rawBlockIdArray = snapshot.getBlockIds(); short[] rawBlockData = snapshot.getBlockData(); byte[] rawBlockLight = snapshot.getBlockLight(); byte[] rawSkyLight = snapshot.getSkyLight(); byte[] fullChunkData = new byte[Chunk.BLOCKS.HALF_VOLUME * 5]; int arrIndex = 0; for (int i = 0; i < rawBlockIdArray.length; i++) { short convert = getMinecraftId(rawBlockIdArray[i]); fullChunkData[arrIndex++] = (byte) (convert & 0xFF); } for (int i = 0; i < rawBlockData.length; i += 2) { fullChunkData[arrIndex++] = (byte) ((rawBlockData[i + 1] << 4) | (rawBlockData[i] & 0xF)); } System.arraycopy(rawBlockLight, 0, fullChunkData, arrIndex, rawBlockLight.length); arrIndex += rawBlockLight.length; System.arraycopy(rawSkyLight, 0, fullChunkData, arrIndex, rawSkyLight.length); arrIndex += rawSkyLight.length; byte[][] packetChunkData = new byte[16][]; packetChunkData[y] = fullChunkData; CompressedChunkMessage CCMsg = new CompressedChunkMessage(x, z, false, new boolean[16], packetChunkData, null); owner.getSession().send(false, CCMsg); }
@Override public Collection<Chunk> sendChunk(Chunk c) { int x = c.getX(); int y = c.getY(); // + SEALEVEL_CHUNK; int z = c.getZ(); if (y < 0 || y >= c.getWorld().getHeight() >> Chunk.BLOCKS.BITS) { return null; } initChunk(c.getBase()); Collection<Chunk> chunks = null; if (activeChunks.add(x, z)) { Point p = c.getBase(); int[][] heights = getColumnHeights(p); BlockMaterial[][] materials = getColumnTopmostMaterials(p); byte[][] packetChunkData = new byte[16][]; for (int cube = 0; cube < 16; cube++) { Point pp = new Point( c.getWorld(), x << Chunk.BLOCKS.BITS, cube << Chunk.BLOCKS.BITS, z << Chunk.BLOCKS.BITS); packetChunkData[cube] = chunkInit.getChunkData(heights, materials, pp); } Chunk chunk = p.getWorld().getChunkFromBlock(p); byte[] biomeData = new byte[Chunk.BLOCKS.AREA]; for (int dx = x; dx < x + Chunk.BLOCKS.SIZE; ++dx) { for (int dz = z; dz < z + Chunk.BLOCKS.SIZE; ++dz) { Biome biome = chunk.getBiome(dx & Chunk.BLOCKS.MASK, 0, dz & Chunk.BLOCKS.MASK); if (biome instanceof VanillaBiome) { biomeData[(dz & Chunk.BLOCKS.MASK) << 4 | (dx & Chunk.BLOCKS.MASK)] = (byte) ((VanillaBiome) biome).getBiomeId(); } } } ChunkDataMessage CCMsg = new ChunkDataMessage( x, z, true, new boolean[16], packetChunkData, biomeData, player.getSession()); player.getSession().send(false, CCMsg); chunks = chunkInit.getChunks(c); } byte[] fullChunkData = ChunkInit.getChunkFullData(c); byte[][] packetChunkData = new byte[16][]; packetChunkData[y] = fullChunkData; ChunkDataMessage CCMsg = new ChunkDataMessage( x, z, false, new boolean[16], packetChunkData, null, player.getSession()); player.getSession().send(false, CCMsg); return chunks; }
@Override protected Collection<Chunk> sendChunk(Chunk c, boolean force) { if (!force) { return sendChunk(c); } int x = c.getX(); int y = c.getY(); // + SEALEVEL_CHUNK; int z = c.getZ(); RepositionManager rm = getRepositionManager(); int cY = rm.convertChunkY(y); if (cY < 0 || cY >= c.getWorld().getHeight() >> Chunk.BLOCKS.BITS) { return null; } initChunkRaw(c.getBase()); Collection<Chunk> chunks = null; List<ProtocolEvent> events = new ArrayList<ProtocolEvent>(); if (activeChunks.add(x, z)) { Point p = c.getBase(); int[][] heights = getColumnHeights(p); BlockMaterial[][] materials = getColumnTopmostMaterials(p); byte[][] packetChunkData = new byte[16][]; for (int cube = 0; cube < 16; cube++) { int serverCube = rm.getInverse().convertChunkY(cube); Point pp = new Point( c.getWorld(), x << Chunk.BLOCKS.BITS, serverCube << Chunk.BLOCKS.BITS, z << Chunk.BLOCKS.BITS); packetChunkData[cube] = chunkInit.getChunkData(heights, materials, pp, events); } Chunk chunk = p.getWorld().getChunkFromBlock(p); byte[] biomeData = new byte[Chunk.BLOCKS.AREA]; for (int dx = x; dx < x + Chunk.BLOCKS.SIZE; ++dx) { for (int dz = z; dz < z + Chunk.BLOCKS.SIZE; ++dz) { Biome biome = chunk.getBiome(dx & Chunk.BLOCKS.MASK, 0, dz & Chunk.BLOCKS.MASK); if (biome instanceof VanillaBiome) { biomeData[(dz & Chunk.BLOCKS.MASK) << 4 | (dx & Chunk.BLOCKS.MASK)] = (byte) ((VanillaBiome) biome).getBiomeId(); } } } ChunkDataMessage CCMsg = new ChunkDataMessage( x, z, true, new boolean[16], packetChunkData, biomeData, player.getSession(), getRepositionManager()); player.getSession().send(false, CCMsg); chunks = chunkInit.getChunks(c); } if (chunks == null || !chunks.contains(c)) { byte[] fullChunkData = ChunkInit.getChunkFullData(c, events); byte[][] packetChunkData = new byte[16][]; packetChunkData[cY] = fullChunkData; ChunkDataMessage CCMsg = new ChunkDataMessage( x, z, false, new boolean[16], packetChunkData, null, player.getSession(), getRepositionManager()); player.getSession().send(false, CCMsg); if (chunks == null) { chunks = new ArrayList<Chunk>(1); } chunks.add(c); } for (ProtocolEvent e : events) { this.callProtocolEvent(e); } return chunks; }