Archived
0

Merge remote-tracking branch 'origin/dmitriymx/devcode' into proto_1.12.2

Warning! Potentially incorrect packet data! Need fixed
This commit is contained in:
2018-08-02 23:56:14 +03:00
8 changed files with 241 additions and 35 deletions

View File

@@ -0,0 +1,15 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-08-02
*/
package mc.core.world;
import mc.core.Location;
public interface Block {
int getId();
int getState();
int getMetadata();
int getLight();
Location getLocation();
}

View File

@@ -4,16 +4,15 @@
*/ */
package mc.core.world; package mc.core.world;
import mc.core.Location;
/* 16x16x16 */ /* 16x16x16 */
public interface Chunk { public interface Chunk {
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);

View File

@@ -0,0 +1,20 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-08-02
*/
package mc.world.flat;
import lombok.Getter;
import lombok.Setter;
import mc.core.Location;
import mc.core.world.Block;
@Getter
@Setter
public class SimpleBlock implements Block {
private int id;
private int state;
private int metadata;
private int light;
private Location location;
}

View File

@@ -4,40 +4,26 @@
*/ */
package mc.world.flat; package mc.world.flat;
import mc.core.world.Block;
import mc.core.world.Chunk; import mc.core.world.Chunk;
public class SimpleChunk implements Chunk { public class SimpleChunk implements Chunk {
@Override @Override
public int getBlockType(int x, int y, int z) { public Block getBlock(int x, int y, int z) {
if (y == 0) return 7; SimpleBlock block = new SimpleBlock();
else if (y >= 1 && y <= 2) return 3; block.setMetadata(0);
else if (y == 3) return 2; block.setLight(0);
else return 0;
if (y == 0) block.setId(7);
else if (y >= 1 && y <= 2) block.setId(3);
else if (y == 3) block.setId(2);
else block.setId(0);
return block;
} }
@Override @Override
public void setBlockType(int x, int y, int z, int type) { public void setBlock(Block block) {
}
@Override
public int getBlockMetadata(int x, int y, int z) {
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

View File

@@ -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();
} }

View File

@@ -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)

View File

@@ -0,0 +1,165 @@
/*
* 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.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.ByteArrayOutputStream;
import java.io.IOException;
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 long serializeBlockState(Block block) {
return (block.getId() << 4) | block.getState();
}
@Override
public void writeSelf(NetOutputStream netStream) {
netStream.writeInt(x); // Chunk X
netStream.writeInt(z); // Chunk Y
netStream.writeBoolean(initChunk); // Init Chunk
netStream.writeVarInt(0b11111111); // Primary Bit Mask
final ByteArrayOutputNetStream data = new ByteArrayOutputNetStream();
for (Chunk chunk : chunks) {
final List<Long> palette = new ArrayList<>();
final ByteArrayOutputNetStream dataArray = new ByteArrayOutputNetStream();
final ByteArrayOutputNetStream blockLight = new ByteArrayOutputNetStream();
final ByteArrayOutputNetStream skyLight = new ByteArrayOutputNetStream();
final ByteArrayOutputNetStream biomes = new ByteArrayOutputNetStream();
int blockLightCompacted = 0;
boolean flagFirstHalf = true;
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);
long blockState = serializeBlockState(block);
int currentIndexPaletteBlock;
if (!palette.contains(blockState)) {
palette.add(blockState);
currentIndexPaletteBlock = palette.size()-1;
} else {
currentIndexPaletteBlock = palette.indexOf(blockState);
}
dataArray.writeLong(currentIndexPaletteBlock);
if (flagFirstHalf) {
blockLightCompacted = block.getLight();
flagFirstHalf = false;
} else {
blockLightCompacted = (blockLightCompacted << 4) | block.getLight();
blockLight.writeByte(blockLightCompacted);
flagFirstHalf = true;
skyLight.writeByte(0b11111111); //FIXME
}
biomes.writeByte(chunk.getBiome(x, z));
}
}
}
// <Chunk Section>
// <Palette>
data.writeUnsignedByte(4); // Bits Per Block
data.writeVarInt(palette.size()); // Size of palette
palette.stream()
.mapToInt(Long::intValue)
.forEach(data::writeVarInt); // Palette
// </Palette>
// <Data Array>
data.writeVarInt(dataArray.size()); // 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 */
}
}

View File

@@ -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());