mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-12 08:58:02 -04:00
update chunk data types
This commit is contained in:
parent
00239e9f18
commit
166093e641
@ -33,4 +33,8 @@ public class BlockPosition {
|
|||||||
BlockPosition pos = (BlockPosition) obj;
|
BlockPosition pos = (BlockPosition) obj;
|
||||||
return pos.getX() == getX() && pos.getY() == getY() && pos.getZ() == getZ();
|
return pos.getX() == getX() && pos.getY() == getY() && pos.getZ() == getZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ChunkLocation getChunkLocation() {
|
||||||
|
return new ChunkLocation(getX() / 16, getZ() / 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,33 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes;
|
package de.bixilon.minosoft.game.datatypes;
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.game.datatypes.blocks.Block;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of 16x16x16 blocks
|
* Collection of 16 chunks
|
||||||
*/
|
*/
|
||||||
public class Chunk {
|
public class Chunk {
|
||||||
private final HashMap<ChunkLocation, WorldBlock> blocks;
|
private final HashMap<Byte, ChunkNibble> chunks;
|
||||||
|
|
||||||
public Chunk(HashMap<ChunkLocation, WorldBlock> blocks) {
|
public Chunk(HashMap<Byte, ChunkNibble> chunks) {
|
||||||
this.blocks = blocks;
|
this.chunks = chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorldBlock getWorldBlock(ChunkLocation loc) {
|
public Block getBlock(int x, int y, int z) {
|
||||||
return blocks.get(loc);
|
if (x > 16 || y > 255 || z > 16 || x < 0 || y < 0 || z < 0) {
|
||||||
|
throw new IllegalArgumentException(String.format("Invalid chunk location %s %s %s", x, y, z));
|
||||||
|
}
|
||||||
|
byte section = (byte) (y / 16);
|
||||||
|
if (section == 0) {
|
||||||
|
return Block.COBBLESTONE;
|
||||||
|
} else if (section == 1) {
|
||||||
|
return Block.DIRT;
|
||||||
|
} else {
|
||||||
|
return Block.AIR;
|
||||||
|
}
|
||||||
|
//ToDo
|
||||||
|
//return chunks.get(section).getBlock(x, y % 16,z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorldBlock getWorldBlock(byte x, byte y, byte z) {
|
|
||||||
return getWorldBlock(new ChunkLocation(x, y, z));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes;
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.game.datatypes.blocks.Blocks;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collection of 16 chunks
|
|
||||||
*/
|
|
||||||
public class ChunkColumn {
|
|
||||||
private final HashMap<Byte, Chunk> chunks;
|
|
||||||
final int x;
|
|
||||||
final int z;
|
|
||||||
|
|
||||||
public ChunkColumn(int x, int z) {
|
|
||||||
chunks = new HashMap<>();
|
|
||||||
this.x = x;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorldBlock getWorldBlock(byte x, short y, byte z) {
|
|
||||||
if (x > 16 || y > 255 || z > 16 || x < 0 || y < 0 || z < 0) {
|
|
||||||
throw new IllegalArgumentException(String.format("Invalid chunk location %s %s %s", x, y, z));
|
|
||||||
}
|
|
||||||
byte heightNumber = (byte) (y / 16);
|
|
||||||
BlockPosition pos = new BlockPosition(this.x * 16 + x, y, this.z * 16 + z);
|
|
||||||
if (heightNumber == 0) {
|
|
||||||
return Blocks.getBlockInstance(Blocks.DIRT, pos);
|
|
||||||
} else {
|
|
||||||
return Blocks.getBlockInstance(Blocks.AIR, pos);
|
|
||||||
}
|
|
||||||
//ToDo
|
|
||||||
//return chunks.get(heightNumber).getWorldBlock(x, (byte) (y - (heightNumber * 16)), z);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Chunk X and Z location (block position / 16, rounded down)
|
|
||||||
*/
|
|
||||||
public class ChunkColumnLocation {
|
|
||||||
int x;
|
|
||||||
int z;
|
|
||||||
|
|
||||||
public ChunkColumnLocation(int x, int z) {
|
|
||||||
this.x = x;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getZ() {
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (super.equals(obj)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ChunkColumnLocation that = (ChunkColumnLocation) obj;
|
|
||||||
return getX() == that.getX() && getZ() == that.getZ();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +1,22 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes;
|
package de.bixilon.minosoft.game.datatypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chunk X, Y and Z location (max 16x16x16)
|
* Chunk X and Z location (block position / 16, rounded down)
|
||||||
*/
|
*/
|
||||||
public class ChunkLocation {
|
public class ChunkLocation {
|
||||||
byte x;
|
int x;
|
||||||
byte y;
|
int z;
|
||||||
byte z;
|
|
||||||
|
|
||||||
public ChunkLocation(byte x, byte y, byte z) {
|
public ChunkLocation(int x, int z) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getX() {
|
public int getX() {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getY() {
|
public int getZ() {
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getZ() {
|
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +26,6 @@ public class ChunkLocation {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ChunkLocation that = (ChunkLocation) obj;
|
ChunkLocation that = (ChunkLocation) obj;
|
||||||
return getX() == that.getX() && getY() == that.getY() && getZ() == that.getZ();
|
return getX() == that.getX() && getZ() == that.getZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package de.bixilon.minosoft.game.datatypes;
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.game.datatypes.blocks.Block;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of 16x16x16 blocks
|
||||||
|
*/
|
||||||
|
public class ChunkNibble {
|
||||||
|
private final HashMap<ChunkNibbleLocation, Block> blocks;
|
||||||
|
|
||||||
|
public ChunkNibble(HashMap<ChunkNibbleLocation, Block> blocks) {
|
||||||
|
this.blocks = blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getBlock(ChunkNibbleLocation loc) {
|
||||||
|
return blocks.get(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getBlock(int x, int y, int z) {
|
||||||
|
return getBlock(new ChunkNibbleLocation(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package de.bixilon.minosoft.game.datatypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chunk X, Y and Z location (max 16x16x16)
|
||||||
|
*/
|
||||||
|
public class ChunkNibbleLocation {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
public ChunkNibbleLocation(int x, int y, int z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (super.equals(obj)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ChunkNibbleLocation that = (ChunkNibbleLocation) obj;
|
||||||
|
return getX() == that.getX() && getY() == that.getY() && getZ() == that.getZ();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package de.bixilon.minosoft.game.datatypes;
|
||||||
|
|
||||||
|
public class Identifier {
|
||||||
|
final String legacy;
|
||||||
|
String mod = "minecraft"; // by default minecraft
|
||||||
|
String water;
|
||||||
|
|
||||||
|
public Identifier(String mod, String legacy, String water) { // water for water update name (post 1.13.x)
|
||||||
|
this.mod = mod;
|
||||||
|
this.legacy = legacy;
|
||||||
|
this.water = water;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Identifier(String legacy, String water) {
|
||||||
|
this.legacy = legacy;
|
||||||
|
this.water = water;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Identifier(String name) {
|
||||||
|
// legacy and water are the same
|
||||||
|
this.legacy = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMod() {
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLegacy() {
|
||||||
|
return legacy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWaterUpdateName() {
|
||||||
|
return ((water == null) ? legacy : water);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,14 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes;
|
package de.bixilon.minosoft.game.datatypes;
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.game.datatypes.blocks.Block;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of ChunkColumns
|
* Collection of ChunkColumns
|
||||||
*/
|
*/
|
||||||
public class World {
|
public class World {
|
||||||
public final HashMap<ChunkColumnLocation, ChunkColumn> chunks;
|
public final HashMap<ChunkLocation, Chunk> chunks;
|
||||||
final String name;
|
final String name;
|
||||||
|
|
||||||
public World(String name) {
|
public World(String name) {
|
||||||
@ -18,9 +20,16 @@ public class World {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkColumn getChunkColumn(ChunkColumnLocation loc) {
|
public Chunk getChunk(ChunkLocation loc) {
|
||||||
return new ChunkColumn(loc.getX(), loc.getZ());
|
return chunks.get(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getBlock(BlockPosition pos) {
|
||||||
//ToDo
|
//ToDo
|
||||||
//return chunks.get(loc);
|
ChunkLocation loc = pos.getChunkLocation();
|
||||||
|
if (getChunk(loc) != null) {
|
||||||
|
return getChunk(loc).getBlock(pos.getX() % 16, pos.getX(), pos.getZ() % 16);
|
||||||
|
}
|
||||||
|
return Block.AIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basically raw chunk stuff. This is not a block like dirt (it can be). Can be dirt, a flower, fire, torch, sapling, fluid (water/lava), nether wart, banner, ...
|
|
||||||
*/
|
|
||||||
public interface WorldBlock {
|
|
||||||
BlockPosition getBlockPosition();
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes.blocks;
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.game.datatypes.BlockPosition;
|
|
||||||
|
|
||||||
public class Air implements Block {
|
|
||||||
final BlockPosition position;
|
|
||||||
|
|
||||||
public Air(BlockPosition position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockPosition getBlockPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLegacyId() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLegacyIdentifier() {
|
|
||||||
return "minecraft:air";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,52 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes.blocks;
|
package de.bixilon.minosoft.game.datatypes.blocks;
|
||||||
|
|
||||||
import de.bixilon.minosoft.game.datatypes.WorldBlock;
|
import de.bixilon.minosoft.game.datatypes.Identifier;
|
||||||
|
|
||||||
public interface Block extends WorldBlock {
|
public enum Block {
|
||||||
|
AIR(new Identifier("air"), 0),
|
||||||
|
DIRT(new Identifier("stone"), 1),
|
||||||
|
GRASS(new Identifier("grass"), 2),
|
||||||
|
COBBLESTONE(new Identifier("stone"), 4),
|
||||||
|
WHITE_WOOL(new Identifier("wool"), 35, 0),
|
||||||
|
RED_WOOL(new Identifier("wool", "red_wool"), 35, 14),
|
||||||
|
DROPPER(new Identifier("dropper", "dropper"), 158, BlockRotation.RotationType.NORMAL);
|
||||||
|
|
||||||
String getLegacyIdentifier();
|
Identifier identifier;
|
||||||
|
int legacyId;
|
||||||
|
int legacyData;
|
||||||
|
BlockRotation.RotationType rotationType;
|
||||||
|
|
||||||
int getLegacyId();
|
Block(Identifier identifier, int legacyId, BlockRotation.RotationType rotationType) {
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.legacyId = legacyId;
|
||||||
|
this.rotationType = rotationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block(Identifier identifier, int legacyId, int legacyData) {
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.legacyId = legacyId;
|
||||||
|
this.legacyData = legacyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block(Identifier identifier, int legacyId) {
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.legacyId = legacyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Identifier getIdentifier() {
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getLegacyId() {
|
||||||
|
return legacyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLegacyData() {
|
||||||
|
return legacyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockRotation.RotationType getRotationType() {
|
||||||
|
return rotationType;
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package de.bixilon.minosoft.game.datatypes.blocks;
|
||||||
|
|
||||||
|
public interface BlockRotation {
|
||||||
|
|
||||||
|
int getId();
|
||||||
|
|
||||||
|
enum RotationType {
|
||||||
|
BARELY,
|
||||||
|
NORMAL,
|
||||||
|
EXTENDED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Barely implements BlockRotation {
|
||||||
|
EAST(0),
|
||||||
|
NORTH(1),
|
||||||
|
SOUTH(2),
|
||||||
|
WEST(3);
|
||||||
|
|
||||||
|
int id;
|
||||||
|
|
||||||
|
Barely(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Barely byId(int id) {
|
||||||
|
for (Barely b : values()) {
|
||||||
|
if (b.getId() == id) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Normal implements BlockRotation {
|
||||||
|
DOWN(0),
|
||||||
|
EAST(1),
|
||||||
|
NORTH(2),
|
||||||
|
SOUTH(3),
|
||||||
|
UP(4),
|
||||||
|
WEST(5);
|
||||||
|
|
||||||
|
int id;
|
||||||
|
|
||||||
|
Normal(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Normal byId(int id) {
|
||||||
|
for (Normal n : values()) {
|
||||||
|
if (n.getId() == id) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Extended implements BlockRotation {
|
||||||
|
SOUTH(0),
|
||||||
|
SOUTH_SOUTH_WEST(1),
|
||||||
|
SOUTH_WEST(2),
|
||||||
|
WEST_SOUTH_WEST(3),
|
||||||
|
WEST(4),
|
||||||
|
WEST_NORTH_WEST(5),
|
||||||
|
NORTH_WEST(6),
|
||||||
|
NORTH_NORTH_WEST(7),
|
||||||
|
NORTH(8),
|
||||||
|
NORTH_NORTH_EAST(9),
|
||||||
|
NORTH_EAST(10),
|
||||||
|
EAST_NORTH_EAST(11),
|
||||||
|
EAST(12),
|
||||||
|
EAST_SOUTH_EAST(13),
|
||||||
|
SOUTH_EAST(14),
|
||||||
|
SOUTH_SOUTH_EAST(15);
|
||||||
|
|
||||||
|
int id;
|
||||||
|
|
||||||
|
Extended(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Extended byId(int id) {
|
||||||
|
for (Extended e : values()) {
|
||||||
|
if (e.getId() == id) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,33 +0,0 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes.blocks;
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.game.datatypes.BlockPosition;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
|
|
||||||
public enum Blocks {
|
|
||||||
DIRT(Dirt.class),
|
|
||||||
AIR(Air.class);
|
|
||||||
|
|
||||||
private final Class<? extends Block> clazz;
|
|
||||||
|
|
||||||
Blocks(Class<? extends Block> clazz) {
|
|
||||||
this.clazz = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Block getBlockInstance(Class<? extends Block> clazz, BlockPosition pos) {
|
|
||||||
try {
|
|
||||||
return clazz.getConstructor(BlockPosition.class).newInstance(pos);
|
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new RuntimeException("Invalid block constructor!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Block getBlockInstance(Blocks b, BlockPosition pos) {
|
|
||||||
return getBlockInstance(b.getClazz(), pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<? extends Block> getClazz() {
|
|
||||||
return clazz;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package de.bixilon.minosoft.game.datatypes.blocks;
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.game.datatypes.BlockPosition;
|
|
||||||
|
|
||||||
public class Dirt implements Block {
|
|
||||||
final BlockPosition position;
|
|
||||||
|
|
||||||
public Dirt(BlockPosition position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockPosition getBlockPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLegacyId() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLegacyIdentifier() {
|
|
||||||
return "minecraft:dirt";
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,93 @@
|
|||||||
|
package de.bixilon.minosoft.protocol.packets.clientbound.play;
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.logging.Log;
|
||||||
|
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
|
||||||
|
import de.bixilon.minosoft.util.BitByte;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.zip.DataFormatException;
|
||||||
|
import java.util.zip.Inflater;
|
||||||
|
|
||||||
|
public class PlayChunkBulk implements ClientboundPacket {
|
||||||
|
short chunkColumnCount;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(InPacketBuffer buffer, ProtocolVersion v) {
|
||||||
|
switch (v) {
|
||||||
|
case VERSION_1_7_10:
|
||||||
|
// ToDo only implement once, not twice (chunk data and chunk bulk)
|
||||||
|
this.chunkColumnCount = buffer.readShort();
|
||||||
|
int dataLen = buffer.readInteger();
|
||||||
|
boolean containsSkyLight = buffer.readBoolean();
|
||||||
|
byte[] data = buffer.readBytes(dataLen);
|
||||||
|
|
||||||
|
// decompressing chunk data
|
||||||
|
Inflater inflater = new Inflater();
|
||||||
|
inflater.setInput(data, 0, dataLen);
|
||||||
|
byte[] result = new byte[4096];
|
||||||
|
ByteArrayOutputStream stream = new ByteArrayOutputStream(dataLen);
|
||||||
|
try {
|
||||||
|
while (!inflater.finished()) {
|
||||||
|
stream.write(result, 0, inflater.inflate(result));
|
||||||
|
}
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InByteBuffer decompressed = new InByteBuffer(stream.toByteArray());
|
||||||
|
|
||||||
|
// chunk meta data
|
||||||
|
for (int i = 0; i < chunkColumnCount; i++) {
|
||||||
|
int x = buffer.readInteger();
|
||||||
|
int y = buffer.readInteger();
|
||||||
|
short primaryBitMask = buffer.readShort();
|
||||||
|
short addBitMask = buffer.readShort();
|
||||||
|
System.out.println(String.format("Meta data: %s %s", x, y));
|
||||||
|
|
||||||
|
for (int c = 0; c < 16; c++) { // max sections per chunks in chunk column
|
||||||
|
if (BitByte.isBitSet(primaryBitMask, c)) {
|
||||||
|
short[] blockType = BitByte.byteArrayToShortArray(decompressed.readBytes(4096)); // 16 * 16 * 16
|
||||||
|
byte[] metadata = decompressed.readBytes(2048); // 16 * 16 * 16 / 2 (only half bit per block)
|
||||||
|
byte[] light;
|
||||||
|
if (containsSkyLight) {
|
||||||
|
light = decompressed.readBytes(2048);
|
||||||
|
}
|
||||||
|
byte[] addBlockType;
|
||||||
|
if (BitByte.isBitSet(addBitMask, c)) {
|
||||||
|
addBlockType = decompressed.readBytes(2048);
|
||||||
|
}
|
||||||
|
byte[] biome = decompressed.readBytes(256);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log() {
|
||||||
|
Log.protocol(String.format("Chunk bulk packet received (chunks: %s)", chunkColumnCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(PacketHandler h) {
|
||||||
|
h.handle(this);
|
||||||
|
}
|
||||||
|
}
|
@ -5,10 +5,7 @@ import de.bixilon.minosoft.protocol.network.Connection;
|
|||||||
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketEncryptionKeyRequest;
|
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketEncryptionKeyRequest;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginDisconnect;
|
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginDisconnect;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginSuccess;
|
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginSuccess;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketJoinGame;
|
import de.bixilon.minosoft.protocol.packets.clientbound.play.*;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketKeepAlive;
|
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketPlayerInfo;
|
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketTimeUpdate;
|
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong;
|
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse;
|
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse;
|
||||||
import de.bixilon.minosoft.protocol.packets.serverbound.login.PacketEncryptionResponse;
|
import de.bixilon.minosoft.protocol.packets.serverbound.login.PacketEncryptionResponse;
|
||||||
@ -68,4 +65,7 @@ public class PacketHandler {
|
|||||||
public void handle(PacketKeepAlive pkg) {
|
public void handle(PacketKeepAlive pkg) {
|
||||||
connection.sendPacket(new PacketKeepAliveResponse(pkg.getId()));
|
connection.sendPacket(new PacketKeepAliveResponse(pkg.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void handle(PlayChunkBulk pkg) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,7 @@ import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
|
|||||||
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketEncryptionKeyRequest;
|
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketEncryptionKeyRequest;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginDisconnect;
|
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginDisconnect;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginSuccess;
|
import de.bixilon.minosoft.protocol.packets.clientbound.login.PacketLoginSuccess;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketJoinGame;
|
import de.bixilon.minosoft.protocol.packets.clientbound.play.*;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketKeepAlive;
|
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketPlayerInfo;
|
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketTimeUpdate;
|
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong;
|
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusPong;
|
||||||
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse;
|
import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusResponse;
|
||||||
|
|
||||||
@ -41,5 +38,6 @@ public interface Protocol {
|
|||||||
packetClassMapping.put(Packets.Clientbound.PLAY_PLAYER_INFO, PacketPlayerInfo.class);
|
packetClassMapping.put(Packets.Clientbound.PLAY_PLAYER_INFO, PacketPlayerInfo.class);
|
||||||
packetClassMapping.put(Packets.Clientbound.PLAY_TIME_UPDATE, PacketTimeUpdate.class);
|
packetClassMapping.put(Packets.Clientbound.PLAY_TIME_UPDATE, PacketTimeUpdate.class);
|
||||||
packetClassMapping.put(Packets.Clientbound.PLAY_KEEP_ALIVE, PacketKeepAlive.class);
|
packetClassMapping.put(Packets.Clientbound.PLAY_KEEP_ALIVE, PacketKeepAlive.class);
|
||||||
|
packetClassMapping.put(Packets.Clientbound.PLAY_CHUNK_BULK, PlayChunkBulk.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,18 @@
|
|||||||
package de.bixilon.minosoft.util;
|
package de.bixilon.minosoft.util;
|
||||||
|
|
||||||
public class BitByte {
|
public class BitByte {
|
||||||
public static boolean isBitSet(byte in, int pos) {
|
public static boolean isBitSet(int in, int pos) {
|
||||||
boolean bitSet;
|
boolean bitSet;
|
||||||
int mask = 1 << pos;
|
int mask = 1 << pos;
|
||||||
bitSet = ((in & mask) == mask);
|
bitSet = ((in & mask) == mask);
|
||||||
return bitSet;
|
return bitSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static short[] byteArrayToShortArray(byte[] readBytes) {
|
||||||
|
short[] ret = new short[readBytes.length];
|
||||||
|
for (int i = 0; i < readBytes.length; i++) {
|
||||||
|
ret[0] = readBytes[0];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user