mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-13 19:51:27 +01:00
Switched to SimpleNet
This commit is contained in:
parent
dedc17f42e
commit
81c0626e57
@ -20,6 +20,6 @@ dependencies {
|
||||
implementation 'com.github.luben:zstd-jni:1.4.3-1'
|
||||
implementation 'com.esotericsoftware:reflectasm:1.11.9'
|
||||
implementation 'com.github.LynnOwens:starlite:9971b899f7'
|
||||
//implementation 'com.github.jhg023:SimpleNet:1.4.14'
|
||||
implementation 'com.github.jhg023:SimpleNet:1.4.14'
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,5 @@
|
||||
package fr.themode.minestom;
|
||||
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.adamaq01.ozao.net.server.Connection;
|
||||
import fr.adamaq01.ozao.net.server.Server;
|
||||
import fr.adamaq01.ozao.net.server.ServerHandler;
|
||||
import fr.adamaq01.ozao.net.server.backend.tcp.TCPServer;
|
||||
import fr.themode.minestom.data.DataManager;
|
||||
import fr.themode.minestom.entity.EntityManager;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
@ -13,17 +8,21 @@ import fr.themode.minestom.instance.InstanceManager;
|
||||
import fr.themode.minestom.instance.demo.StoneBlock;
|
||||
import fr.themode.minestom.listener.PacketListenerManager;
|
||||
import fr.themode.minestom.net.ConnectionManager;
|
||||
import fr.themode.minestom.net.ConnectionUtils;
|
||||
import fr.themode.minestom.net.PacketProcessor;
|
||||
import fr.themode.minestom.net.packet.PacketReader;
|
||||
import fr.themode.minestom.net.packet.client.status.LegacyServerListPingPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.KeepAlivePacket;
|
||||
import fr.themode.minestom.net.protocol.MinecraftProtocol;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
import simplenet.Server;
|
||||
|
||||
public class Main {
|
||||
|
||||
// Thread number
|
||||
public static final int THREAD_COUNT_PACKET_WRITER = 5;
|
||||
public static final int THREAD_COUNT_PACKET_WRITER = 2;
|
||||
public static final int THREAD_COUNT_CHUNK_IO = 2;
|
||||
public static final int THREAD_COUNT_CHUNK_BATCH = 3;
|
||||
public static final int THREAD_COUNT_ENTITIES = 3;
|
||||
public static final int THREAD_COUNT_CHUNK_BATCH = 2;
|
||||
public static final int THREAD_COUNT_ENTITIES = 2;
|
||||
public static final int THREAD_COUNT_PLAYERS_ENTITIES = 2;
|
||||
|
||||
public static final int TICK_MS = 50;
|
||||
@ -57,39 +56,42 @@ public class Main {
|
||||
|
||||
blockManager.registerBlock(StoneBlock::new);
|
||||
|
||||
server = new TCPServer(new MinecraftProtocol()).addHandler(new ServerHandler() {
|
||||
@Override
|
||||
public void onConnect(Server server, Connection connection) {
|
||||
System.out.println("A connection");
|
||||
}
|
||||
server = new Server(136434);
|
||||
|
||||
@Override
|
||||
public void onDisconnect(Server server, Connection connection) {
|
||||
server.onConnect(client -> {
|
||||
System.out.println("CONNECTION");
|
||||
|
||||
client.postDisconnect(() -> {
|
||||
System.out.println("A Disconnection");
|
||||
if (packetProcessor.hasPlayerConnection(connection)) {
|
||||
Player player = connectionManager.getPlayer(packetProcessor.getPlayerConnection(connection));
|
||||
if (packetProcessor.hasPlayerConnection(client)) {
|
||||
Player player = connectionManager.getPlayer(packetProcessor.getPlayerConnection(client));
|
||||
if (player != null) {
|
||||
|
||||
player.remove();
|
||||
|
||||
connectionManager.removePlayer(player.getPlayerConnection());
|
||||
}
|
||||
packetProcessor.removePlayerConnection(connection);
|
||||
packetProcessor.removePlayerConnection(client);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(Server server, Connection connection, Packet packet) {
|
||||
packetProcessor.process(connection, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Server server, Connection connection, Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
}
|
||||
ConnectionUtils.readVarIntAlways(client, length -> {
|
||||
if (length == 0xFE) { // Legacy server ping
|
||||
LegacyServerListPingPacket legacyServerListPingPacket = new LegacyServerListPingPacket();
|
||||
legacyServerListPingPacket.read(new PacketReader(client, 0, 0), () -> {
|
||||
legacyServerListPingPacket.process(null, null);
|
||||
});
|
||||
} else {
|
||||
final int varIntLength = Utils.lengthVarInt(length);
|
||||
ConnectionUtils.readVarInt(client, packetId -> {
|
||||
int offset = varIntLength + Utils.lengthVarInt(packetId);
|
||||
packetProcessor.process(client, packetId, length, offset);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
server.bind(25565);
|
||||
server.bind("localhost", 25565);
|
||||
System.out.println("Server started");
|
||||
|
||||
long tickDistance = TICK_MS * 1000000;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.themode.minestom.entity;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.Viewable;
|
||||
import fr.themode.minestom.collision.BoundingBox;
|
||||
@ -15,11 +14,13 @@ import fr.themode.minestom.net.packet.server.play.*;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
import fr.themode.minestom.utils.Vector;
|
||||
import fr.themode.minestom.utils.*;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public abstract class Entity implements Viewable, DataContainer {
|
||||
|
||||
@ -569,49 +570,48 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
public EntityMetaDataPacket getMetadataPacket() {
|
||||
EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket();
|
||||
metaDataPacket.entityId = getEntityId();
|
||||
metaDataPacket.data = getMetadataBuffer();
|
||||
metaDataPacket.consumer = getMetadataConsumer();
|
||||
return metaDataPacket;
|
||||
}
|
||||
|
||||
public Buffer getMetadataBuffer() {
|
||||
Buffer buffer = Buffer.create();
|
||||
fillMetadataIndex(buffer, 0);
|
||||
fillMetadataIndex(buffer, 1);
|
||||
fillMetadataIndex(buffer, 5);
|
||||
return buffer;
|
||||
public Consumer<Packet> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
fillMetadataIndex(packet, 0);
|
||||
fillMetadataIndex(packet, 1);
|
||||
fillMetadataIndex(packet, 5);
|
||||
};
|
||||
}
|
||||
|
||||
protected void sendMetadataIndex(int index) {
|
||||
Buffer buffer = Buffer.create();
|
||||
fillMetadataIndex(buffer, index);
|
||||
|
||||
EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket();
|
||||
metaDataPacket.entityId = getEntityId();
|
||||
metaDataPacket.data = buffer;
|
||||
metaDataPacket.consumer = packet -> {
|
||||
fillMetadataIndex(packet, index);
|
||||
};
|
||||
|
||||
sendPacketToViewersAndSelf(metaDataPacket);
|
||||
}
|
||||
|
||||
private void fillMetadataIndex(Buffer buffer, int index) {
|
||||
private void fillMetadataIndex(Packet packet, int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
fillStateMetadata(buffer);
|
||||
fillStateMetadata(packet);
|
||||
break;
|
||||
case 1:
|
||||
fillAirTickMetaData(buffer);
|
||||
fillAirTickMetaData(packet);
|
||||
break;
|
||||
case 2:
|
||||
fillCustomNameMetaData(buffer);
|
||||
fillCustomNameMetaData(packet);
|
||||
break;
|
||||
case 5:
|
||||
fillNoGravityMetaData(buffer);
|
||||
fillNoGravityMetaData(packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void fillStateMetadata(Buffer buffer) {
|
||||
buffer.putByte((byte) 0);
|
||||
buffer.putByte(METADATA_BYTE);
|
||||
private void fillStateMetadata(Packet packet) {
|
||||
packet.putByte((byte) 0);
|
||||
packet.putByte(METADATA_BYTE);
|
||||
byte index0 = 0;
|
||||
if (onFire)
|
||||
index0 += 1;
|
||||
@ -629,7 +629,25 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
index0 += 64;
|
||||
if (usingElytra)
|
||||
index0 += 128;
|
||||
buffer.putByte(index0);
|
||||
packet.putByte(index0);
|
||||
}
|
||||
|
||||
private void fillAirTickMetaData(Packet packet) {
|
||||
packet.putByte((byte) 1);
|
||||
packet.putByte(METADATA_VARINT);
|
||||
Utils.writeVarInt(packet, air);
|
||||
}
|
||||
|
||||
private void fillCustomNameMetaData(Packet packet) {
|
||||
packet.putByte((byte) 2);
|
||||
packet.putByte(METADATA_CHAT);
|
||||
Utils.writeString(packet, customName);
|
||||
}
|
||||
|
||||
private void fillNoGravityMetaData(Packet packet) {
|
||||
packet.putByte((byte) 5);
|
||||
packet.putByte(METADATA_BOOLEAN);
|
||||
packet.putBoolean(noGravity);
|
||||
}
|
||||
|
||||
protected void sendSynchronization() {
|
||||
@ -643,24 +661,6 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
sendPacketToViewers(getPassengersPacket());
|
||||
}
|
||||
|
||||
private void fillAirTickMetaData(Buffer buffer) {
|
||||
buffer.putByte((byte) 1);
|
||||
buffer.putByte(METADATA_VARINT);
|
||||
Utils.writeVarInt(buffer, air);
|
||||
}
|
||||
|
||||
private void fillCustomNameMetaData(Buffer buffer) {
|
||||
buffer.putByte((byte) 2);
|
||||
buffer.putByte(METADATA_CHAT);
|
||||
Utils.writeString(buffer, customName);
|
||||
}
|
||||
|
||||
private void fillNoGravityMetaData(Buffer buffer) {
|
||||
buffer.putByte((byte) 5);
|
||||
buffer.putByte(METADATA_BOOLEAN);
|
||||
buffer.putBoolean(noGravity);
|
||||
}
|
||||
|
||||
private boolean shouldUpdate() {
|
||||
return (float) (System.currentTimeMillis() - lastUpdate) >= Main.TICK_MS * 0.9f; // Margin of error
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public abstract class EntityCreature extends LivingEntity {
|
||||
spawnMobPacket.entityType = getEntityType();
|
||||
spawnMobPacket.position = getPosition();
|
||||
spawnMobPacket.headPitch = 0;
|
||||
spawnMobPacket.metadata = getMetadataBuffer();
|
||||
spawnMobPacket.consumer = getMetadataConsumer();
|
||||
playerConnection.sendPacket(entityPacket);
|
||||
playerConnection.sendPacket(spawnMobPacket);
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package fr.themode.minestom.entity;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ItemEntity extends ObjectEntity {
|
||||
|
||||
@ -36,12 +38,13 @@ public class ItemEntity extends ObjectEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer getMetadataBuffer() {
|
||||
Buffer buffer = super.getMetadataBuffer();
|
||||
buffer.putByte((byte) 7);
|
||||
buffer.putByte(METADATA_SLOT);
|
||||
Utils.writeItemStack(buffer, itemStack);
|
||||
return buffer;
|
||||
public Consumer<Packet> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
packet.putByte((byte) 7);
|
||||
packet.putByte(METADATA_SLOT);
|
||||
Utils.writeItemStack(packet, itemStack);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.themode.minestom.entity;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.collision.BoundingBox;
|
||||
import fr.themode.minestom.entity.property.Attribute;
|
||||
import fr.themode.minestom.event.PickupItemEvent;
|
||||
@ -9,8 +8,10 @@ import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.packet.server.play.AnimationPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.CollectItemPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.EntityPropertiesPacket;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public abstract class LivingEntity extends Entity {
|
||||
|
||||
@ -67,20 +68,21 @@ public abstract class LivingEntity extends Entity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer getMetadataBuffer() {
|
||||
Buffer buffer = super.getMetadataBuffer();
|
||||
buffer.putByte((byte) 7);
|
||||
buffer.putByte(METADATA_BYTE);
|
||||
byte activeHandValue = 0;
|
||||
if (isHandActive) {
|
||||
activeHandValue += 1;
|
||||
if (activeHand)
|
||||
activeHandValue += 2;
|
||||
if (riptideSpinAttack)
|
||||
activeHandValue += 4;
|
||||
}
|
||||
buffer.putByte(activeHandValue);
|
||||
return buffer;
|
||||
public Consumer<Packet> getMetadataConsumer() {
|
||||
return packet -> {
|
||||
super.getMetadataConsumer().accept(packet);
|
||||
packet.putByte((byte) 7);
|
||||
packet.putByte(METADATA_BYTE);
|
||||
byte activeHandValue = 0;
|
||||
if (isHandActive) {
|
||||
activeHandValue += 1;
|
||||
if (activeHand)
|
||||
activeHandValue += 2;
|
||||
if (riptideSpinAttack)
|
||||
activeHandValue += 4;
|
||||
}
|
||||
packet.putByte(activeHandValue);
|
||||
};
|
||||
}
|
||||
|
||||
public void damage(float value) {
|
||||
|
@ -156,7 +156,7 @@ public class Player extends LivingEntity {
|
||||
|
||||
setEventCallback(PlayerSpawnEvent.class, event -> {
|
||||
System.out.println("SPAWN");
|
||||
setGameMode(GameMode.CREATIVE);
|
||||
setGameMode(GameMode.SURVIVAL);
|
||||
teleport(new Position(0, 66, 0));
|
||||
|
||||
/*ChickenCreature chickenCreature = new ChickenCreature();
|
||||
@ -191,7 +191,7 @@ public class Player extends LivingEntity {
|
||||
teamsPacket.entities = new String[]{getUsername()};
|
||||
sendPacketToViewersAndSelf(teamsPacket);
|
||||
|
||||
setAttribute(Attribute.MAX_HEALTH, 40);
|
||||
setAttribute(Attribute.MAX_HEALTH, 10);
|
||||
heal();
|
||||
|
||||
setExp(0.9f);
|
||||
@ -502,6 +502,8 @@ public class Player extends LivingEntity {
|
||||
sendPacketToViewers(spawnPlayerPacket);
|
||||
playerConnection.sendPacket(getPropertiesPacket());
|
||||
sendUpdateHealthPacket();
|
||||
syncEquipments();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -637,7 +639,7 @@ public class Player extends LivingEntity {
|
||||
DisconnectPacket disconnectPacket = new DisconnectPacket();
|
||||
disconnectPacket.message = message;
|
||||
playerConnection.sendPacket(disconnectPacket);
|
||||
playerConnection.getConnection().close();
|
||||
playerConnection.getClient().close();
|
||||
}
|
||||
|
||||
public LevelType getLevelType() {
|
||||
@ -736,6 +738,12 @@ public class Player extends LivingEntity {
|
||||
sendPacketToViewers(getEquipmentPacket(slot));
|
||||
}
|
||||
|
||||
public void syncEquipments() {
|
||||
for (EntityEquipmentPacket.Slot slot : EntityEquipmentPacket.Slot.values()) {
|
||||
syncEquipment(slot);
|
||||
}
|
||||
}
|
||||
|
||||
protected EntityEquipmentPacket getEquipmentPacket(EntityEquipmentPacket.Slot slot) {
|
||||
EntityEquipmentPacket equipmentPacket = new EntityEquipmentPacket();
|
||||
equipmentPacket.entityId = getEntityId();
|
||||
@ -820,7 +828,11 @@ public class Player extends LivingEntity {
|
||||
public int getChunkRange() {
|
||||
int serverRange = Main.CHUNK_VIEW_DISTANCE;
|
||||
int playerRange = getSettings().viewDistance;
|
||||
return serverRange;//playerRange < serverRange ? playerRange : serverRange;
|
||||
if (playerRange == 0) {
|
||||
return serverRange; // Didn't receive settings packet yet
|
||||
} else {
|
||||
return playerRange < serverRange ? playerRange : serverRange;
|
||||
}
|
||||
}
|
||||
|
||||
public long getLastKeepAlive() {
|
||||
|
@ -1,13 +1,12 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.Viewable;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
|
||||
import fr.themode.minestom.utils.PacketUtils;
|
||||
import fr.themode.minestom.utils.SerializerUtils;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
@ -33,7 +32,7 @@ public class Chunk implements Viewable {
|
||||
|
||||
// Cache
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private Buffer fullDataPacket;
|
||||
private Packet fullDataPacket;
|
||||
|
||||
public Chunk(Biome biome, int chunkX, int chunkZ) {
|
||||
this.biome = biome;
|
||||
@ -93,7 +92,7 @@ public class Chunk implements Viewable {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
public Buffer getFullDataPacket() {
|
||||
public Packet getFullDataPacket() {
|
||||
return fullDataPacket;
|
||||
}
|
||||
|
||||
@ -106,7 +105,7 @@ public class Chunk implements Viewable {
|
||||
return blockEntities;
|
||||
}
|
||||
|
||||
public void setFullDataPacket(Buffer fullDataPacket) {
|
||||
public void setFullDataPacket(Packet fullDataPacket) {
|
||||
this.fullDataPacket = fullDataPacket;
|
||||
}
|
||||
|
||||
@ -151,8 +150,7 @@ public class Chunk implements Viewable {
|
||||
}
|
||||
|
||||
protected void refreshDataPacket() {
|
||||
Packet packet = PacketUtils.writePacket(getFreshFullDataPacket());
|
||||
this.fullDataPacket = PacketUtils.encode(packet); // TODO write packet buffer in another thread (heavy calculations)
|
||||
PacketUtils.writePacket(getFreshFullDataPacket(), packet -> fullDataPacket = packet); // TODO write packet buffer in another thread (heavy calculations)
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,11 +1,11 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.entity.*;
|
||||
import fr.themode.minestom.utils.BlockPosition;
|
||||
import fr.themode.minestom.utils.ChunkUtils;
|
||||
import fr.themode.minestom.utils.Position;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@ -70,11 +70,9 @@ public abstract class Instance implements BlockModifier {
|
||||
|
||||
//
|
||||
protected void sendChunkUpdate(Collection<Player> players, Chunk chunk) {
|
||||
Buffer chunkData = chunk.getFullDataPacket();
|
||||
chunkData.getData().retain(players.size()).markReaderIndex();
|
||||
Packet chunkData = chunk.getFullDataPacket();
|
||||
players.forEach(player -> {
|
||||
player.getPlayerConnection().sendUnencodedPacket(chunkData);
|
||||
chunkData.getData().resetReaderIndex();
|
||||
player.getPlayerConnection().sendPacket(chunkData);
|
||||
});
|
||||
}
|
||||
//
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.event.PlayerBlockBreakEvent;
|
||||
import fr.themode.minestom.net.PacketWriterUtils;
|
||||
@ -151,10 +150,7 @@ public class InstanceContainer extends Instance {
|
||||
|
||||
@Override
|
||||
public void sendChunkUpdate(Player player, Chunk chunk) {
|
||||
Buffer chunkData = chunk.getFullDataPacket();
|
||||
chunkData.getData().retain(1).markReaderIndex();
|
||||
player.getPlayerConnection().sendUnencodedPacket(chunkData);
|
||||
chunkData.getData().resetReaderIndex();
|
||||
player.getPlayerConnection().sendPacket(chunk.getFullDataPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
170
src/main/java/fr/themode/minestom/net/ConnectionUtils.java
Normal file
170
src/main/java/fr/themode/minestom/net/ConnectionUtils.java
Normal file
@ -0,0 +1,170 @@
|
||||
package fr.themode.minestom.net;
|
||||
|
||||
import simplenet.Client;
|
||||
import simplenet.packet.Packet;
|
||||
import simplenet.utility.exposed.consumer.ByteConsumer;
|
||||
import simplenet.utility.exposed.predicate.BytePredicate;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
public class ConnectionUtils {
|
||||
|
||||
/**
|
||||
* Reads a variable-length number from a {@link Client}
|
||||
*
|
||||
* @param client The {@link Client} to read from
|
||||
* @param maxBytes The maximum size (in bytes) of the VarNum
|
||||
* @param callback The {@link LongConsumer} callback for the read VarNum
|
||||
*/
|
||||
private static void readVarNum(Client client, int maxBytes, LongConsumer callback) {
|
||||
client.readByteUntil(new BytePredicate() {
|
||||
int count;
|
||||
long value;
|
||||
|
||||
@Override
|
||||
public boolean test(byte data) {
|
||||
value |= ((int) data & 0x7F) << (7 * count);
|
||||
if (++count > maxBytes) throw new RuntimeException("VarNum is too big");
|
||||
if ((data & 0x80) == 0) {
|
||||
callback.accept(value);
|
||||
return false;
|
||||
} else return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a variable-length number to a byte array
|
||||
*
|
||||
* @param value The value to wrapPacket
|
||||
* @return The array containing the VarNum's bytes
|
||||
*/
|
||||
public static byte[] writeVarNum(long value) {
|
||||
final byte[] bytes = new byte[10];
|
||||
int written = 0;
|
||||
do {
|
||||
byte temp = (byte) (value & 0x7F);
|
||||
value >>>= 7;
|
||||
if (value != 0) {
|
||||
temp |= 0x80;
|
||||
}
|
||||
bytes[written++] = temp;
|
||||
} while (value != 0);
|
||||
return Arrays.copyOfRange(bytes, 0, written);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a variable-length String from the {@link Client}
|
||||
*
|
||||
* @param client The {@link Client} to read from
|
||||
* @param callback The {@link Consumer<String>} callback for the read String
|
||||
*/
|
||||
public static void readString(Client client, Consumer<String> callback) {
|
||||
readVarInt(client, stringLength ->
|
||||
client.readBytes(stringLength, bytes ->
|
||||
callback.accept(new String(bytes, UTF_8))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a variable-length integer from the client, up to 5 bytes long
|
||||
*
|
||||
* @param client The client to read from
|
||||
* @param callback See {@link ConnectionUtils#readVarNum(Client, int, LongConsumer)}
|
||||
*/
|
||||
public static void readVarInt(Client client, IntConsumer callback) {
|
||||
readVarNum(client, 5, it -> callback.accept((int) it));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a variable-length long from the client, up to 10 bytes long
|
||||
*
|
||||
* @param client The client to read from
|
||||
* @param callback See {@link ConnectionUtils#readVarNum(Client, int, LongConsumer)}
|
||||
*/
|
||||
public static void readVarLong(Client client, LongConsumer callback) {
|
||||
readVarNum(client, 10, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a legacy string to a packet container
|
||||
* Legacy strings are prefixed with their length in characters as a short
|
||||
* Modern strings are prefixed with their length in bytes as a VarInt
|
||||
*
|
||||
* @param string The String to write to the packet container
|
||||
* @param charset The {@link Charset} this string is encoded in
|
||||
* @param packet The {@link Packet} for this string to be written to
|
||||
*/
|
||||
public static void writeLegacyString(String string, Charset charset, Packet packet) {
|
||||
final int length = string.length();
|
||||
packet.putShort(length);
|
||||
packet.putBytes(string.getBytes(charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a legacy UTF-8 String to a packet container
|
||||
*
|
||||
* @param string The String to write
|
||||
* @param packet The {@link Packet} for this String to be written to
|
||||
*/
|
||||
public static void writeLegacyString(String string, Packet packet) {
|
||||
writeLegacyString(string, UTF_8, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a standard string to a packet container
|
||||
*
|
||||
* @param string The String to write to the packet container
|
||||
* @param charset The {@link Charset} this String is encoded in
|
||||
* @param packet The {@link Packet} for this string to be written to
|
||||
*/
|
||||
public static void writeString(String string, Charset charset, Packet packet) {
|
||||
final byte[] bytes = string.getBytes(charset);
|
||||
final int length = bytes.length;
|
||||
final byte[] strLen = writeVarNum(length);
|
||||
packet.putBytes(strLen);
|
||||
packet.putBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a standard UTF-8 string to a packet container
|
||||
*
|
||||
* @param string The String to write
|
||||
* @param packet The {@link Packet} for this String to be written to
|
||||
*/
|
||||
public static void writeString(String string, Packet packet) {
|
||||
writeString(string, UTF_8, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a Variable Length integer from the {@link Client}, restarting when complete
|
||||
*
|
||||
* @param client The {@link Client} to read from
|
||||
* @param callback The {@link IntConsumer} callback for the read VarInt
|
||||
*/
|
||||
public static void readVarIntAlways(Client client, IntConsumer callback) {
|
||||
client.readByteAlways(new ByteConsumer() {
|
||||
int count;
|
||||
long value;
|
||||
|
||||
@Override
|
||||
public void accept(byte data) {
|
||||
value |= ((int) data & 0x7F) << (7 * count);
|
||||
if (++count > 5) throw new RuntimeException("VarNum is too big");
|
||||
if ((data & 0x80) == 0) {
|
||||
callback.accept((int) value);
|
||||
count = 0;
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
package fr.themode.minestom.net;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.adamaq01.ozao.net.server.Connection;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.packet.PacketReader;
|
||||
@ -13,17 +10,16 @@ import fr.themode.minestom.net.packet.client.handler.ClientPlayPacketsHandler;
|
||||
import fr.themode.minestom.net.packet.client.handler.ClientStatusPacketsHandler;
|
||||
import fr.themode.minestom.net.packet.client.handshake.HandshakePacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
import simplenet.Client;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static fr.themode.minestom.net.protocol.MinecraftProtocol.PACKET_ID_IDENTIFIER;
|
||||
|
||||
public class PacketProcessor {
|
||||
|
||||
private Map<Connection, PlayerConnection> connectionPlayerConnectionMap = new HashMap<>();
|
||||
private Map<Client, PlayerConnection> connectionPlayerConnectionMap = new HashMap<>();
|
||||
|
||||
private ConnectionManager connectionManager;
|
||||
|
||||
@ -42,25 +38,20 @@ public class PacketProcessor {
|
||||
|
||||
private List<Integer> printBlackList = Arrays.asList(17, 18, 19);
|
||||
|
||||
public void process(Connection connection, Packet packet) {
|
||||
int id = packet.get(PACKET_ID_IDENTIFIER);
|
||||
Buffer buffer = packet.getPayload();
|
||||
connectionPlayerConnectionMap.get(connection);
|
||||
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(connection, c -> new PlayerConnection(c));
|
||||
public void process(Client client, int id, int length, int offset) {
|
||||
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(client, c -> new PlayerConnection(client));
|
||||
ConnectionState connectionState = playerConnection.getConnectionState();
|
||||
|
||||
if (!printBlackList.contains(id)) {
|
||||
//System.out.println("RECEIVED ID: 0x" + Integer.toHexString(id) + " State: " + connectionState);
|
||||
}
|
||||
|
||||
PacketReader packetReader = new PacketReader(buffer);
|
||||
PacketReader packetReader = new PacketReader(client, length, offset);
|
||||
|
||||
if (connectionState == ConnectionState.UNKNOWN) {
|
||||
// Should be handshake packet
|
||||
if (id == 0) {
|
||||
HandshakePacket handshakePacket = new HandshakePacket();
|
||||
handshakePacket.read(packetReader);
|
||||
handshakePacket.process(playerConnection, connectionManager);
|
||||
handshakePacket.read(packetReader, () -> handshakePacket.process(playerConnection, connectionManager));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -69,18 +60,15 @@ public class PacketProcessor {
|
||||
case PLAY:
|
||||
Player player = connectionManager.getPlayer(playerConnection);
|
||||
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketInstance(id);
|
||||
playPacket.read(packetReader);
|
||||
player.addPacketToQueue(playPacket); // Processed during player tick update
|
||||
playPacket.read(packetReader, () -> player.addPacketToQueue(playPacket));
|
||||
break;
|
||||
case LOGIN:
|
||||
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(id);
|
||||
loginPacket.read(packetReader);
|
||||
loginPacket.process(playerConnection, connectionManager);
|
||||
loginPacket.read(packetReader, () -> loginPacket.process(playerConnection, connectionManager));
|
||||
break;
|
||||
case STATUS:
|
||||
ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(id);
|
||||
statusPacket.read(packetReader);
|
||||
statusPacket.process(playerConnection, connectionManager);
|
||||
statusPacket.read(packetReader, () -> statusPacket.process(playerConnection, connectionManager));
|
||||
break;
|
||||
case UNKNOWN:
|
||||
// Ignore packet (unexpected)
|
||||
@ -88,15 +76,15 @@ public class PacketProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
public PlayerConnection getPlayerConnection(Connection connection) {
|
||||
return connectionPlayerConnectionMap.get(connection);
|
||||
public PlayerConnection getPlayerConnection(Client client) {
|
||||
return connectionPlayerConnectionMap.get(client);
|
||||
}
|
||||
|
||||
public boolean hasPlayerConnection(Connection connection) {
|
||||
return connectionPlayerConnectionMap.containsKey(connection);
|
||||
public boolean hasPlayerConnection(Client client) {
|
||||
return connectionPlayerConnectionMap.containsKey(client);
|
||||
}
|
||||
|
||||
public void removePlayerConnection(Connection connection) {
|
||||
connectionPlayerConnectionMap.remove(connection);
|
||||
public void removePlayerConnection(Client client) {
|
||||
connectionPlayerConnectionMap.remove(client);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
package fr.themode.minestom.net;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
import fr.themode.minestom.utils.PacketUtils;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@ -15,12 +14,11 @@ import java.util.function.Consumer;
|
||||
|
||||
public class PacketWriterUtils {
|
||||
|
||||
private static volatile ExecutorService batchesPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_PACKET_WRITER);
|
||||
private static ExecutorService batchesPool = Executors.newFixedThreadPool(Main.THREAD_COUNT_PACKET_WRITER);
|
||||
|
||||
public static void writeCallbackPacket(ServerPacket serverPacket, Consumer<Buffer> consumer) {
|
||||
public static void writeCallbackPacket(ServerPacket serverPacket, Consumer<Packet> consumer) {
|
||||
batchesPool.execute(() -> {
|
||||
Packet p = PacketUtils.writePacket(serverPacket);
|
||||
consumer.accept(PacketUtils.encode(p));
|
||||
PacketUtils.writePacket(serverPacket, packet -> consumer.accept(packet));
|
||||
});
|
||||
}
|
||||
|
||||
@ -30,22 +28,17 @@ public class PacketWriterUtils {
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
Packet p = PacketUtils.writePacket(serverPacket);
|
||||
Buffer encoded = PacketUtils.encode(p);
|
||||
|
||||
encoded.getData().retain(size).markReaderIndex();
|
||||
for (Player player : players) {
|
||||
player.getPlayerConnection().writeUnencodedPacket(encoded);
|
||||
encoded.getData().resetReaderIndex();
|
||||
}
|
||||
PacketUtils.writePacket(serverPacket, packet -> {
|
||||
for (Player player : players) {
|
||||
player.getPlayerConnection().writeUnencodedPacket(packet);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static void writeAndSend(PlayerConnection playerConnection, ServerPacket serverPacket) {
|
||||
batchesPool.execute(() -> {
|
||||
Packet p = PacketUtils.writePacket(serverPacket);
|
||||
Buffer encoded = PacketUtils.encode(p);
|
||||
playerConnection.writeUnencodedPacket(encoded);
|
||||
PacketUtils.writePacket(serverPacket, packet -> playerConnection.sendPacket(packet));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,55 +1,88 @@
|
||||
package fr.themode.minestom.net.packet;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.ConnectionUtils;
|
||||
import fr.themode.minestom.utils.BlockPosition;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
import fr.themode.minestom.utils.consumer.StringConsumer;
|
||||
import simplenet.Client;
|
||||
import simplenet.utility.exposed.consumer.BooleanConsumer;
|
||||
import simplenet.utility.exposed.consumer.ByteConsumer;
|
||||
import simplenet.utility.exposed.consumer.FloatConsumer;
|
||||
import simplenet.utility.exposed.consumer.ShortConsumer;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.DoubleConsumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.LongConsumer;
|
||||
|
||||
public class PacketReader {
|
||||
|
||||
private Buffer buffer;
|
||||
private Client client;
|
||||
private int length;
|
||||
private int sizeOffset;
|
||||
|
||||
public PacketReader(Buffer buffer) {
|
||||
this.buffer = buffer;
|
||||
public PacketReader(Client client, int length, int sizeOffset) {
|
||||
this.client = client;
|
||||
this.length = length;
|
||||
this.sizeOffset = sizeOffset;
|
||||
}
|
||||
|
||||
public int readVarInt() {
|
||||
return Utils.readVarInt(buffer);
|
||||
public void readVarInt(IntConsumer consumer) {
|
||||
ConnectionUtils.readVarInt(client, value -> {
|
||||
consumer.accept(value);
|
||||
sizeOffset += Utils.lengthVarInt(value);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean readBoolean() {
|
||||
return buffer.getBoolean();
|
||||
public void readBoolean(BooleanConsumer consumer) {
|
||||
sizeOffset += Byte.BYTES;
|
||||
client.readBoolean(consumer);
|
||||
}
|
||||
|
||||
public byte readByte() {
|
||||
return buffer.getByte();
|
||||
public void readByte(ByteConsumer consumer) {
|
||||
sizeOffset += Byte.BYTES;
|
||||
client.readByte(consumer);
|
||||
}
|
||||
|
||||
public short readShort() {
|
||||
return buffer.getShort();
|
||||
public void readShort(ShortConsumer consumer) {
|
||||
sizeOffset += Short.BYTES;
|
||||
client.readShort(consumer);
|
||||
}
|
||||
|
||||
public long readLong() {
|
||||
return buffer.getLong();
|
||||
public void readLong(LongConsumer consumer) {
|
||||
sizeOffset += Long.BYTES;
|
||||
client.readLong(consumer);
|
||||
}
|
||||
|
||||
public float readFloat() {
|
||||
return buffer.getFloat();
|
||||
public void readFloat(FloatConsumer consumer) {
|
||||
sizeOffset += Float.BYTES;
|
||||
client.readFloat(consumer);
|
||||
}
|
||||
|
||||
public double readDouble() {
|
||||
return buffer.getDouble();
|
||||
public void readDouble(DoubleConsumer consumer) {
|
||||
sizeOffset += Double.BYTES;
|
||||
client.readDouble(consumer);
|
||||
}
|
||||
|
||||
public String readSizedString() {
|
||||
return Utils.readString(buffer);
|
||||
public void readSizedString(StringConsumer consumer) {
|
||||
Utils.readString(client, consumer);
|
||||
}
|
||||
|
||||
public byte[] getRemainingBytes() {
|
||||
return buffer.getAllBytes();
|
||||
public void readSizedString(Consumer<String> consumer) {
|
||||
readSizedString((string, length1) -> consumer.accept(string));
|
||||
}
|
||||
|
||||
public BlockPosition readBlockPosition() {
|
||||
return Utils.readPosition(buffer);
|
||||
public void getRemainingBytes(int offset, Consumer<byte[]> consumer) {
|
||||
int size = length - 1 - offset;
|
||||
client.readBytes(size, consumer);
|
||||
}
|
||||
|
||||
public void getRemainingBytes(Consumer<byte[]> consumer) {
|
||||
getRemainingBytes(0, consumer);
|
||||
}
|
||||
|
||||
public void readBlockPosition(Consumer<BlockPosition> consumer) {
|
||||
Utils.readPosition(client, consumer);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,54 +1,55 @@
|
||||
package fr.themode.minestom.net.packet;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.utils.BlockPosition;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PacketWriter {
|
||||
|
||||
private Buffer buffer;
|
||||
private Packet packet;
|
||||
|
||||
public PacketWriter(Buffer buffer) {
|
||||
this.buffer = buffer;
|
||||
public PacketWriter(Packet packet) {
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public void writeBoolean(boolean b) {
|
||||
buffer.putBoolean(b);
|
||||
packet.putBoolean(b);
|
||||
}
|
||||
|
||||
public void writeByte(byte b) {
|
||||
buffer.putByte(b);
|
||||
packet.putByte(b);
|
||||
}
|
||||
|
||||
public void writeShort(short s) {
|
||||
buffer.putShort(s);
|
||||
packet.putShort(s);
|
||||
}
|
||||
|
||||
public void writeInt(int i) {
|
||||
buffer.putInt(i);
|
||||
packet.putInt(i);
|
||||
}
|
||||
|
||||
public void writeLong(long l) {
|
||||
buffer.putLong(l);
|
||||
packet.putLong(l);
|
||||
}
|
||||
|
||||
public void writeFloat(float f) {
|
||||
buffer.putFloat(f);
|
||||
packet.putFloat(f);
|
||||
}
|
||||
|
||||
public void writeDouble(double d) {
|
||||
buffer.putDouble(d);
|
||||
packet.putDouble(d);
|
||||
}
|
||||
|
||||
public void writeVarInt(int i) {
|
||||
Utils.writeVarInt(buffer, i);
|
||||
Utils.writeVarInt(packet, i);
|
||||
}
|
||||
|
||||
public void writeSizedString(String string) {
|
||||
Utils.writeString(buffer, string);
|
||||
Utils.writeString(packet, string);
|
||||
}
|
||||
|
||||
public void writeVarIntArray(int[] array) {
|
||||
@ -63,7 +64,7 @@ public class PacketWriter {
|
||||
}
|
||||
|
||||
public void writeBytes(byte[] bytes) {
|
||||
buffer.putBytes(bytes);
|
||||
packet.putBytes(bytes);
|
||||
}
|
||||
|
||||
public void writeStringArray(String[] array) {
|
||||
@ -77,8 +78,9 @@ public class PacketWriter {
|
||||
}
|
||||
}
|
||||
|
||||
public void writeBuffer(Buffer buffer) {
|
||||
this.buffer.putBuffer(buffer);
|
||||
public void write(Consumer<Packet> consumer) {
|
||||
if (consumer != null)
|
||||
consumer.accept(packet);
|
||||
}
|
||||
|
||||
public void writeUuid(UUID uuid) {
|
||||
@ -87,15 +89,15 @@ public class PacketWriter {
|
||||
}
|
||||
|
||||
public void writeBlockPosition(BlockPosition blockPosition) {
|
||||
Utils.writePosition(buffer, blockPosition);
|
||||
Utils.writePosition(packet, blockPosition);
|
||||
}
|
||||
|
||||
public void writeBlockPosition(int x, int y, int z) {
|
||||
Utils.writePosition(buffer, x, y, z);
|
||||
Utils.writePosition(packet, x, y, z);
|
||||
}
|
||||
|
||||
public void writeItemStack(ItemStack itemStack) {
|
||||
Utils.writeItemStack(buffer, itemStack);
|
||||
Utils.writeItemStack(packet, itemStack);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ import fr.themode.minestom.net.packet.PacketReader;
|
||||
|
||||
public interface ClientPacket {
|
||||
|
||||
void read(PacketReader reader);
|
||||
void read(PacketReader reader, Runnable callback);
|
||||
|
||||
}
|
||||
|
@ -3,21 +3,24 @@ package fr.themode.minestom.net.packet.client.handler;
|
||||
import com.esotericsoftware.reflectasm.ConstructorAccess;
|
||||
import fr.themode.minestom.net.packet.client.ClientPacket;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClientPacketsHandler {
|
||||
|
||||
private Map<Integer, ConstructorAccess<? extends ClientPacket>> constructorAccessMap = new HashMap<>();
|
||||
private static final int SIZE = 0xFF;
|
||||
|
||||
private ConstructorAccess[] constructorAccesses = new ConstructorAccess[SIZE];
|
||||
|
||||
public void register(int id, Class<? extends ClientPacket> packet) {
|
||||
this.constructorAccessMap.put(id, ConstructorAccess.get(packet));
|
||||
constructorAccesses[id] = ConstructorAccess.get(packet);
|
||||
}
|
||||
|
||||
public ClientPacket getPacketInstance(int id) {
|
||||
ClientPacket packet = constructorAccessMap.get(id).newInstance();
|
||||
if (packet == null)
|
||||
if (id > SIZE)
|
||||
throw new IllegalStateException("Packet ID 0x" + Integer.toHexString(id) + " has been tried to be parsed, debug needed");
|
||||
|
||||
ConstructorAccess<? extends ClientPacket> constructorAccess = constructorAccesses[id];
|
||||
if (constructorAccess == null)
|
||||
System.err.println("Packet id 0x" + Integer.toHexString(id) + " isn't registered!");
|
||||
ClientPacket packet = constructorAccess.newInstance();
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,20 @@ import fr.themode.minestom.net.player.PlayerConnection;
|
||||
|
||||
public class HandshakePacket implements ClientPreplayPacket {
|
||||
|
||||
private int protocolVersion;
|
||||
private String serverAddress;
|
||||
private short serverPort;
|
||||
private int nextState;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
int protocolVersion = reader.readVarInt();
|
||||
String serverAddress = reader.readSizedString();
|
||||
short serverPort = reader.readShort();
|
||||
this.nextState = reader.readVarInt();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> protocolVersion = value);
|
||||
reader.readSizedString(s -> serverAddress = s);
|
||||
reader.readShort(value -> serverPort = value);
|
||||
reader.readVarInt(value -> {
|
||||
nextState = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -106,7 +106,10 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.username = reader.readSizedString();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readSizedString(s -> {
|
||||
username = s;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,10 @@ public class ClientAnimationPacket extends ClientPlayPacket {
|
||||
public Player.Hand hand;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.hand = Player.Hand.values()[reader.readVarInt()];
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> {
|
||||
this.hand = Player.Hand.values()[value];
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,10 @@ public class ClientChatMessagePacket extends ClientPlayPacket {
|
||||
public String message;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.message = reader.readSizedString();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readSizedString(s -> {
|
||||
message = s;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,15 @@ public class ClientClickWindowPacket extends ClientPlayPacket {
|
||||
// TODO clicked item
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.windowId = reader.readByte();
|
||||
this.slot = reader.readShort();
|
||||
this.button = reader.readByte();
|
||||
this.actionNumber = reader.readShort();
|
||||
this.mode = reader.readVarInt();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readByte(value -> windowId = value);
|
||||
reader.readShort(value -> slot = value);
|
||||
reader.readByte(value -> button = value);
|
||||
reader.readShort(value -> actionNumber = value);
|
||||
reader.readVarInt(value -> {
|
||||
mode = value;
|
||||
callback.run();
|
||||
});
|
||||
// TODO read clicked item
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,10 @@ public class ClientCloseWindow extends ClientPlayPacket {
|
||||
public int windowId;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.windowId = reader.readVarInt();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> {
|
||||
windowId = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,8 @@ public class ClientConfirmTransactionPacket extends ClientPlayPacket {
|
||||
public boolean accepted;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
callback.run();
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,13 @@ public class ClientEntityActionPacket extends ClientPlayPacket {
|
||||
public int horseJumpBoost;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.playerId = reader.readVarInt();
|
||||
this.action = Action.values()[reader.readVarInt()];
|
||||
this.horseJumpBoost = reader.readVarInt();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> playerId = value);
|
||||
reader.readVarInt(value -> action = Action.values()[value]);
|
||||
reader.readVarInt(value -> {
|
||||
horseJumpBoost = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
|
@ -8,7 +8,10 @@ public class ClientHeldItemChangePacket extends ClientPlayPacket {
|
||||
public short slot;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.slot = reader.readShort();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readShort(value -> {
|
||||
slot = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,10 @@ public class ClientKeepAlivePacket extends ClientPlayPacket {
|
||||
public long id;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.id = reader.readLong();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readLong(value -> {
|
||||
id = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,12 @@ public class ClientPlayerAbilitiesPacket extends ClientPlayPacket {
|
||||
public float walkingSpeed;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.flags = reader.readByte();
|
||||
this.flyingSpeed = reader.readFloat();
|
||||
this.walkingSpeed = reader.readFloat();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readByte(value -> flags = value);
|
||||
reader.readFloat(value -> flyingSpeed = value);
|
||||
reader.readFloat(value -> {
|
||||
walkingSpeed = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,17 @@ public class ClientPlayerBlockPlacementPacket extends ClientPlayPacket {
|
||||
public boolean insideBlock;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.hand = Player.Hand.values()[reader.readVarInt()];
|
||||
this.blockPosition = reader.readBlockPosition();
|
||||
this.blockFace = ClientPlayerDiggingPacket.BlockFace.values()[reader.readVarInt()];
|
||||
this.cursorPositionX = reader.readFloat();
|
||||
this.cursorPositionY = reader.readFloat();
|
||||
this.cursorPositionZ = reader.readFloat();
|
||||
this.insideBlock = reader.readBoolean();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> hand = Player.Hand.values()[value]);
|
||||
reader.readBlockPosition(blockPosition1 -> blockPosition = blockPosition1);
|
||||
reader.readVarInt(value -> blockFace = ClientPlayerDiggingPacket.BlockFace.values()[value]);
|
||||
reader.readFloat(value -> cursorPositionX = value);
|
||||
reader.readFloat(value -> cursorPositionY = value);
|
||||
reader.readFloat(value -> cursorPositionZ = value);
|
||||
reader.readBoolean(value -> {
|
||||
insideBlock = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,10 +11,13 @@ public class ClientPlayerDiggingPacket extends ClientPlayPacket {
|
||||
public BlockFace blockFace;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.status = Status.values()[reader.readVarInt()];
|
||||
this.blockPosition = reader.readBlockPosition();
|
||||
this.blockFace = BlockFace.values()[reader.readVarInt()];
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> status = Status.values()[value]);
|
||||
reader.readBlockPosition(blockPosition1 -> blockPosition = blockPosition1);
|
||||
reader.readVarInt(value -> {
|
||||
blockFace = BlockFace.values()[value];
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
|
||||
public enum Status {
|
||||
|
@ -9,9 +9,12 @@ public class ClientPlayerLookPacket extends ClientPlayPacket {
|
||||
public boolean onGround;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.yaw = reader.readFloat();
|
||||
this.pitch = reader.readFloat();
|
||||
this.onGround = reader.readBoolean();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readFloat(value -> yaw = value);
|
||||
reader.readFloat(value -> pitch = value);
|
||||
reader.readBoolean(value -> {
|
||||
onGround = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,10 @@ public class ClientPlayerPacket extends ClientPlayPacket {
|
||||
public boolean onGround;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.onGround = reader.readBoolean();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readBoolean(value -> {
|
||||
onGround = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,12 +10,15 @@ public class ClientPlayerPositionAndLookPacket extends ClientPlayPacket {
|
||||
public boolean onGround;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.x = reader.readDouble();
|
||||
this.y = reader.readDouble();
|
||||
this.z = reader.readDouble();
|
||||
this.yaw = reader.readFloat();
|
||||
this.pitch = reader.readFloat();
|
||||
this.onGround = reader.readBoolean();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readDouble(value -> x = value);
|
||||
reader.readDouble(value -> y = value);
|
||||
reader.readDouble(value -> z = value);
|
||||
reader.readFloat(value -> yaw = value);
|
||||
reader.readFloat(value -> pitch = value);
|
||||
reader.readBoolean(value -> {
|
||||
onGround = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,13 @@ public class ClientPlayerPositionPacket extends ClientPlayPacket {
|
||||
public boolean onGround;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.x = reader.readDouble();
|
||||
this.y = reader.readDouble();
|
||||
this.z = reader.readDouble();
|
||||
this.onGround = reader.readBoolean();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readDouble(value -> x = value);
|
||||
reader.readDouble(value -> y = value);
|
||||
reader.readDouble(value -> z = value);
|
||||
reader.readBoolean(value -> {
|
||||
onGround = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,13 @@ public class ClientPluginMessagePacket extends ClientPlayPacket {
|
||||
private byte[] data;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.identifier = reader.readSizedString();
|
||||
this.data = reader.getRemainingBytes();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readSizedString((s, l) -> {
|
||||
identifier = s;
|
||||
reader.getRemainingBytes(l, bytes -> {
|
||||
data = bytes;
|
||||
callback.run();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -14,12 +14,15 @@ public class ClientSettingsPacket extends ClientPlayPacket {
|
||||
public Player.MainHand mainHand;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.locale = reader.readSizedString();
|
||||
this.viewDistance = reader.readByte();
|
||||
this.chatMode = Player.ChatMode.values()[reader.readVarInt()];
|
||||
this.chatColors = reader.readBoolean();
|
||||
this.displayedSkinParts = reader.readByte();
|
||||
this.mainHand = Player.MainHand.values()[reader.readVarInt()];
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readSizedString(s -> locale = s);
|
||||
reader.readByte(value -> viewDistance = value);
|
||||
reader.readVarInt(value -> chatMode = Player.ChatMode.values()[value]);
|
||||
reader.readBoolean(value -> chatColors = value);
|
||||
reader.readByte(value -> displayedSkinParts = value);
|
||||
reader.readVarInt(value -> {
|
||||
mainHand = Player.MainHand.values()[value];
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,11 @@ public class ClientStatusPacket extends ClientPlayPacket {
|
||||
public Action action;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.action = Action.values()[reader.readVarInt()];
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> {
|
||||
action = Action.values()[value];
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
|
@ -10,9 +10,12 @@ public class ClientSteerVehiclePacket extends ClientPlayPacket {
|
||||
public byte flags;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.sideways = reader.readFloat();
|
||||
this.forward = reader.readFloat();
|
||||
this.flags = reader.readByte();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readFloat(value -> sideways = value);
|
||||
reader.readFloat(value -> forward = value);
|
||||
reader.readByte(value -> {
|
||||
flags = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,10 @@ public class ClientTeleportConfirmPacket extends ClientPlayPacket {
|
||||
public int teleportId;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.teleportId = reader.readVarInt();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> {
|
||||
teleportId = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -14,16 +14,26 @@ public class ClientUseEntityPacket extends ClientPlayPacket {
|
||||
public Player.Hand hand;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.targetId = reader.readVarInt();
|
||||
this.type = Type.values()[reader.readVarInt()];
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> targetId = value);
|
||||
reader.readVarInt(value -> {
|
||||
type = Type.values()[value];
|
||||
if (type == Type.ATTACK)
|
||||
callback.run();
|
||||
});
|
||||
|
||||
if (this.type == Type.INTERACT_AT) {
|
||||
this.x = reader.readFloat();
|
||||
this.y = reader.readFloat();
|
||||
this.z = reader.readFloat();
|
||||
reader.readFloat(value -> x = value);
|
||||
reader.readFloat(value -> y = value);
|
||||
reader.readFloat(value -> {
|
||||
z = value;
|
||||
});
|
||||
}
|
||||
if (type == Type.INTERACT || type == Type.INTERACT_AT)
|
||||
this.hand = Player.Hand.values()[reader.readVarInt()];
|
||||
reader.readVarInt(value -> {
|
||||
hand = Player.Hand.values()[value];
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
|
@ -9,7 +9,10 @@ public class ClientUseItemPacket extends ClientPlayPacket {
|
||||
public Player.Hand hand;
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.hand = Player.Hand.values()[reader.readVarInt()];
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readVarInt(value -> {
|
||||
hand = Player.Hand.values()[value];
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package fr.themode.minestom.net.packet.client.status;
|
||||
|
||||
import fr.themode.minestom.net.ConnectionManager;
|
||||
import fr.themode.minestom.net.packet.PacketReader;
|
||||
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
|
||||
public class LegacyServerListPingPacket implements ClientPreplayPacket {
|
||||
|
||||
private byte payload;
|
||||
|
||||
@Override
|
||||
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readByte(value -> {
|
||||
payload = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
@ -14,11 +14,14 @@ public class PingPacket implements ClientPreplayPacket {
|
||||
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||
PongPacket pongPacket = new PongPacket(number);
|
||||
connection.sendPacket(pongPacket);
|
||||
connection.getConnection().close();
|
||||
connection.getClient().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
this.number = reader.readLong();
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
reader.readLong(value -> {
|
||||
number = value;
|
||||
callback.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ public class StatusRequestPacket implements ClientPreplayPacket {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(PacketReader reader) {
|
||||
public void read(PacketReader reader, Runnable callback) {
|
||||
callback.run();
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class ChunkDataPacket implements ServerPacket {
|
||||
}
|
||||
|
||||
writer.writeVarInt(blocks.length());
|
||||
writer.writeBuffer(blocks);
|
||||
writer.writeBytes(blocks.getAllBytes());
|
||||
|
||||
// Block entities
|
||||
Set<Integer> blockEntities = chunk.getBlockEntities();
|
||||
|
@ -1,18 +1,20 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.PacketWriter;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EntityMetaDataPacket implements ServerPacket {
|
||||
|
||||
public int entityId;
|
||||
public Buffer data;
|
||||
public Consumer<Packet> consumer;
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
writer.writeVarInt(entityId);
|
||||
writer.writeBuffer(data);
|
||||
writer.write(consumer);
|
||||
writer.writeByte((byte) 0xFF);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.PacketWriter;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Position;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class SpawnMobPacket implements ServerPacket {
|
||||
|
||||
@ -15,7 +16,7 @@ public class SpawnMobPacket implements ServerPacket {
|
||||
public Position position;
|
||||
public float headPitch;
|
||||
public short velocityX, velocityY, velocityZ;
|
||||
public Buffer metadata;
|
||||
public Consumer<Packet> consumer;
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
@ -31,8 +32,8 @@ public class SpawnMobPacket implements ServerPacket {
|
||||
writer.writeShort(velocityX);
|
||||
writer.writeShort(velocityY);
|
||||
writer.writeShort(velocityZ);
|
||||
if (metadata != null) {
|
||||
writer.writeBuffer(metadata);
|
||||
if (consumer != null) {
|
||||
writer.write(consumer);
|
||||
} else {
|
||||
writer.writeByte((byte) 0xff);
|
||||
}
|
||||
|
@ -1,18 +1,19 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.PacketWriter;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Position;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class SpawnPlayerPacket implements ServerPacket {
|
||||
|
||||
public int entityId;
|
||||
public UUID playerUuid;
|
||||
public Position position;
|
||||
public Buffer metadata;
|
||||
public Consumer<Packet> metadataConsumer;
|
||||
|
||||
@Override
|
||||
public void write(PacketWriter writer) {
|
||||
@ -24,8 +25,8 @@ public class SpawnPlayerPacket implements ServerPacket {
|
||||
writer.writeByte((byte) (position.getYaw() * 256f / 360f));
|
||||
writer.writeByte((byte) (position.getPitch() * 256f / 360f));
|
||||
|
||||
if (metadata != null) {
|
||||
writer.writeBuffer(metadata);
|
||||
if (metadataConsumer != null) {
|
||||
writer.write(metadataConsumer);
|
||||
} else {
|
||||
writer.writeByte((byte) 0xff);
|
||||
}
|
||||
|
@ -1,63 +1,40 @@
|
||||
package fr.themode.minestom.net.player;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.adamaq01.ozao.net.server.Connection;
|
||||
import fr.themode.minestom.net.ConnectionState;
|
||||
import fr.themode.minestom.net.PacketWriterUtils;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import fr.themode.minestom.utils.PacketUtils;
|
||||
import simplenet.Client;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
public class PlayerConnection {
|
||||
|
||||
private Connection connection;
|
||||
private Client client;
|
||||
private ConnectionState connectionState;
|
||||
|
||||
public PlayerConnection(Connection connection) {
|
||||
this.connection = connection;
|
||||
public PlayerConnection(Client client) {
|
||||
this.client = client;
|
||||
this.connectionState = ConnectionState.UNKNOWN;
|
||||
}
|
||||
|
||||
public void sendPacket(Packet packet) {
|
||||
this.connection.sendPacket(packet);
|
||||
packet.writeAndFlush(client);
|
||||
}
|
||||
|
||||
|
||||
// TODO make that proper (remove reflection)
|
||||
private static Field field;
|
||||
|
||||
static {
|
||||
try {
|
||||
field = Class.forName("fr.adamaq01.ozao.net.server.backend.tcp.TCPConnection").getDeclaredField("channel");
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
field.setAccessible(true);
|
||||
}
|
||||
|
||||
public void sendUnencodedPacket(Buffer packet) {
|
||||
getChannel().writeAndFlush(packet.getData());
|
||||
}
|
||||
|
||||
public void writeUnencodedPacket(Buffer packet) {
|
||||
getChannel().write(packet.getData());
|
||||
public void writeUnencodedPacket(Packet packet) {
|
||||
packet.write(client);
|
||||
}
|
||||
|
||||
public void sendPacket(ServerPacket serverPacket) {
|
||||
PacketWriterUtils.writeAndSend(this, serverPacket);
|
||||
PacketUtils.writePacket(serverPacket, packet -> sendPacket(packet));
|
||||
//PacketWriterUtils.writeAndSend(this, serverPacket);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
getChannel().flush();
|
||||
client.flush();
|
||||
}
|
||||
|
||||
public Connection getConnection() {
|
||||
return connection;
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setConnectionState(ConnectionState connectionState) {
|
||||
@ -67,13 +44,4 @@ public class PlayerConnection {
|
||||
public ConnectionState getConnectionState() {
|
||||
return connectionState;
|
||||
}
|
||||
|
||||
private Channel getChannel() {
|
||||
try {
|
||||
return ((SocketChannel) field.get(connection));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package fr.themode.minestom.net.protocol;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.adamaq01.ozao.net.protocol.Protocol;
|
||||
import fr.themode.minestom.utils.PacketUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import static fr.themode.minestom.utils.Utils.readVarInt;
|
||||
|
||||
public class MinecraftProtocol extends Protocol {
|
||||
|
||||
public static final String PACKET_ID_IDENTIFIER = "id";
|
||||
|
||||
public MinecraftProtocol() {
|
||||
super("minecraft");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(Buffer buffer) {
|
||||
int length = readVarInt(buffer);
|
||||
int realLength = buffer.slice(buffer.readerIndex()).length();
|
||||
int id = readVarInt(buffer);
|
||||
buffer.readerIndex(0);
|
||||
return length == realLength && id >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(Packet packet) {
|
||||
return PacketUtils.verify(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Buffer> cut(Buffer buffer) {
|
||||
ArrayList<Buffer> buffers = new ArrayList<>();
|
||||
int read = 0;
|
||||
while (read < buffer.length()) {
|
||||
int lengthLength = buffer.readerIndex(read).readerIndex();
|
||||
int length = readVarInt(buffer);
|
||||
lengthLength = buffer.readerIndex() - lengthLength;
|
||||
buffers.add(buffer.sliceCopy(read, length + lengthLength));
|
||||
read += length + lengthLength;
|
||||
}
|
||||
return buffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet decode(Buffer buffer) {
|
||||
int length = readVarInt(buffer);
|
||||
int id = readVarInt(buffer);
|
||||
Buffer packetPayload = buffer.sliceCopy(buffer.readerIndex());
|
||||
return Packet.create(packetPayload).put(PACKET_ID_IDENTIFIER, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer encode(Packet packet) {
|
||||
return PacketUtils.encode(packet);
|
||||
}
|
||||
}
|
@ -1,40 +1,24 @@
|
||||
package fr.themode.minestom.utils;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.adamaq01.ozao.net.packet.Packet;
|
||||
import fr.themode.minestom.net.packet.PacketWriter;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import static fr.themode.minestom.net.protocol.MinecraftProtocol.PACKET_ID_IDENTIFIER;
|
||||
import static fr.themode.minestom.utils.Utils.writeVarInt;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PacketUtils {
|
||||
|
||||
public static Packet writePacket(ServerPacket serverPacket) {
|
||||
public static void writePacket(ServerPacket serverPacket, Consumer<Packet> callback) {
|
||||
int id = serverPacket.getId();
|
||||
Packet packet = Packet.create();
|
||||
Buffer buffer = packet.getPayload();
|
||||
|
||||
PacketWriter packetWriter = new PacketWriter(buffer);
|
||||
|
||||
//System.out.println("SEND PACKET: 0x"+Integer.toHexString(id));
|
||||
Packet packet = Packet.builder();
|
||||
Utils.writeVarInt(packet, id);
|
||||
PacketWriter packetWriter = new PacketWriter(packet);
|
||||
serverPacket.write(packetWriter);
|
||||
packet.put(PACKET_ID_IDENTIFIER, id);
|
||||
return packet;
|
||||
}
|
||||
|
||||
public static boolean verify(Packet packet) {
|
||||
return packet.get("id") != null;
|
||||
}
|
||||
|
||||
public static Buffer encode(Packet packet) {
|
||||
Buffer buffer = Buffer.create();
|
||||
Buffer idAndPayload = Buffer.create();
|
||||
|
||||
writeVarInt(idAndPayload, packet.get(PACKET_ID_IDENTIFIER));
|
||||
idAndPayload.putBuffer(packet.getPayload());
|
||||
writeVarInt(buffer, idAndPayload.length());
|
||||
buffer.putBuffer(idAndPayload);
|
||||
return buffer;
|
||||
callback.accept(packet.prepend(p -> {
|
||||
Utils.writeVarInt(packet, packet.getSize());
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,12 +3,17 @@ package fr.themode.minestom.utils;
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.chat.Chat;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.ConnectionUtils;
|
||||
import fr.themode.minestom.utils.consumer.StringConsumer;
|
||||
import simplenet.Client;
|
||||
import simplenet.packet.Packet;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static void writeString(Buffer buffer, String value) {
|
||||
public static void writeString(Packet packet, String value) {
|
||||
byte[] bytes = new byte[0];
|
||||
try {
|
||||
bytes = value.getBytes("UTF-8");
|
||||
@ -18,23 +23,26 @@ public class Utils {
|
||||
if (bytes.length > 32767) {
|
||||
System.out.println("String too big (was " + value.length() + " bytes encoded, max " + 32767 + ")");
|
||||
} else {
|
||||
writeVarInt(buffer, bytes.length);
|
||||
buffer.putBytes(bytes);
|
||||
writeVarInt(packet, bytes.length);
|
||||
packet.putBytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readString(Buffer buffer) {
|
||||
int length = readVarInt(buffer);
|
||||
byte bytes[] = buffer.getBytes(length);
|
||||
try {
|
||||
return new String(bytes, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
public static void readString(Client client, StringConsumer consumer) {
|
||||
ConnectionUtils.readVarInt(client, length -> {
|
||||
int stringLength = Utils.lengthVarInt(length) + length;
|
||||
client.readBytes(length, bytes -> {
|
||||
try {
|
||||
consumer.accept(new String(bytes, "UTF-8"), stringLength);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
consumer.accept(null, stringLength);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static void writeVarInt(Buffer buffer, int value) {
|
||||
public static void writeVarIntBuffer(Buffer buffer, int value) {
|
||||
do {
|
||||
byte temp = (byte) (value & 0b01111111);
|
||||
value >>>= 7;
|
||||
@ -45,12 +53,23 @@ public class Utils {
|
||||
} while (value != 0);
|
||||
}
|
||||
|
||||
public static int readVarInt(Buffer buffer) {
|
||||
public static void writeVarInt(Packet packet, int value) {
|
||||
do {
|
||||
byte temp = (byte) (value & 0b01111111);
|
||||
value >>>= 7;
|
||||
if (value != 0) {
|
||||
temp |= 0b10000000;
|
||||
}
|
||||
packet.putByte(temp);
|
||||
} while (value != 0);
|
||||
}
|
||||
|
||||
public static int readVarInt(Client client) {
|
||||
int numRead = 0;
|
||||
int result = 0;
|
||||
byte read;
|
||||
do {
|
||||
read = buffer.getByte();
|
||||
read = client.readByte();
|
||||
int value = (read & 0b01111111);
|
||||
result |= (value << (7 * numRead));
|
||||
|
||||
@ -90,23 +109,23 @@ public class Utils {
|
||||
return i;
|
||||
}
|
||||
|
||||
public static void writeVarLong(Buffer buffer, long value) {
|
||||
public static void writeVarLong(Packet packet, long value) {
|
||||
do {
|
||||
byte temp = (byte) (value & 0b01111111);
|
||||
value >>>= 7;
|
||||
if (value != 0) {
|
||||
temp |= 0b10000000;
|
||||
}
|
||||
buffer.putByte(temp);
|
||||
packet.putByte(temp);
|
||||
} while (value != 0);
|
||||
}
|
||||
|
||||
public static long readVarLong(Buffer buffer) {
|
||||
public static long readVarLong(Client client) {
|
||||
int numRead = 0;
|
||||
long result = 0;
|
||||
byte read;
|
||||
do {
|
||||
read = buffer.getByte();
|
||||
read = client.readByte();
|
||||
int value = (read & 0b01111111);
|
||||
result |= (value << (7 * numRead));
|
||||
|
||||
@ -119,54 +138,56 @@ public class Utils {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void writePosition(Buffer buffer, int x, int y, int z) {
|
||||
buffer.putLong(SerializerUtils.positionToLong(x, y, z));
|
||||
public static void writePosition(Packet packet, int x, int y, int z) {
|
||||
packet.putLong(SerializerUtils.positionToLong(x, y, z));
|
||||
}
|
||||
|
||||
public static void writePosition(Buffer buffer, BlockPosition blockPosition) {
|
||||
writePosition(buffer, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
public static void writePosition(Packet packet, BlockPosition blockPosition) {
|
||||
writePosition(packet, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||
}
|
||||
|
||||
public static BlockPosition readPosition(Buffer buffer) {
|
||||
return SerializerUtils.longToBlockPosition(buffer.getLong());
|
||||
public static void readPosition(Client client, Consumer<BlockPosition> consumer) {
|
||||
client.readLong(value -> {
|
||||
consumer.accept(SerializerUtils.longToBlockPosition(value));
|
||||
});
|
||||
}
|
||||
|
||||
public static void writeItemStack(Buffer buffer, ItemStack itemStack) {
|
||||
public static void writeItemStack(Packet packet, ItemStack itemStack) {
|
||||
if (itemStack == null) {
|
||||
buffer.putBoolean(false);
|
||||
packet.putBoolean(false);
|
||||
} else {
|
||||
buffer.putBoolean(true);
|
||||
Utils.writeVarInt(buffer, itemStack.getMaterial().getId());
|
||||
buffer.putByte(itemStack.getAmount());
|
||||
packet.putBoolean(true);
|
||||
Utils.writeVarInt(packet, itemStack.getMaterial().getId());
|
||||
packet.putByte(itemStack.getAmount());
|
||||
|
||||
buffer.putByte((byte) 0x0A); // Compound
|
||||
buffer.putShort((short) 0);
|
||||
packet.putByte((byte) 0x0A); // Compound
|
||||
packet.putShort((short) 0);
|
||||
|
||||
// Unbreakable
|
||||
if (itemStack.isUnbreakable()) {
|
||||
buffer.putByte((byte) 0x03); // Integer
|
||||
buffer.putString("Unbreakable");
|
||||
buffer.putInt(1);
|
||||
packet.putByte((byte) 0x03); // Integer
|
||||
packet.putString("Unbreakable");
|
||||
packet.putInt(1);
|
||||
}
|
||||
|
||||
// Display
|
||||
buffer.putByte((byte) 0x0A); // Compound
|
||||
buffer.putString("display");
|
||||
packet.putByte((byte) 0x0A); // Compound
|
||||
packet.putString("display");
|
||||
|
||||
if (itemStack.getDisplayName() != null) {
|
||||
buffer.putByte((byte) 0x08);
|
||||
buffer.putString("Name");
|
||||
buffer.putString(Chat.rawText(itemStack.getDisplayName()));
|
||||
packet.putByte((byte) 0x08);
|
||||
packet.putString("Name");
|
||||
packet.putString(Chat.rawText(itemStack.getDisplayName()));
|
||||
}
|
||||
|
||||
// TODO lore
|
||||
buffer.putByte((byte) 0x08);
|
||||
buffer.putString("Lore");
|
||||
buffer.putString(Chat.rawText("a line"));
|
||||
packet.putByte((byte) 0x08);
|
||||
packet.putString("Lore");
|
||||
packet.putString(Chat.rawText("a line"));
|
||||
|
||||
buffer.putByte((byte) 0); // End display compound
|
||||
packet.putByte((byte) 0); // End display compound
|
||||
|
||||
buffer.putByte((byte) 0); // End nbt
|
||||
packet.putByte((byte) 0); // End nbt
|
||||
}
|
||||
|
||||
}
|
||||
@ -190,7 +211,7 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
long[] data = encodeBlocks(blocksData, 14);
|
||||
writeVarInt(buffer, data.length);
|
||||
writeVarIntBuffer(buffer, data.length);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
buffer.putLong(data[i]);
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package fr.themode.minestom.utils.consumer;
|
||||
|
||||
public interface StringConsumer {
|
||||
|
||||
void accept(String string, int length);
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user