Lot of new packets

This commit is contained in:
Felix Cravic 2020-04-11 17:21:53 +02:00
parent c8ebe32116
commit a8f48aafe9
27 changed files with 529 additions and 12 deletions

View File

@ -1,6 +1,5 @@
package fr.themode.demo;
import fr.themode.demo.entity.ChickenCreature;
import fr.themode.demo.generator.ChunkGeneratorDemo;
import fr.themode.minestom.MinecraftServer;
import fr.themode.minestom.entity.Entity;
@ -79,8 +78,8 @@ public class PlayerInit {
p.teleport(player.getPosition());
}
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
chickenCreature.setInstance(player.getInstance());
//ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
//chickenCreature.setInstance(player.getInstance());
});
@ -96,8 +95,6 @@ public class PlayerInit {
player.setGameMode(GameMode.CREATIVE);
player.teleport(new Position(0, 66, 0));
player.sendHeaderFooter("Its the header", "Its the footer", '&');
/*Random random = new Random();
for (int i = 0; i < 50; i++) {
ChickenCreature chickenCreature = new ChickenCreature();

View File

@ -89,12 +89,11 @@ public class Chunk implements Viewable {
setBlock(index, customBlock.getType(), customBlock.getId(), data, updateConsumer);
}
private void setBlock(int index, short blockType, short customId, Data data, UpdateConsumer updateConsumer) {
private void setBlock(int index, short blockId, short customId, Data data, UpdateConsumer updateConsumer) {
if (blockType != 0
|| (blockType == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
int value = (blockType << 16 | customId & 0xFFFF); // Merge blockType and customId to one unique Integer (16/16 bits)
this.blocks.put(index, value);
if (blockId != 0
|| (blockId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
refreshBlockValue(index, blockId, customId);
} else {
// Block has been deleted, clear cache and return
@ -127,7 +126,7 @@ public class Chunk implements Viewable {
this.updatableBlocksLastUpdate.remove(index);
}
if (isBlockEntity(blockType)) {
if (isBlockEntity(blockId)) {
this.blockEntities.add(index);
} else {
this.blockEntities.remove(index);
@ -162,6 +161,23 @@ public class Chunk implements Viewable {
return id != 0 ? BLOCK_MANAGER.getBlock(id) : null;
}
protected void refreshBlockValue(int index, short blockId, short customId) {
int value = createBlockValue(blockId, customId);
this.blocks.put(index, value);
}
protected void refreshBlockValue(int index, short blockId) {
CustomBlock customBlock = getCustomBlock(index);
short customBlockId = customBlock == null ? 0 : customBlock.getId();
refreshBlockValue(index, blockId, customBlockId);
}
public int createBlockValue(short blockId, short customId) {
// Merge blockType and customId to one unique Integer (16/16 bits)
int value = (blockId << 16 | customId & 0xFFFF);
return value;
}
private int getBlockValue(int index) {
return blocks.getOrDefault(index, 0);
}

View File

@ -7,6 +7,7 @@ import fr.themode.minestom.data.DataContainer;
import fr.themode.minestom.entity.*;
import fr.themode.minestom.instance.batch.BlockBatch;
import fr.themode.minestom.instance.batch.ChunkBatch;
import fr.themode.minestom.instance.block.Block;
import fr.themode.minestom.instance.block.BlockManager;
import fr.themode.minestom.instance.block.CustomBlock;
import fr.themode.minestom.net.PacketWriterUtils;
@ -41,6 +42,8 @@ public abstract class Instance implements BlockModifier, DataContainer {
this.uniqueId = uniqueId;
}
public abstract void refreshBlockId(int x, int y, int z, short blockId);
// Used to call BlockBreakEvent and sending particle packet if true
public abstract void breakBlock(Player player, BlockPosition blockPosition);
@ -129,6 +132,10 @@ public abstract class Instance implements BlockModifier, DataContainer {
return Collections.unmodifiableSet(getEntitiesInChunk(ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ())));
}
public void refreshBlockId(int x, int y, int z, Block block) {
refreshBlockId(x, y, z, block.getBlockId());
}
public void loadChunk(int chunkX, int chunkZ) {
loadChunk(chunkX, chunkZ, null);
}

View File

@ -80,6 +80,22 @@ public class InstanceContainer extends Instance {
}
}
@Override
public void refreshBlockId(int x, int y, int z, short blockId) {
Chunk chunk = getChunkAt(x, z);
synchronized (chunk) {
byte chunkX = (byte) (x % 16);
byte chunkY = (byte) y;
byte chunkZ = (byte) (z % 16);
int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
chunk.refreshBlockValue(index, blockId);
// TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket
sendBlockChange(chunk, x, y, z, blockId);
}
}
private void callBlockDestroy(Chunk chunk, int index, int x, int y, int z) {
CustomBlock previousBlock = chunk.getCustomBlock(index);
if (previousBlock != null) {

View File

@ -23,6 +23,11 @@ public class SharedInstance extends Instance {
this.instanceContainer = instanceContainer;
}
@Override
public void refreshBlockId(int x, int y, int z, short blockId) {
instanceContainer.refreshBlockId(x, y, z, blockId);
}
@Override
public void breakBlock(Player player, BlockPosition blockPosition) {
instanceContainer.breakBlock(player, blockPosition);

View File

@ -1,5 +1,6 @@
package fr.themode.minestom.instance.block;
import fr.themode.minestom.instance.block.rule.BlockPlacementRule;
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
@ -11,6 +12,8 @@ public class BlockManager {
private Short2ObjectMap<CustomBlock> blocksInternalId = new Short2ObjectOpenHashMap<>();
private Map<String, CustomBlock> blocksId = new HashMap<>();
private Map<Block, BlockPlacementRule> placementRules = new HashMap<>();
public void registerCustomBlock(CustomBlock customBlock) {
String identifier = customBlock.getIdentifier();
short id = customBlock.getId();
@ -18,6 +21,10 @@ public class BlockManager {
this.blocksId.put(identifier, customBlock);
}
public void registerBlockPlacementRule(BlockPlacementRule blockPlacementRule) {
this.placementRules.put(blockPlacementRule.getBlock(), blockPlacementRule);
}
public CustomBlock getBlock(String identifier) {
return blocksId.get(identifier);
}

View File

@ -0,0 +1,22 @@
package fr.themode.minestom.instance.block.rule;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.instance.block.Block;
import fr.themode.minestom.utils.BlockPosition;
public abstract class BlockPlacementRule {
private Block block;
public BlockPlacementRule(Block block) {
this.block = block;
}
public abstract void onPlace(Instance instance, BlockPosition blockPosition);
public abstract void onNeighborPlace(Instance instance, int offsetX, int offsetY, int offsetZ);
public Block getBlock() {
return block;
}
}

View File

@ -0,0 +1,14 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.packet.client.play.ClientTabCompletePacket;
public class TabCompleteListener {
public static void listener(ClientTabCompletePacket packet, Player player) {
// TODO when is it called?
System.out.println("text: " + packet.text);
}
}

View File

@ -34,6 +34,7 @@ public class PacketListenerManager {
addListener(ClientSettingsPacket.class, SettingsListener::listener);
addListener(ClientCreativeInventoryActionPacket.class, CreativeInventoryActionListener::listener);
addListener(ClientCraftRecipeRequest.class, RecipeListener::listener);
addListener(ClientTabCompletePacket.class, TabCompleteListener::listener);
}
public <T extends ClientPlayPacket> void process(T packet, Player player) {

View File

@ -9,6 +9,7 @@ public class ClientPlayPacketsHandler extends ClientPacketsHandler {
register(0x03, ClientChatMessagePacket.class);
register(0x04, ClientStatusPacket.class);
register(0x05, ClientSettingsPacket.class);
register(0x06, ClientTabCompletePacket.class);
register(0x07, ClientWindowConfirmationPacket.class);
register(0x08, ClientClickWindowButtonPacket.class); // Marked as 0x07 on wiki.vg
register(0x09, ClientClickWindowPacket.class);
@ -17,19 +18,30 @@ public class ClientPlayPacketsHandler extends ClientPacketsHandler {
register(0x0E, ClientUseEntityPacket.class);
register(0x0F, ClientKeepAlivePacket.class);
// 0x10 packet not used server-side
register(0x11, ClientPlayerPositionPacket.class);
register(0x12, ClientPlayerPositionAndLookPacket.class);
register(0x13, ClientPlayerLookPacket.class);
register(0x14, ClientPlayerPacket.class);
register(0x15, ClientVehicleMovePacket.class);
register(0x16, ClientSteerBoatPacket.class);
register(0x17, ClientPickItemPacket.class);
register(0x18, ClientCraftRecipeRequest.class);
register(0x19, ClientPlayerAbilitiesPacket.class);
register(0x1A, ClientPlayerDiggingPacket.class);
register(0x1B, ClientEntityActionPacket.class);
register(0x1C, ClientSteerVehiclePacket.class);
register(0x1D, ClientRecipeBookData.class);
register(0x1E, ClientNameItemPacket.class);
register(0x1F, ClientResourcePackStatusPacket.class);
register(0x20, ClientAdvancementTabPacket.class);
register(0x21, ClientSelectTradePacket.class);
register(0x23, ClientHeldItemChangePacket.class);
register(0x24, ClientUpdateCommandBlockPacket.class);
register(0x25, ClientUpdateCommandBlockMinecartPacket.class);
register(0x26, ClientCreativeInventoryActionPacket.class);
register(0x29, ClientUpdateSignPacket.class);
register(0x2A, ClientAnimationPacket.class);
register(0x2C, ClientPlayerBlockPlacementPacket.class);
register(0x2D, ClientUseItemPacket.class);

View File

@ -0,0 +1,31 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientAdvancementTabPacket extends ClientPlayPacket {
public Action action;
public String tabIdentifier;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readVarInt(i -> {
action = Action.values()[i];
if (action == Action.OPENED_TAB) {
reader.readSizedString((string, length) -> {
tabIdentifier = string;
callback.run();
});
} else {
callback.run();
}
});
}
public enum Action {
OPENED_TAB,
CLOSED_SCREEN
}
}

View File

@ -0,0 +1,17 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientNameItemPacket extends ClientPlayPacket {
public String itemName;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readSizedString((string, length) -> {
itemName = string;
callback.run();
});
}
}

View File

@ -0,0 +1,17 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientPickItemPacket extends ClientPlayPacket {
public int slotToUse;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readVarInt(i -> {
slotToUse = i;
callback.run();
});
}
}

View File

@ -0,0 +1,22 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientResourcePackStatusPacket extends ClientPlayPacket {
public Result result;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readVarInt(i -> {
result = Result.values()[i];
callback.run();
});
}
public enum Result {
SUCCESS, DECLINED, FAILED_DOWNLOAD, ACCEPTED
}
}

View File

@ -0,0 +1,17 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientSelectTradePacket extends ClientPlayPacket {
public int selectedSlot;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readVarInt(i -> {
selectedSlot = i;
callback.run();
});
}
}

View File

@ -0,0 +1,16 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import java.util.UUID;
public class ClientSpectatePacket extends ClientPlayPacket {
public UUID targetUuid;
@Override
public void read(PacketReader reader, Runnable callback) {
// TODO reader uuid
}
}

View File

@ -0,0 +1,19 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientSteerBoatPacket extends ClientPlayPacket {
public boolean leftPaddleTurning;
public boolean rightPaddleTurning;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readBoolean(value -> leftPaddleTurning = value);
reader.readBoolean(value -> {
rightPaddleTurning = value;
callback.run();
});
}
}

View File

@ -0,0 +1,19 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientTabCompletePacket extends ClientPlayPacket {
public int transactionId;
public String text;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readVarInt(i -> transactionId = i);
reader.readSizedString((string, length) -> {
text = string;
callback.run();
});
}
}

View File

@ -0,0 +1,21 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientUpdateCommandBlockMinecartPacket extends ClientPlayPacket {
public int entityId;
public String command;
public boolean trackOutput;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readVarInt(i -> entityId = i);
reader.readSizedString((string, length) -> command = string);
reader.readBoolean(value -> {
trackOutput = value;
callback.run();
});
}
}

View File

@ -0,0 +1,29 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.BlockPosition;
public class ClientUpdateCommandBlockPacket extends ClientPlayPacket {
public BlockPosition blockPosition;
public String command;
public Mode mode;
public byte flags;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readBlockPosition(blockPosition1 -> blockPosition = blockPosition1);
reader.readSizedString((string, length) -> command = string);
reader.readVarInt(i -> mode = Mode.values()[i]);
reader.readByte(value -> {
flags = value;
callback.run();
});
}
public enum Mode {
SEQUENCE, AUTO, REDSTONE
}
}

View File

@ -0,0 +1,27 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.utils.BlockPosition;
public class ClientUpdateSignPacket extends ClientPlayPacket {
public BlockPosition blockPosition;
public String line1;
public String line2;
public String line3;
public String line4;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readBlockPosition(blockPosition1 -> blockPosition = blockPosition1);
reader.readSizedString((string, length) -> line1 = string);
reader.readSizedString((string, length) -> line2 = string);
reader.readSizedString((string, length) -> line3 = string);
reader.readSizedString((string, length) -> {
line4 = string;
callback.run();
});
}
}

View File

@ -0,0 +1,23 @@
package fr.themode.minestom.net.packet.client.play;
import fr.themode.minestom.net.packet.PacketReader;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
public class ClientVehicleMovePacket extends ClientPlayPacket {
public double x, y, z;
public float yaw, pitch;
@Override
public void read(PacketReader reader, Runnable callback) {
reader.readDouble(v -> x = v);
reader.readDouble(v -> y = v);
reader.readDouble(v -> z = v);
reader.readFloat(value -> yaw = value);
reader.readFloat(value -> {
pitch = value;
callback.run();
});
}
}

View File

@ -0,0 +1,24 @@
package fr.themode.minestom.net.packet.server.play;
import fr.themode.minestom.net.packet.PacketWriter;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.ServerPacketIdentifier;
public class OpenHorseWindowPacket implements ServerPacket {
public byte windowId;
public int slotCount;
public int entityId;
@Override
public void write(PacketWriter writer) {
writer.writeByte(windowId);
writer.writeVarInt(slotCount);
writer.writeInt(entityId);
}
@Override
public int getId() {
return ServerPacketIdentifier.OPEN_HORSE_WINDOW;
}
}

View File

@ -0,0 +1,49 @@
package fr.themode.minestom.net.packet.server.play;
import fr.themode.minestom.net.packet.PacketWriter;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.ServerPacketIdentifier;
public class StatisticsPacket implements ServerPacket {
public Statistic[] statistics;
@Override
public void write(PacketWriter writer) {
writer.writeVarInt(statistics.length);
for (Statistic statistic : statistics) {
statistic.write(writer);
}
}
@Override
public int getId() {
return ServerPacketIdentifier.STATISTICS;
}
public enum StatisticCategory {
MINED,
CRAFTED,
USED,
BROKEN,
PICKED_UP,
DROPPED,
KILLED,
KILLED_BY,
CUSTOM
}
public static class Statistic {
public StatisticCategory category;
public int statisticIdentifier;
public int value;
private void write(PacketWriter writer) {
writer.writeVarInt(category.ordinal());
writer.writeVarInt(statisticIdentifier);
writer.writeVarInt(value);
}
}
}

View File

@ -0,0 +1,40 @@
package fr.themode.minestom.net.packet.server.play;
import fr.themode.minestom.net.packet.PacketWriter;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.ServerPacketIdentifier;
public class TabCompletePacket implements ServerPacket {
public int transactionId;
public int start;
public int length;
public Match[] matches;
@Override
public void write(PacketWriter writer) {
writer.writeVarInt(transactionId);
writer.writeVarInt(start);
writer.writeVarInt(length);
writer.writeVarInt(matches.length);
for (Match match : matches) {
writer.writeSizedString(match.match);
writer.writeBoolean(match.hasTooltip);
if (match.hasTooltip)
writer.writeSizedString(match.tooltip);
}
}
@Override
public int getId() {
return ServerPacketIdentifier.TAB_COMPLETE;
}
public static class Match {
public String match;
public boolean hasTooltip;
public String tooltip; // Chat
}
}

View File

@ -0,0 +1,42 @@
package fr.themode.minestom.net.packet.server.play;
import fr.themode.minestom.net.packet.PacketWriter;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.ServerPacketIdentifier;
public class UpdateLightPacket implements ServerPacket {
public int chunkX;
public int chunkZ;
public int skyLightMask;
public int blockLightMask;
public int emptySkyLightMask;
public int emptyBlockLightMask;
public byte[] skyLight;
public byte[] blockLight;
@Override
public void write(PacketWriter writer) {
writer.writeVarInt(chunkX);
writer.writeVarInt(chunkZ);
writer.writeVarInt(skyLightMask);
writer.writeVarInt(blockLightMask);
writer.writeVarInt(emptySkyLightMask);
writer.writeVarInt(emptyBlockLightMask);
writer.writeVarInt(2048); // Always 2048 length
writer.writeBytes(skyLight);
writer.writeVarInt(2048); // Always 2048 length
writer.writeBytes(blockLight);
}
@Override
public int getId() {
return ServerPacketIdentifier.UPDATE_LIGHT;
}
}

View File

@ -60,7 +60,14 @@ public class RegistryMain {
Block block = Block.valueOf(registryItem.name);
material.setIdentifier(registryItem.itemId, block);
} catch (IllegalArgumentException e) {
material.setIdentifier(registryItem.itemId, null);
switch (material) {
case REDSTONE:
material.setIdentifier(registryItem.itemId, Block.REDSTONE_WIRE);
break;
default:
material.setIdentifier(registryItem.itemId, null);
break;
}
}
}
}