Archived
0

PlayerDiggingAndMorePacket

This commit is contained in:
2021-07-18 13:57:52 +03:00
parent 376a5264e3
commit 31d795e0d9
8 changed files with 184 additions and 20 deletions

View File

@@ -53,17 +53,18 @@ public enum State {
PLAY(3,
// client side
Map.of(
0x00, TeleportConfirmPacket.class,
0x04, ClientSettingsPacket.class,
0x09, PluginMessagePacket.class,
0x0B, KeepAlivePacket.class,
0x0C, PlayerOnGroundPacket.class,
0x0D, PlayerPositionPacket.class,
0x0E, CPlayerPositionAndLookPacket.class,
0x0F, PlayerLookPacket.class,
0x13, CPlayerAbilitiesPacket.class,
0x15, EntityActionPacket.class
Map.ofEntries(
Map.entry(0x00, TeleportConfirmPacket.class),
Map.entry(0x04, ClientSettingsPacket.class),
Map.entry(0x09, PluginMessagePacket.class),
Map.entry(0x0B, KeepAlivePacket.class),
Map.entry(0x0C, PlayerOnGroundPacket.class),
Map.entry(0x0D, PlayerPositionPacket.class),
Map.entry(0x0E, CPlayerPositionAndLookPacket.class),
Map.entry(0x0F, PlayerLookPacket.class),
Map.entry(0x13, CPlayerAbilitiesPacket.class),
Map.entry(0x14, PlayerDiggingAndMorePacket.class),
Map.entry(0x15, EntityActionPacket.class)
),
// server side
Map.of(

View File

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

View File

@@ -5,7 +5,7 @@ import lombok.Data;
import mc.protocol.buffer.NetByteBuf;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.pool.ProtocolObjectPool;
import mc.protocol.utils.ChunkSerializeUtil;
import mc.protocol.utils.SerializeUtil;
import mc.protocol.world.Chunk;
import mc.protocol.world.ChunkSection;
@@ -101,7 +101,7 @@ public class ChunkDataPacket implements ServerSidePacket {
for (int h = 0; h < 16; h++) {
ChunkSection section = chunk.getSection(h);
NetByteBuf data = ChunkSerializeUtil.serializeSection(section);
NetByteBuf data = SerializeUtil.serializeChunkSection(section);
dataStructure.writeBytes(data); // Data
ProtocolObjectPool.netByteBuf().returnObject(data);
}

View 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;
}

View 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;
}

View File

@@ -4,6 +4,7 @@ import io.netty.buffer.Unpooled;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import mc.protocol.buffer.NetByteBuf;
import mc.protocol.model.BlockLocation;
import mc.protocol.pool.ProtocolObjectPool;
import mc.protocol.world.Block;
import mc.protocol.world.ChunkSection;
@@ -12,12 +13,12 @@ import mc.utils.array.BitByteArray;
import mc.utils.array.BitLongArray;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ChunkSerializeUtil {
public final class SerializeUtil {
private static final int BITS_PER_BLOCK = 13;
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 blockLight = new BitByteArray(4, ALL_BLOCKS);
BitArray skyLight = new BitByteArray(4, ALL_BLOCKS);
@@ -56,4 +57,21 @@ public final class ChunkSerializeUtil {
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;
}
}

View File

@@ -2,7 +2,7 @@ package mc.server.di;
import com.typesafe.config.Config;
import mc.protocol.model.Location;
import mc.protocol.utils.ChunkSerializeUtil;
import mc.protocol.utils.SerializeUtil;
import mc.protocol.world.World;
import mc.server.world.FlatWorld;
import mc.utils.array.BitArray;
@@ -46,7 +46,7 @@ public class FlatWorldModule extends WorldModule {
k += count;
for (int j = 0; j < count; j++) {
flatConfig.put(ChunkSerializeUtil.blockIdMetaSerialize(blockId, blockMeta));
flatConfig.put(SerializeUtil.blockIdMetaSerialize(blockId, blockMeta));
}
}

View File

@@ -3,7 +3,7 @@ package mc.server.world;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import mc.protocol.model.BlockLocation;
import mc.protocol.utils.ChunkSerializeUtil;
import mc.protocol.utils.SerializeUtil;
import mc.protocol.world.Block;
import mc.protocol.world.ChunkSection;
import mc.utils.array.BitArray;
@@ -26,7 +26,7 @@ public class FlatChunkSection implements ChunkSection {
public Block getBlock(int x, int y, int z) {
return blocks.computeIfAbsent(y, y0 -> {
int blockState = chunkConfig.get((this.y << 4) + y);
int[] blockIdMeta = ChunkSerializeUtil.blockIdMetaDeserialize(blockState);
int[] blockIdMeta = SerializeUtil.blockIdMetaDeserialize(blockState);
SomeBlock block = new SomeBlock();
block.setId(blockIdMeta[0]);
@@ -44,7 +44,7 @@ public class FlatChunkSection implements ChunkSection {
public int getSkyLight(int x, int y, int z) {
return sky.computeIfAbsent(y, y0 -> {
int blockState = chunkConfig.get((this.y << 4) + y);
int[] blockIdMeta = ChunkSerializeUtil.blockIdMetaDeserialize(blockState);
int[] blockIdMeta = SerializeUtil.blockIdMetaDeserialize(blockState);
if (blockIdMeta[0] != 0/*AIR*/) {
return 0;