Merge branch 'proto_1.12.2' into develop
Tests: FAILED
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
package mc.core.block;
|
package mc.core.world.block;
|
||||||
|
|
||||||
import com.flowpowered.nbt.Tag;
|
import com.flowpowered.nbt.Tag;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -10,7 +10,8 @@ import java.util.Map;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public abstract class AbstractBlock implements Block {
|
public abstract class AbstractBlock implements Block {
|
||||||
@Getter@Setter
|
@Getter
|
||||||
|
@Setter
|
||||||
private Location location;
|
private Location location;
|
||||||
@Getter
|
@Getter
|
||||||
private int meta;
|
private int meta;
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package mc.core.block;
|
package mc.core.world.block;
|
||||||
|
|
||||||
import com.flowpowered.nbt.Tag;
|
|
||||||
import mc.core.Location;
|
import mc.core.Location;
|
||||||
import mc.core.nbt.Taggable;
|
import mc.core.nbt.Taggable;
|
||||||
|
|
||||||
@@ -29,20 +28,6 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
public interface Block extends Taggable, Serializable{
|
public interface Block extends Taggable, Serializable{
|
||||||
|
|
||||||
static Block airBlock (int x, int y, int z) {
|
|
||||||
return new AbstractBlock(BlockType.AIR) {
|
|
||||||
@Override
|
|
||||||
public Tag<?> getTag(String name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Location getLocation() {
|
|
||||||
return new Location(x, y, z);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Block id */
|
/** Block id */
|
||||||
int getId();
|
int getId();
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mc.core.block;
|
package mc.core.world.block;
|
||||||
|
|
||||||
import mc.core.Location;
|
import mc.core.Location;
|
||||||
|
|
||||||
@@ -8,6 +8,10 @@ public class BlockFactory {
|
|||||||
return new EmbeddedBlock(blockType, meta);
|
return new EmbeddedBlock(blockType, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Block create(BlockType blockType) {
|
||||||
|
return create(blockType, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For first-time generation
|
* For first-time generation
|
||||||
*/
|
*/
|
||||||
@@ -4,7 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
package mc.core.world;
|
package mc.core.world;
|
||||||
|
|
||||||
import mc.core.block.Block;
|
import mc.core.Location;
|
||||||
|
import mc.core.world.block.Block;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
@@ -23,14 +24,11 @@ import java.io.Serializable;
|
|||||||
*/
|
*/
|
||||||
/* 16x16x16 */
|
/* 16x16x16 */
|
||||||
public interface Chunk extends Serializable{
|
public interface Chunk extends Serializable{
|
||||||
int getBlockType(int x, int y, int z);
|
Block getBlock(int x, int y, int z);
|
||||||
void setBlockType(int x, int y, int z, int type);
|
default Block getBlock(Location location) {
|
||||||
|
return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||||
int getBlockMetadata(int x, int y, int z);
|
}
|
||||||
void setBlockMetadata(int x, int y, int z, int metadata);
|
void setBlock(Block block);
|
||||||
|
|
||||||
int getBlockLight(int x, int y, int z);
|
|
||||||
void setBlockLight(int x, int y, int z, int lightLevel);
|
|
||||||
|
|
||||||
int getSkyLight(int x, int y, int z);
|
int getSkyLight(int x, int y, int z);
|
||||||
void setSkyLight(int x, int y, int z, int lightLevel);
|
void setSkyLight(int x, int y, int z, int lightLevel);
|
||||||
@@ -44,7 +42,4 @@ public interface Chunk extends Serializable{
|
|||||||
int getX();
|
int getX();
|
||||||
int getY();
|
int getY();
|
||||||
int getZ();
|
int getZ();
|
||||||
|
|
||||||
void setBlock (int x, int y, int z, Block block);
|
|
||||||
Block getBlock (int x, int y, int z);
|
|
||||||
}
|
}
|
||||||
@@ -4,44 +4,33 @@
|
|||||||
*/
|
*/
|
||||||
package mc.world.flat;
|
package mc.world.flat;
|
||||||
|
|
||||||
import mc.core.block.Block;
|
|
||||||
import mc.core.block.BlockFactory;
|
|
||||||
import mc.core.block.BlockType;
|
|
||||||
import mc.core.world.Biome;
|
import mc.core.world.Biome;
|
||||||
import mc.core.world.Chunk;
|
import mc.core.world.block.Block;
|
||||||
|
import mc.core.world.block.BlockFactory;
|
||||||
|
import mc.core.world.chunk.Chunk;
|
||||||
|
|
||||||
|
import static mc.core.world.block.BlockType.*;
|
||||||
|
|
||||||
public class SimpleChunk implements Chunk {
|
public class SimpleChunk implements Chunk {
|
||||||
@Override
|
private static BlockFactory blockFactory = new BlockFactory();
|
||||||
public int getBlockType(int x, int y, int z) {
|
private final int x, y, z;
|
||||||
if (y == 0) return 7;
|
|
||||||
else if (y >= 1 && y <= 2) return 3;
|
public SimpleChunk(int x, int y, int z) {
|
||||||
else if (y == 3) return 2;
|
this.x = x;
|
||||||
else return 0;
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBlockType(int x, int y, int z, int type) {
|
public Block getBlock(int x, int y, int z) {
|
||||||
|
if (y == 0) return blockFactory.create(BEDROCK);
|
||||||
|
else if (y >= 1 && y <= 2) return blockFactory.create(DIRT);
|
||||||
|
else if (y == 3) return blockFactory.create(GRASS);
|
||||||
|
else return blockFactory.create(AIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBlockMetadata(int x, int y, int z) {
|
public void setBlock(Block block) {
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlockMetadata(int x, int y, int z, int metadata) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getBlockLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlockLight(int x, int y, int z, int lightLevel) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -77,31 +66,16 @@ public class SimpleChunk implements Chunk {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getX() {
|
public int getX() {
|
||||||
return 0;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getY() {
|
public int getY() {
|
||||||
return 0;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getZ() {
|
public int getZ() {
|
||||||
return 0;
|
return z;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlock(int x, int y, int z, Block block) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Block getBlock(int x, int y, int z) {
|
|
||||||
BlockFactory blockFactory = new BlockFactory();
|
|
||||||
|
|
||||||
if (y == 0) return blockFactory.create(BlockType.BEDROCK, 0);
|
|
||||||
else if (y >= 1 && y <= 2) return blockFactory.create(BlockType.DIRT, 0);
|
|
||||||
else if (y == 3) return blockFactory.create(BlockType.GRASS, 0);
|
|
||||||
else return Block.airBlock(x, y, z);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ public class ByteArrayOutputNetStream extends NetOutputStream_p340 {
|
|||||||
writeLong(Double.doubleToLongBits(value));
|
writeLong(Double.doubleToLongBits(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return baos.size();
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] toByteArray() {
|
public byte[] toByteArray() {
|
||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,16 @@ import java.util.UUID;
|
|||||||
public abstract class NetOutputStream_p340 extends NetOutputStream {
|
public abstract class NetOutputStream_p340 extends NetOutputStream {
|
||||||
@Override
|
@Override
|
||||||
public void writeVarInt(int value) {
|
public void writeVarInt(int value) {
|
||||||
do {
|
while ((value & -128) != 0) {
|
||||||
byte temp = (byte)(value & 0b01111111);
|
writeByte(value & 127 | 128);
|
||||||
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
|
|
||||||
value >>>= 7;
|
value >>>= 7;
|
||||||
if (value != 0) {
|
}
|
||||||
temp |= 0b10000000;
|
|
||||||
}
|
writeByte(value);
|
||||||
writeByte(temp);
|
|
||||||
} while (value != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeString(String value) {
|
public void writeString(String value) {
|
||||||
if (value.length() > Short.MAX_VALUE) {
|
if (value.length() > Short.MAX_VALUE) {
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ public enum State {
|
|||||||
.put(PluginMessagePacket.class, 0x18)
|
.put(PluginMessagePacket.class, 0x18)
|
||||||
.put(ChangeGameState.class, 0x1E)
|
.put(ChangeGameState.class, 0x1E)
|
||||||
.put(KeepAlivePacket.class, 0x1F)
|
.put(KeepAlivePacket.class, 0x1F)
|
||||||
|
.put(ChunkDataPacket.class, 0x20)
|
||||||
.put(JoinGamePacket.class, 0x23)
|
.put(JoinGamePacket.class, 0x23)
|
||||||
.put(PlayerAbilitiesPacket.class, 0x2C)
|
.put(PlayerAbilitiesPacket.class, 0x2C)
|
||||||
.put(PlayerListItemPacket.class, 0x2E)
|
.put(PlayerListItemPacket.class, 0x2E)
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* DmitriyMX <dimon550@gmail.com>
|
||||||
|
* 2018-07-21
|
||||||
|
*/
|
||||||
|
package mc.core.network.proto_1_12_2.packets;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import mc.core.Location;
|
||||||
|
import mc.core.network.NetOutputStream;
|
||||||
|
import mc.core.network.SCPacket;
|
||||||
|
import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream;
|
||||||
|
import mc.core.world.Block;
|
||||||
|
import mc.core.world.Chunk;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Packet structure
|
||||||
|
|
||||||
|
- https://wiki.vg/Chunk_Format#Packet_structure
|
||||||
|
|
||||||
|
+------------------------------------------------------+
|
||||||
|
| Field | Type |
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Chunk X | int |
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Chunk Y | int |
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Init Chunk | boolean | ("Ground-Up Continuous")
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Primary Bit Mask | VarInt |
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Size of Data | VarInt |
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Data | Byte array | - https://wiki.vg/Chunk_Format#Data_structure
|
||||||
|
| +------------------------------------------------+ |
|
||||||
|
| | Chunk Section | Byte array | | - https://wiki.vg/Chunk_Format#Chunk_Section_structure
|
||||||
|
| | +------------------------------------------+ | |
|
||||||
|
| | | Bits Per Block | Unsigned Byte | | | (we use 4 bits per block)
|
||||||
|
| | |--------------------|---------------------| | |
|
||||||
|
| | | Palette | Byte array | | | - https://wiki.vg/Chunk_Format#Palettes
|
||||||
|
| | | +------------------------------------+ | | | (we use Indirect type palette)
|
||||||
|
| | | | Size of palette | VarInt | | | |
|
||||||
|
| | | |-----------------|------------------| | | |
|
||||||
|
| | | | Palette | Array of VarInt | | | |
|
||||||
|
| | | +------------------------------------+ | | |
|
||||||
|
| | |--------------------|---------------------| | |
|
||||||
|
| | | Size of Data Array | VarInt | | |
|
||||||
|
| | |--------------------|---------------------| | |
|
||||||
|
| | | Data Array | Array of Long | | |
|
||||||
|
| | |--------------------|---------------------| | |
|
||||||
|
| | | Block Light | Byte Array | | | (Half byte per block)
|
||||||
|
| | |--------------------|---------------------| | |
|
||||||
|
| | | Sky Light | Optional Byte Array | | | (Only if in the Overworld; half byte per block)
|
||||||
|
| | +------------------------------------------+ | |
|
||||||
|
| |-----------------------|------------------------| |
|
||||||
|
| | Biomes | Optional Byte array | |
|
||||||
|
| +------------------------------------------------+ |
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Number of block entities | VarInt |
|
||||||
|
|--------------------------|---------------------------|
|
||||||
|
| Block entities | Array of NBT |
|
||||||
|
+------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ChunkDataPacket implements SCPacket {
|
||||||
|
@Setter
|
||||||
|
private int x;
|
||||||
|
@Setter
|
||||||
|
private int z;
|
||||||
|
@Setter
|
||||||
|
private boolean initChunk = true; // "Ground-Up Continuous"
|
||||||
|
@Getter
|
||||||
|
private List<Chunk> chunks = new ArrayList<>();
|
||||||
|
|
||||||
|
private int serializeBlockState(int id, int state) {
|
||||||
|
return (id << 4) | state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeSelf(NetOutputStream netStream) {
|
||||||
|
netStream.writeInt(x); // Chunk X
|
||||||
|
netStream.writeInt(z); // Chunk Y
|
||||||
|
netStream.writeBoolean(initChunk); // Init Chunk
|
||||||
|
netStream.writeVarInt(0b00000001); // Primary Bit Mask
|
||||||
|
|
||||||
|
final ByteArrayOutputNetStream data = new ByteArrayOutputNetStream();
|
||||||
|
int dataItems = 0;
|
||||||
|
final int airBlockPalette = serializeBlockState(0, 0);
|
||||||
|
|
||||||
|
for (Chunk chunk : chunks) {
|
||||||
|
final List<Integer> palette = new ArrayList<>();
|
||||||
|
palette.add(airBlockPalette);
|
||||||
|
final ByteArrayOutputNetStream dataArray = new ByteArrayOutputNetStream();
|
||||||
|
final ByteArrayOutputNetStream blockLight = new ByteArrayOutputNetStream();
|
||||||
|
final ByteArrayOutputNetStream skyLight = new ByteArrayOutputNetStream();
|
||||||
|
final ByteArrayOutputNetStream biomes = new ByteArrayOutputNetStream();
|
||||||
|
|
||||||
|
long dataValueCompacted = 0;
|
||||||
|
int blockLightCompacted = 0;
|
||||||
|
int skyLightCompacted = 0;
|
||||||
|
|
||||||
|
int idxHalfLong = 0;
|
||||||
|
int idxHalfByte = 0;
|
||||||
|
boolean biomeFinally = false;
|
||||||
|
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
Block block = chunk.getBlock(x, y, z);
|
||||||
|
int blockState = serializeBlockState(block.getId(), block.getState());
|
||||||
|
|
||||||
|
int currentIndexPaletteBlock;
|
||||||
|
if (!palette.contains(blockState)) {
|
||||||
|
palette.add(blockState);
|
||||||
|
currentIndexPaletteBlock = palette.size()-1;
|
||||||
|
} else {
|
||||||
|
currentIndexPaletteBlock = palette.indexOf(blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idxHalfLong == 0) {
|
||||||
|
dataValueCompacted = currentIndexPaletteBlock;
|
||||||
|
idxHalfLong++;
|
||||||
|
} else if (idxHalfLong > 0 && idxHalfLong < 15) {
|
||||||
|
dataValueCompacted = (dataValueCompacted << 4) | currentIndexPaletteBlock;
|
||||||
|
idxHalfLong++;
|
||||||
|
} else {
|
||||||
|
dataValueCompacted = (dataValueCompacted << 4) | currentIndexPaletteBlock;
|
||||||
|
dataArray.writeLong(dataValueCompacted);
|
||||||
|
idxHalfLong = 0;
|
||||||
|
dataItems++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idxHalfByte == 0) {
|
||||||
|
blockLightCompacted = block.getLight();
|
||||||
|
skyLightCompacted = chunk.getSkyLight(x, y, z);
|
||||||
|
idxHalfByte++;
|
||||||
|
} else {
|
||||||
|
blockLightCompacted = (blockLightCompacted << 4) | block.getLight();
|
||||||
|
blockLight.writeByte(blockLightCompacted);
|
||||||
|
skyLightCompacted = (skyLightCompacted << 4) | chunk.getSkyLight(x, y, z);
|
||||||
|
skyLight.writeByte(skyLightCompacted);
|
||||||
|
idxHalfByte = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!biomeFinally) {
|
||||||
|
biomes.writeByte(chunk.getBiome(x, z));
|
||||||
|
if (x == 15 && z == 15) {
|
||||||
|
biomeFinally = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Chunk Section>
|
||||||
|
// <Palette>
|
||||||
|
data.writeUnsignedByte(4); // Bits Per Block
|
||||||
|
data.writeVarInt(palette.size()); // Size of palette
|
||||||
|
palette.forEach(data::writeVarInt); // Palette
|
||||||
|
// </Palette>
|
||||||
|
// <Data Array>
|
||||||
|
data.writeVarInt(dataItems); // Size of Data Array
|
||||||
|
data.writeBytes(dataArray.toByteArray()); // Data Array
|
||||||
|
// </Data Array>
|
||||||
|
// <Block Light>
|
||||||
|
data.writeBytes(blockLight.toByteArray());
|
||||||
|
// </Block Light>
|
||||||
|
// <Sky Light>
|
||||||
|
data.writeBytes(skyLight.toByteArray());
|
||||||
|
// </Sky Light>
|
||||||
|
// </Chunk Section>
|
||||||
|
// <Biomes>
|
||||||
|
data.writeBytes(biomes.toByteArray());
|
||||||
|
// </Biomes>
|
||||||
|
}
|
||||||
|
|
||||||
|
netStream.writeVarInt(data.size()); // Size of Data
|
||||||
|
netStream.writeBytes(data.toByteArray()); // Data
|
||||||
|
netStream.writeVarInt(0); // Number of block entities
|
||||||
|
/* writeNBT */
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,6 +80,22 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
|
|||||||
channel.write(pkt3);
|
channel.write(pkt3);
|
||||||
channel.flush();
|
channel.flush();
|
||||||
|
|
||||||
|
// Send chunk data
|
||||||
|
ChunkDataPacket pkt8 = new ChunkDataPacket();
|
||||||
|
pkt8.setX(0);
|
||||||
|
pkt8.setZ(0);
|
||||||
|
pkt8.getChunks().add(world.getChunk(0,0));
|
||||||
|
pkt8.setInitChunk(true);
|
||||||
|
channel.writeAndFlush(pkt8);
|
||||||
|
|
||||||
|
// One Chunk
|
||||||
|
ChunkDataPacket pkt9 = new ChunkDataPacket();
|
||||||
|
pkt9.setInitChunk(true);
|
||||||
|
pkt9.setX(0);
|
||||||
|
pkt9.setZ(0);
|
||||||
|
pkt9.getChunks().add(world.getChunk(0, 0));
|
||||||
|
channel.writeAndFlush(pkt9);
|
||||||
|
|
||||||
// Player Position And Look
|
// Player Position And Look
|
||||||
PlayerPositionAndLookPacket pkt4 = new PlayerPositionAndLookPacket();
|
PlayerPositionAndLookPacket pkt4 = new PlayerPositionAndLookPacket();
|
||||||
pkt4.setLocation(player.getLocation());
|
pkt4.setLocation(player.getLocation());
|
||||||
|
|||||||
Reference in New Issue
Block a user