PlayerDiggingAndMorePacket
This commit is contained in:
@@ -53,17 +53,18 @@ public enum State {
|
|||||||
|
|
||||||
PLAY(3,
|
PLAY(3,
|
||||||
// client side
|
// client side
|
||||||
Map.of(
|
Map.ofEntries(
|
||||||
0x00, TeleportConfirmPacket.class,
|
Map.entry(0x00, TeleportConfirmPacket.class),
|
||||||
0x04, ClientSettingsPacket.class,
|
Map.entry(0x04, ClientSettingsPacket.class),
|
||||||
0x09, PluginMessagePacket.class,
|
Map.entry(0x09, PluginMessagePacket.class),
|
||||||
0x0B, KeepAlivePacket.class,
|
Map.entry(0x0B, KeepAlivePacket.class),
|
||||||
0x0C, PlayerOnGroundPacket.class,
|
Map.entry(0x0C, PlayerOnGroundPacket.class),
|
||||||
0x0D, PlayerPositionPacket.class,
|
Map.entry(0x0D, PlayerPositionPacket.class),
|
||||||
0x0E, CPlayerPositionAndLookPacket.class,
|
Map.entry(0x0E, CPlayerPositionAndLookPacket.class),
|
||||||
0x0F, PlayerLookPacket.class,
|
Map.entry(0x0F, PlayerLookPacket.class),
|
||||||
0x13, CPlayerAbilitiesPacket.class,
|
Map.entry(0x13, CPlayerAbilitiesPacket.class),
|
||||||
0x15, EntityActionPacket.class
|
Map.entry(0x14, PlayerDiggingAndMorePacket.class),
|
||||||
|
Map.entry(0x15, EntityActionPacket.class)
|
||||||
),
|
),
|
||||||
// server side
|
// server side
|
||||||
Map.of(
|
Map.of(
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package mc.protocol.packets.play.client;
|
||||||
|
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
import mc.protocol.buffer.NetByteBuf;
|
||||||
|
import mc.protocol.model.BlockLocation;
|
||||||
|
import mc.protocol.packets.ClientSidePacket;
|
||||||
|
import mc.protocol.utils.DiggingStatus;
|
||||||
|
import mc.protocol.utils.Face;
|
||||||
|
import mc.protocol.utils.SerializeUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Клиент копает, ломает блок (и не только).
|
||||||
|
*
|
||||||
|
* <p>Структура пакета</p>
|
||||||
|
* <pre>
|
||||||
|
* | FIELD | TYPE | NOTES |
|
||||||
|
* |----------|----------|------------------------------------------|
|
||||||
|
* | Status | VarInt | Действие Игрока к блоку |
|
||||||
|
* | Location | Position | Позиция блока |
|
||||||
|
* | Face | Byte | Сторона блока, с которой взаимодействуют |
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>Возможные действия Игрока к блоку</p>
|
||||||
|
* <pre>
|
||||||
|
* | VALUE | DESCRIPTION | NOTES |
|
||||||
|
* |--------- |-------------------------|---------------------------------------------------------------------------------------|
|
||||||
|
* | 0 | Начал ломать | |
|
||||||
|
* | 1 | Прекратил ломать | Отправляется, когда Игрок отпустил клавишу "копания" |
|
||||||
|
* | 2 | Закончил ломать | Отправляется, когда Игрок закончил ломать блок. Т.е. блок готов сломаться |
|
||||||
|
* | 3 | Бросает стек предметов | Отправляется, когда Игрок с помощью клавиши "Выкинуть предмет"(Q) |
|
||||||
|
* | | | с модификатором(??) для выкидывания полного стека. |
|
||||||
|
* | | | Поле Location всегда будет 0/0/0, а Face всегда -Y. |
|
||||||
|
* | 4 | Бросает предмет | Отправляется, когда Игрок выкидывает предмет. |
|
||||||
|
* | | | Поле Location всегда будет 0/0/0, а Face всегда -Y. |
|
||||||
|
* | 5 | Стреляет стрелой / | Указывает, что текущего состояние удерживаемого предмета должно |
|
||||||
|
* | | Заканчивает есть / | быть обновлено. Например, поедание еды, натягивание луков, использование ведер и т.д. |
|
||||||
|
* | | и т.д. | Поле Location всегда будет 0/0/0, а Face всегда -Y. |
|
||||||
|
* | 6 | Поменять предмет в руке | Отправляется когда Игрок меняет предмет предмет во второй руке через "свап". |
|
||||||
|
* | | | Поле Location всегда будет 0/0/0, а Face всегда -Y. |
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>Значения Стороны блока</p>
|
||||||
|
* <pre>
|
||||||
|
* | VALUE | OFFCET | FACE |
|
||||||
|
* |-------|--------|--------|
|
||||||
|
* | 0 | -Y | Bottom |
|
||||||
|
* | 1 | +Y | Top |
|
||||||
|
* | 2 | -Z | North |
|
||||||
|
* | 3 | +Z | South |
|
||||||
|
* | 4 | -X | West |
|
||||||
|
* | 5 | +X | East |
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Player_Digging">Player Digging</a>
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@ToString
|
||||||
|
public class PlayerDiggingAndMorePacket implements ClientSidePacket {
|
||||||
|
|
||||||
|
private DiggingStatus status;
|
||||||
|
private BlockLocation location;
|
||||||
|
private Face face;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readSelf(NetByteBuf netByteBuf) {
|
||||||
|
this.status = DiggingStatus.valueById(netByteBuf.readVarInt());
|
||||||
|
this.location = SerializeUtil.long2location(netByteBuf.readLong());
|
||||||
|
this.face = Face.valueById(netByteBuf.readByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void passivate() {
|
||||||
|
this.status = null;
|
||||||
|
this.location = null;
|
||||||
|
this.face = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import lombok.Data;
|
|||||||
import mc.protocol.buffer.NetByteBuf;
|
import mc.protocol.buffer.NetByteBuf;
|
||||||
import mc.protocol.packets.ServerSidePacket;
|
import mc.protocol.packets.ServerSidePacket;
|
||||||
import mc.protocol.pool.ProtocolObjectPool;
|
import mc.protocol.pool.ProtocolObjectPool;
|
||||||
import mc.protocol.utils.ChunkSerializeUtil;
|
import mc.protocol.utils.SerializeUtil;
|
||||||
import mc.protocol.world.Chunk;
|
import mc.protocol.world.Chunk;
|
||||||
import mc.protocol.world.ChunkSection;
|
import mc.protocol.world.ChunkSection;
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ public class ChunkDataPacket implements ServerSidePacket {
|
|||||||
|
|
||||||
for (int h = 0; h < 16; h++) {
|
for (int h = 0; h < 16; h++) {
|
||||||
ChunkSection section = chunk.getSection(h);
|
ChunkSection section = chunk.getSection(h);
|
||||||
NetByteBuf data = ChunkSerializeUtil.serializeSection(section);
|
NetByteBuf data = SerializeUtil.serializeChunkSection(section);
|
||||||
dataStructure.writeBytes(data); // Data
|
dataStructure.writeBytes(data); // Data
|
||||||
ProtocolObjectPool.netByteBuf().returnObject(data);
|
ProtocolObjectPool.netByteBuf().returnObject(data);
|
||||||
}
|
}
|
||||||
|
|||||||
32
protocol/src/main/java/mc/protocol/utils/DiggingStatus.java
Normal file
32
protocol/src/main/java/mc/protocol/utils/DiggingStatus.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package mc.protocol.utils;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum DiggingStatus {
|
||||||
|
|
||||||
|
STARTED(0),
|
||||||
|
CANCELLED(1),
|
||||||
|
FINISHED(2),
|
||||||
|
DROP_ITEM_STACK(3),
|
||||||
|
DROP_ITEM(4),
|
||||||
|
HELT_UPDATE_STATE(5),
|
||||||
|
SWAP_HAND(6);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DiggingStatus valueById(int id) {
|
||||||
|
for (DiggingStatus diggingStatus : DiggingStatus.values()) {
|
||||||
|
if (diggingStatus.getId() == id) {
|
||||||
|
return diggingStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final int id;
|
||||||
|
}
|
||||||
31
protocol/src/main/java/mc/protocol/utils/Face.java
Normal file
31
protocol/src/main/java/mc/protocol/utils/Face.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package mc.protocol.utils;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum Face {
|
||||||
|
|
||||||
|
BOTTOM(0),
|
||||||
|
TOP(1),
|
||||||
|
NORTH(2),
|
||||||
|
SOUTH(3),
|
||||||
|
WEST(4),
|
||||||
|
EAST(5);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Face valueById(int id) {
|
||||||
|
for (Face face : Face.values()) {
|
||||||
|
if (face.getId() == id) {
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final int id;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import io.netty.buffer.Unpooled;
|
|||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import mc.protocol.buffer.NetByteBuf;
|
import mc.protocol.buffer.NetByteBuf;
|
||||||
|
import mc.protocol.model.BlockLocation;
|
||||||
import mc.protocol.pool.ProtocolObjectPool;
|
import mc.protocol.pool.ProtocolObjectPool;
|
||||||
import mc.protocol.world.Block;
|
import mc.protocol.world.Block;
|
||||||
import mc.protocol.world.ChunkSection;
|
import mc.protocol.world.ChunkSection;
|
||||||
@@ -12,12 +13,12 @@ import mc.utils.array.BitByteArray;
|
|||||||
import mc.utils.array.BitLongArray;
|
import mc.utils.array.BitLongArray;
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public final class ChunkSerializeUtil {
|
public final class SerializeUtil {
|
||||||
|
|
||||||
private static final int BITS_PER_BLOCK = 13;
|
private static final int BITS_PER_BLOCK = 13;
|
||||||
private static final int ALL_BLOCKS = 16 * 16 * 16;
|
private static final int ALL_BLOCKS = 16 * 16 * 16;
|
||||||
|
|
||||||
public static NetByteBuf serializeSection(ChunkSection section) {
|
public static NetByteBuf serializeChunkSection(ChunkSection section) {
|
||||||
BitArray blockArray = new BitLongArray(BITS_PER_BLOCK, ALL_BLOCKS);
|
BitArray blockArray = new BitLongArray(BITS_PER_BLOCK, ALL_BLOCKS);
|
||||||
BitArray blockLight = new BitByteArray(4, ALL_BLOCKS);
|
BitArray blockLight = new BitByteArray(4, ALL_BLOCKS);
|
||||||
BitArray skyLight = new BitByteArray(4, ALL_BLOCKS);
|
BitArray skyLight = new BitByteArray(4, ALL_BLOCKS);
|
||||||
@@ -56,4 +57,21 @@ public final class ChunkSerializeUtil {
|
|||||||
blockState & 0b1111
|
blockState & 0b1111
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long location2long(BlockLocation blockLocation) {
|
||||||
|
return ((long) (blockLocation.getX() & 0x3FFFFFF) << 38)
|
||||||
|
| ((long) (blockLocation.getZ() & 0x3FFFFFF) << 12)
|
||||||
|
| (blockLocation.getY() & 0xFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockLocation long2location(long value) {
|
||||||
|
BlockLocation blockLocation = new BlockLocation();
|
||||||
|
blockLocation.set(
|
||||||
|
(int) (value >> 38),
|
||||||
|
(int) (value & 0xFFF),
|
||||||
|
(int) (value << 26 >> 38)
|
||||||
|
);
|
||||||
|
|
||||||
|
return blockLocation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ package mc.server.di;
|
|||||||
|
|
||||||
import com.typesafe.config.Config;
|
import com.typesafe.config.Config;
|
||||||
import mc.protocol.model.Location;
|
import mc.protocol.model.Location;
|
||||||
import mc.protocol.utils.ChunkSerializeUtil;
|
import mc.protocol.utils.SerializeUtil;
|
||||||
import mc.protocol.world.World;
|
import mc.protocol.world.World;
|
||||||
import mc.server.world.FlatWorld;
|
import mc.server.world.FlatWorld;
|
||||||
import mc.utils.array.BitArray;
|
import mc.utils.array.BitArray;
|
||||||
@@ -46,7 +46,7 @@ public class FlatWorldModule extends WorldModule {
|
|||||||
|
|
||||||
k += count;
|
k += count;
|
||||||
for (int j = 0; j < count; j++) {
|
for (int j = 0; j < count; j++) {
|
||||||
flatConfig.put(ChunkSerializeUtil.blockIdMetaSerialize(blockId, blockMeta));
|
flatConfig.put(SerializeUtil.blockIdMetaSerialize(blockId, blockMeta));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package mc.server.world;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import mc.protocol.model.BlockLocation;
|
import mc.protocol.model.BlockLocation;
|
||||||
import mc.protocol.utils.ChunkSerializeUtil;
|
import mc.protocol.utils.SerializeUtil;
|
||||||
import mc.protocol.world.Block;
|
import mc.protocol.world.Block;
|
||||||
import mc.protocol.world.ChunkSection;
|
import mc.protocol.world.ChunkSection;
|
||||||
import mc.utils.array.BitArray;
|
import mc.utils.array.BitArray;
|
||||||
@@ -26,7 +26,7 @@ public class FlatChunkSection implements ChunkSection {
|
|||||||
public Block getBlock(int x, int y, int z) {
|
public Block getBlock(int x, int y, int z) {
|
||||||
return blocks.computeIfAbsent(y, y0 -> {
|
return blocks.computeIfAbsent(y, y0 -> {
|
||||||
int blockState = chunkConfig.get((this.y << 4) + y);
|
int blockState = chunkConfig.get((this.y << 4) + y);
|
||||||
int[] blockIdMeta = ChunkSerializeUtil.blockIdMetaDeserialize(blockState);
|
int[] blockIdMeta = SerializeUtil.blockIdMetaDeserialize(blockState);
|
||||||
|
|
||||||
SomeBlock block = new SomeBlock();
|
SomeBlock block = new SomeBlock();
|
||||||
block.setId(blockIdMeta[0]);
|
block.setId(blockIdMeta[0]);
|
||||||
@@ -44,7 +44,7 @@ public class FlatChunkSection implements ChunkSection {
|
|||||||
public int getSkyLight(int x, int y, int z) {
|
public int getSkyLight(int x, int y, int z) {
|
||||||
return sky.computeIfAbsent(y, y0 -> {
|
return sky.computeIfAbsent(y, y0 -> {
|
||||||
int blockState = chunkConfig.get((this.y << 4) + y);
|
int blockState = chunkConfig.get((this.y << 4) + y);
|
||||||
int[] blockIdMeta = ChunkSerializeUtil.blockIdMetaDeserialize(blockState);
|
int[] blockIdMeta = SerializeUtil.blockIdMetaDeserialize(blockState);
|
||||||
|
|
||||||
if (blockIdMeta[0] != 0/*AIR*/) {
|
if (blockIdMeta[0] != 0/*AIR*/) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user