mirror of
https://github.com/GeyserMC/MCProtocolLib.git
synced 2024-11-28 01:55:34 -05:00
Streamline api (#832)
This basically makes MinecraftCodec stateless and removes unused APIs. The MinecraftCodecHelper has a state for an unused registry API, which is not needed at all. Developers can just send their own registry as seen in ServerListener. These only exist because there was an attempt at allowing multi-version support inside MinecraftCodecHelper, but that's not gonna be necessary if ViaVersion support gets added to MCPL. The option to add back logic for multi-version support is fully open for the future. I didn't remove MinecraftCodecHelper being instance-based, so it's fully possible to readd the multi-version logic back in the future. Just level events and sounds being dynamic is not enough for multi-version support and thus should be removed to streamline the API. This also removes many workarounds from the code that cause possible inconsistency. Often the MinecraftCodecHelper gets initialized in the tests with empty parameters. This removes them as parameters and removes the need to provide them by moving them to the object itself. PacketCodecs were also improved to decrease the inheritance issues and streamline the code flow and remove the UnsupportedOperationExceptions being needed. BufferedPacket was also removed since it's useless for Minecraft.
This commit is contained in:
parent
05a699d1ba
commit
41eccedb93
17 changed files with 352 additions and 566 deletions
|
@ -12,6 +12,7 @@ import org.geysermc.mcprotocollib.network.crypt.PacketEncryption;
|
|||
import org.geysermc.mcprotocollib.network.packet.DefaultPacketHeader;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketHeader;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketRegistry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -21,6 +22,7 @@ import java.security.GeneralSecurityException;
|
|||
public class TestProtocol extends PacketProtocol {
|
||||
private static final Logger log = LoggerFactory.getLogger(TestProtocol.class);
|
||||
private final PacketHeader header = new DefaultPacketHeader();
|
||||
private final PacketRegistry registry = new PacketRegistry();
|
||||
private AESEncryption encrypt;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
@ -36,7 +38,7 @@ public class TestProtocol extends PacketProtocol {
|
|||
}
|
||||
|
||||
public void setSecretKey(SecretKey key) {
|
||||
this.register(0, PingPacket.class, new PacketSerializer<>() {
|
||||
registry.register(0, PingPacket.class, new PacketSerializer<>() {
|
||||
@Override
|
||||
public void serialize(ByteBuf buf, PacketCodecHelper helper, PingPacket packet) {
|
||||
helper.writeString(buf, packet.getPingId());
|
||||
|
@ -78,4 +80,9 @@ public class TestProtocol extends PacketProtocol {
|
|||
public void newServerSession(Server server, Session session) {
|
||||
session.addListener(new ServerSessionListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketRegistry getPacketRegistry() {
|
||||
return registry;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
package org.geysermc.mcprotocollib.network.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketDefinition;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketSerializer;
|
||||
|
||||
public class BufferedPacket implements Packet, PacketSerializer<BufferedPacket, PacketCodecHelper> {
|
||||
private final Class<? extends Packet> packetClass;
|
||||
private final byte[] buf;
|
||||
|
||||
public BufferedPacket(Class<? extends Packet> packetClass, byte[] buf) {
|
||||
this.packetClass = packetClass;
|
||||
this.buf = buf;
|
||||
}
|
||||
|
||||
public Class<? extends Packet> getPacketClass() {
|
||||
return packetClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPriority() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(ByteBuf buf, PacketCodecHelper helper, BufferedPacket packet) {
|
||||
buf.writeBytes(this.buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedPacket deserialize(ByteBuf buf, PacketCodecHelper helper, PacketDefinition<BufferedPacket, PacketCodecHelper> definition) {
|
||||
byte[] array = new byte[buf.readableBytes()];
|
||||
buf.readBytes(array);
|
||||
|
||||
return new BufferedPacket(definition.getPacketClass(), array);
|
||||
}
|
||||
}
|
|
@ -1,28 +1,15 @@
|
|||
package org.geysermc.mcprotocollib.network.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.geysermc.mcprotocollib.network.Server;
|
||||
import org.geysermc.mcprotocollib.network.Session;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketDefinition;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketSerializer;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A protocol for packet sending and receiving.
|
||||
* All implementations must have a constructor that takes in a {@link ByteBuf}.
|
||||
*/
|
||||
public abstract class PacketProtocol {
|
||||
private final Int2ObjectMap<PacketDefinition<? extends Packet, ?>> serverbound = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2ObjectMap<PacketDefinition<? extends Packet, ?>> clientbound = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private final Map<Class<? extends Packet>, Integer> clientboundIds = new IdentityHashMap<>();
|
||||
private final Map<Class<? extends Packet>, Integer> serverboundIds = new IdentityHashMap<>();
|
||||
|
||||
/**
|
||||
* Gets the prefix used when locating SRV records for this protocol.
|
||||
*
|
||||
|
@ -62,241 +49,9 @@ public abstract class PacketProtocol {
|
|||
public abstract void newServerSession(Server server, Session session);
|
||||
|
||||
/**
|
||||
* Clears all currently registered packets.
|
||||
*/
|
||||
public final void clearPackets() {
|
||||
this.serverbound.clear();
|
||||
this.clientbound.clear();
|
||||
this.clientboundIds.clear();
|
||||
this.serverboundIds.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a packet to this protocol as both serverbound and clientbound.
|
||||
* Gets the packet registry for this protocol.
|
||||
*
|
||||
* @param id Id to register the packet to.
|
||||
* @param packet Packet to register.
|
||||
* @param serializer The packet serializer.
|
||||
* @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound.
|
||||
* @return The protocol's packet registry.
|
||||
*/
|
||||
public final <T extends Packet, H extends PacketCodecHelper> void register(int id, Class<T> packet, PacketSerializer<T, H> serializer) {
|
||||
this.registerServerbound(id, packet, serializer);
|
||||
this.registerClientbound(id, packet, serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a packet to this protocol as both serverbound and clientbound.
|
||||
*
|
||||
* @param definition The packet definition.
|
||||
* @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound.
|
||||
*/
|
||||
public final void register(PacketDefinition<? extends Packet, ?> definition) {
|
||||
this.registerServerbound(definition);
|
||||
this.registerClientbound(definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a serverbound packet to this protocol.
|
||||
*
|
||||
* @param id Id to register the packet to.
|
||||
* @param packet Packet to register.
|
||||
* @param serializer The packet serializer.
|
||||
* @throws IllegalArgumentException If the packet fails a test creation.
|
||||
*/
|
||||
public final <T extends Packet, H extends PacketCodecHelper> void registerServerbound(int id, Class<T> packet, PacketSerializer<T, H> serializer) {
|
||||
this.registerServerbound(new PacketDefinition<>(id, packet, serializer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a serverbound packet to this protocol.
|
||||
*
|
||||
* @param definition The packet definition.
|
||||
*/
|
||||
public final void registerServerbound(PacketDefinition<? extends Packet, ?> definition) {
|
||||
this.serverbound.put(definition.getId(), definition);
|
||||
this.serverboundIds.put(definition.getPacketClass(), definition.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a clientbound packet to this protocol.
|
||||
*
|
||||
* @param id Id to register the packet to.
|
||||
* @param packet Packet to register.
|
||||
* @param serializer The packet serializer.
|
||||
*/
|
||||
public final <T extends Packet, H extends PacketCodecHelper> void registerClientbound(int id, Class<T> packet, PacketSerializer<T, H> serializer) {
|
||||
this.registerClientbound(new PacketDefinition<>(id, packet, serializer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a clientbound packet to this protocol.
|
||||
*
|
||||
* @param definition The packet definition.
|
||||
*/
|
||||
public final void registerClientbound(PacketDefinition<? extends Packet, ?> definition) {
|
||||
this.clientbound.put(definition.getId(), definition);
|
||||
this.clientboundIds.put(definition.getPacketClass(), definition.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a clientbound packet with the given id and read the clientbound input.
|
||||
*
|
||||
* @param id Id of the packet to create.
|
||||
* @param buf The buffer to read the packet from.
|
||||
* @param codecHelper The codec helper.
|
||||
* @return The created packet.
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <H extends PacketCodecHelper> Packet createClientboundPacket(int id, ByteBuf buf, H codecHelper) {
|
||||
PacketDefinition<?, H> definition = (PacketDefinition<?, H>) this.clientbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.newInstance(buf, codecHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a clientbound packet class.
|
||||
*
|
||||
* @param packetClass Class of the packet to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getClientboundId(Class<? extends Packet> packetClass) {
|
||||
Integer packetId = this.clientboundIds.get(packetClass);
|
||||
if (packetId == null) {
|
||||
throw new IllegalArgumentException("Unregistered clientbound packet class: " + packetClass.getName());
|
||||
}
|
||||
|
||||
return packetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a clientbound {@link Packet} instance.
|
||||
*
|
||||
* @param packet Instance of {@link Packet} to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getClientboundId(Packet packet) {
|
||||
if (packet instanceof BufferedPacket bufferedPacket) {
|
||||
return getClientboundId(bufferedPacket.getPacketClass());
|
||||
}
|
||||
|
||||
return getClientboundId(packet.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet class for a packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
public Class<? extends Packet> getClientboundClass(int id) {
|
||||
PacketDefinition<?, ?> definition = this.clientbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.getPacketClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a serverbound packet with the given id and read the serverbound input.
|
||||
*
|
||||
* @param id Id of the packet to create.
|
||||
* @param buf The buffer to read the packet from.
|
||||
* @param codecHelper The codec helper.
|
||||
* @return The created packet.
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <H extends PacketCodecHelper> Packet createServerboundPacket(int id, ByteBuf buf, H codecHelper) {
|
||||
PacketDefinition<?, H> definition = (PacketDefinition<?, H>) this.serverbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.newInstance(buf, codecHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a serverbound packet class.
|
||||
*
|
||||
* @param packetClass Class of the packet to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getServerboundId(Class<? extends Packet> packetClass) {
|
||||
Integer packetId = this.serverboundIds.get(packetClass);
|
||||
if (packetId == null) {
|
||||
throw new IllegalArgumentException("Unregistered serverbound packet class: " + packetClass.getName());
|
||||
}
|
||||
|
||||
return packetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a serverbound {@link Packet} instance.
|
||||
*
|
||||
* @param packet Instance of {@link Packet} to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getServerboundId(Packet packet) {
|
||||
if (packet instanceof BufferedPacket bufferedPacket) {
|
||||
return getServerboundId(bufferedPacket.getPacketClass());
|
||||
}
|
||||
|
||||
return getServerboundId(packet.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet class for a packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
public Class<? extends Packet> getServerboundClass(int id) {
|
||||
PacketDefinition<?, ?> definition = this.serverbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.getPacketClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the serverbound packet definition for the given packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
*/
|
||||
public PacketDefinition<?, ?> getServerboundDefinition(int id) {
|
||||
PacketDefinition<?, ?> definition = this.serverbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clientbound packet definition for the given packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
*/
|
||||
public PacketDefinition<?, ?> getClientboundDefinition(int id) {
|
||||
PacketDefinition<?, ?> definition = this.clientbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
public abstract PacketRegistry getPacketRegistry();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
package org.geysermc.mcprotocollib.network.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketDefinition;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketSerializer;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A protocol for packet sending and receiving.
|
||||
* All implementations must have a constructor that takes in a {@link ByteBuf}.
|
||||
*/
|
||||
public class PacketRegistry {
|
||||
private final Int2ObjectMap<PacketDefinition<? extends Packet, ?>> serverbound = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2ObjectMap<PacketDefinition<? extends Packet, ?>> clientbound = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private final Map<Class<? extends Packet>, Integer> clientboundIds = new IdentityHashMap<>();
|
||||
private final Map<Class<? extends Packet>, Integer> serverboundIds = new IdentityHashMap<>();
|
||||
|
||||
/**
|
||||
* Clears all currently registered packets.
|
||||
*/
|
||||
public final void clearPackets() {
|
||||
this.serverbound.clear();
|
||||
this.clientbound.clear();
|
||||
this.clientboundIds.clear();
|
||||
this.serverboundIds.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a packet to this protocol as both serverbound and clientbound.
|
||||
*
|
||||
* @param id Id to register the packet to.
|
||||
* @param packet Packet to register.
|
||||
* @param serializer The packet serializer.
|
||||
* @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound.
|
||||
*/
|
||||
public final <T extends Packet, H extends PacketCodecHelper> void register(int id, Class<T> packet, PacketSerializer<T, H> serializer) {
|
||||
this.registerServerbound(id, packet, serializer);
|
||||
this.registerClientbound(id, packet, serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a packet to this protocol as both serverbound and clientbound.
|
||||
*
|
||||
* @param definition The packet definition.
|
||||
* @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound.
|
||||
*/
|
||||
public final void register(PacketDefinition<? extends Packet, ?> definition) {
|
||||
this.registerServerbound(definition);
|
||||
this.registerClientbound(definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a serverbound packet to this protocol.
|
||||
*
|
||||
* @param id Id to register the packet to.
|
||||
* @param packet Packet to register.
|
||||
* @param serializer The packet serializer.
|
||||
* @throws IllegalArgumentException If the packet fails a test creation.
|
||||
*/
|
||||
public final <T extends Packet, H extends PacketCodecHelper> void registerServerbound(int id, Class<T> packet, PacketSerializer<T, H> serializer) {
|
||||
this.registerServerbound(new PacketDefinition<>(id, packet, serializer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a serverbound packet to this protocol.
|
||||
*
|
||||
* @param definition The packet definition.
|
||||
*/
|
||||
public final void registerServerbound(PacketDefinition<? extends Packet, ?> definition) {
|
||||
this.serverbound.put(definition.getId(), definition);
|
||||
this.serverboundIds.put(definition.getPacketClass(), definition.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a clientbound packet to this protocol.
|
||||
*
|
||||
* @param id Id to register the packet to.
|
||||
* @param packet Packet to register.
|
||||
* @param serializer The packet serializer.
|
||||
*/
|
||||
public final <T extends Packet, H extends PacketCodecHelper> void registerClientbound(int id, Class<T> packet, PacketSerializer<T, H> serializer) {
|
||||
this.registerClientbound(new PacketDefinition<>(id, packet, serializer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a clientbound packet to this protocol.
|
||||
*
|
||||
* @param definition The packet definition.
|
||||
*/
|
||||
public final void registerClientbound(PacketDefinition<? extends Packet, ?> definition) {
|
||||
this.clientbound.put(definition.getId(), definition);
|
||||
this.clientboundIds.put(definition.getPacketClass(), definition.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a clientbound packet with the given id and read the clientbound input.
|
||||
*
|
||||
* @param id Id of the packet to create.
|
||||
* @param buf The buffer to read the packet from.
|
||||
* @param codecHelper The codec helper.
|
||||
* @return The created packet.
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <H extends PacketCodecHelper> Packet createClientboundPacket(int id, ByteBuf buf, H codecHelper) {
|
||||
PacketDefinition<?, H> definition = (PacketDefinition<?, H>) this.clientbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.newInstance(buf, codecHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a clientbound packet class.
|
||||
*
|
||||
* @param packetClass Class of the packet to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getClientboundId(Class<? extends Packet> packetClass) {
|
||||
Integer packetId = this.clientboundIds.get(packetClass);
|
||||
if (packetId == null) {
|
||||
throw new IllegalArgumentException("Unregistered clientbound packet class: " + packetClass.getName());
|
||||
}
|
||||
|
||||
return packetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a clientbound {@link Packet} instance.
|
||||
*
|
||||
* @param packet Instance of {@link Packet} to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getClientboundId(Packet packet) {
|
||||
return getClientboundId(packet.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet class for a packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
public Class<? extends Packet> getClientboundClass(int id) {
|
||||
PacketDefinition<?, ?> definition = this.clientbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.getPacketClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a serverbound packet with the given id and read the serverbound input.
|
||||
*
|
||||
* @param id Id of the packet to create.
|
||||
* @param buf The buffer to read the packet from.
|
||||
* @param codecHelper The codec helper.
|
||||
* @return The created packet.
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <H extends PacketCodecHelper> Packet createServerboundPacket(int id, ByteBuf buf, H codecHelper) {
|
||||
PacketDefinition<?, H> definition = (PacketDefinition<?, H>) this.serverbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.newInstance(buf, codecHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a serverbound packet class.
|
||||
*
|
||||
* @param packetClass Class of the packet to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getServerboundId(Class<? extends Packet> packetClass) {
|
||||
Integer packetId = this.serverboundIds.get(packetClass);
|
||||
if (packetId == null) {
|
||||
throw new IllegalArgumentException("Unregistered serverbound packet class: " + packetClass.getName());
|
||||
}
|
||||
|
||||
return packetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered id of a serverbound {@link Packet} instance.
|
||||
*
|
||||
* @param packet Instance of {@link Packet} to get the id for.
|
||||
* @return The packet's registered id.
|
||||
* @throws IllegalArgumentException If the packet is not registered.
|
||||
*/
|
||||
public int getServerboundId(Packet packet) {
|
||||
return getServerboundId(packet.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet class for a packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
* @throws IllegalArgumentException If the packet ID is not registered.
|
||||
*/
|
||||
public Class<? extends Packet> getServerboundClass(int id) {
|
||||
PacketDefinition<?, ?> definition = this.serverbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition.getPacketClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the serverbound packet definition for the given packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
*/
|
||||
public PacketDefinition<?, ?> getServerboundDefinition(int id) {
|
||||
PacketDefinition<?, ?> definition = this.serverbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clientbound packet definition for the given packet id.
|
||||
*
|
||||
* @param id The packet id.
|
||||
* @return The registered packet's class
|
||||
*/
|
||||
public PacketDefinition<?, ?> getClientboundDefinition(int id) {
|
||||
PacketDefinition<?, ?> definition = this.clientbound.get(id);
|
||||
if (definition == null) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
}
|
|
@ -29,8 +29,8 @@ public class TcpPacketCodec extends ByteToMessageCodec<Packet> {
|
|||
PacketProtocol packetProtocol = this.session.getPacketProtocol();
|
||||
PacketCodecHelper codecHelper = this.session.getCodecHelper();
|
||||
try {
|
||||
int packetId = this.client ? packetProtocol.getServerboundId(packet) : packetProtocol.getClientboundId(packet);
|
||||
PacketDefinition definition = this.client ? packetProtocol.getServerboundDefinition(packetId) : packetProtocol.getClientboundDefinition(packetId);
|
||||
int packetId = this.client ? packetProtocol.getPacketRegistry().getServerboundId(packet) : packetProtocol.getPacketRegistry().getClientboundId(packet);
|
||||
PacketDefinition definition = this.client ? packetProtocol.getPacketRegistry().getServerboundDefinition(packetId) : packetProtocol.getPacketRegistry().getClientboundDefinition(packetId);
|
||||
|
||||
packetProtocol.getPacketHeader().writePacketId(buf, codecHelper, packetId);
|
||||
definition.getSerializer().serialize(buf, codecHelper, packet);
|
||||
|
@ -59,7 +59,7 @@ public class TcpPacketCodec extends ByteToMessageCodec<Packet> {
|
|||
return;
|
||||
}
|
||||
|
||||
Packet packet = this.client ? packetProtocol.createClientboundPacket(id, buf, codecHelper) : packetProtocol.createServerboundPacket(id, buf, codecHelper);
|
||||
Packet packet = this.client ? packetProtocol.getPacketRegistry().createClientboundPacket(id, buf, codecHelper) : packetProtocol.getPacketRegistry().createServerboundPacket(id, buf, codecHelper);
|
||||
|
||||
if (buf.readableBytes() > 0) {
|
||||
throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read.");
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.geysermc.mcprotocollib.protocol;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
|
@ -10,17 +9,14 @@ import org.cloudburstmc.nbt.NbtUtils;
|
|||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.network.Server;
|
||||
import org.geysermc.mcprotocollib.network.Session;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketDefinition;
|
||||
import org.geysermc.mcprotocollib.network.crypt.AESEncryption;
|
||||
import org.geysermc.mcprotocollib.network.crypt.PacketEncryption;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketHeader;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketRegistry;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.PacketCodec;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.PacketStateCodec;
|
||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
@ -49,7 +45,7 @@ public class MinecraftProtocol extends PacketProtocol {
|
|||
private final PacketCodec codec;
|
||||
|
||||
private ProtocolState state;
|
||||
private PacketStateCodec stateCodec;
|
||||
private PacketRegistry stateRegistry;
|
||||
|
||||
private final ProtocolState targetState;
|
||||
|
||||
|
@ -176,6 +172,11 @@ public class MinecraftProtocol extends PacketProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketRegistry getPacketRegistry() {
|
||||
return this.stateRegistry;
|
||||
}
|
||||
|
||||
protected PacketEncryption enableEncryption(Key key) {
|
||||
try {
|
||||
return new AESEncryption(key);
|
||||
|
@ -195,57 +196,7 @@ public class MinecraftProtocol extends PacketProtocol {
|
|||
|
||||
public void setState(ProtocolState state) {
|
||||
this.state = state;
|
||||
this.stateCodec = this.codec.getCodec(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet createClientboundPacket(int id, ByteBuf buf, PacketCodecHelper codecHelper) {
|
||||
return this.stateCodec.createClientboundPacket(id, buf, codecHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClientboundId(Class<? extends Packet> packetClass) {
|
||||
return this.stateCodec.getClientboundId(packetClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClientboundId(Packet packet) {
|
||||
return this.stateCodec.getClientboundId(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Packet> getClientboundClass(int id) {
|
||||
return this.stateCodec.getClientboundClass(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet createServerboundPacket(int id, ByteBuf buf, PacketCodecHelper codecHelper) {
|
||||
return this.stateCodec.createServerboundPacket(id, buf, codecHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerboundId(Class<? extends Packet> packetClass) {
|
||||
return this.stateCodec.getServerboundId(packetClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerboundId(Packet packet) {
|
||||
return this.stateCodec.getServerboundId(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Packet> getServerboundClass(int id) {
|
||||
return this.stateCodec.getServerboundClass(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketDefinition<?, ?> getServerboundDefinition(int id) {
|
||||
return this.stateCodec.getServerboundDefinition(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketDefinition<?, ?> getClientboundDefinition(int id) {
|
||||
return this.stateCodec.getClientboundDefinition(id);
|
||||
this.stateRegistry = this.codec.getCodec(state);
|
||||
}
|
||||
|
||||
public static NbtMap loadNetworkCodec() {
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package org.geysermc.mcprotocollib.protocol.codec;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCookieRequestPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCustomReportDetailsPacket;
|
||||
|
@ -207,31 +203,15 @@ import org.geysermc.mcprotocollib.protocol.packet.status.clientbound.Clientbound
|
|||
import org.geysermc.mcprotocollib.protocol.packet.status.serverbound.ServerboundPingRequestPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.status.serverbound.ServerboundStatusRequestPacket;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MinecraftCodec {
|
||||
private static final Int2ObjectMap<LevelEventType> LEVEL_EVENTS = new Int2ObjectOpenHashMap<>();
|
||||
private static final Map<String, BuiltinSound> SOUND_NAMES = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (LevelEventType levelEvent : LevelEventType.values()) {
|
||||
LEVEL_EVENTS.put(levelEvent.getId(), levelEvent);
|
||||
}
|
||||
|
||||
for (BuiltinSound sound : BuiltinSound.values()) {
|
||||
SOUND_NAMES.put(sound.getName(), sound);
|
||||
}
|
||||
}
|
||||
|
||||
public static final PacketCodec CODEC = PacketCodec.builder()
|
||||
.protocolVersion(767)
|
||||
.helper(() -> new MinecraftCodecHelper(LEVEL_EVENTS, SOUND_NAMES))
|
||||
.helper(MinecraftCodecHelper::new)
|
||||
.minecraftVersion("1.21")
|
||||
.state(ProtocolState.HANDSHAKE, PacketStateCodec.builder()
|
||||
.state(ProtocolState.HANDSHAKE, MinecraftPacketRegistry.builder()
|
||||
.registerServerboundPacket(ClientIntentionPacket.class, ClientIntentionPacket::new)
|
||||
)
|
||||
.state(ProtocolState.LOGIN, PacketStateCodec.builder()
|
||||
.state(ProtocolState.LOGIN, MinecraftPacketRegistry.builder()
|
||||
.registerClientboundPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new)
|
||||
.registerClientboundPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new)
|
||||
.registerClientboundPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new)
|
||||
|
@ -243,12 +223,12 @@ public class MinecraftCodec {
|
|||
.registerServerboundPacket(ServerboundCustomQueryAnswerPacket.class, ServerboundCustomQueryAnswerPacket::new)
|
||||
.registerServerboundPacket(ServerboundLoginAcknowledgedPacket.class, ServerboundLoginAcknowledgedPacket::new)
|
||||
.registerServerboundPacket(ServerboundCookieResponsePacket.class, ServerboundCookieResponsePacket::new)
|
||||
).state(ProtocolState.STATUS, PacketStateCodec.builder()
|
||||
).state(ProtocolState.STATUS, MinecraftPacketRegistry.builder()
|
||||
.registerClientboundPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new)
|
||||
.registerClientboundPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new)
|
||||
.registerServerboundPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new)
|
||||
.registerServerboundPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)
|
||||
).state(ProtocolState.CONFIGURATION, PacketStateCodec.builder()
|
||||
).state(ProtocolState.CONFIGURATION, MinecraftPacketRegistry.builder()
|
||||
.registerClientboundPacket(ClientboundCookieRequestPacket.class, ClientboundCookieRequestPacket::new)
|
||||
.registerClientboundPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new)
|
||||
.registerClientboundPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new)
|
||||
|
@ -274,7 +254,7 @@ public class MinecraftCodec {
|
|||
.registerServerboundPacket(ServerboundPongPacket.class, ServerboundPongPacket::new)
|
||||
.registerServerboundPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new)
|
||||
.registerServerboundPacket(ServerboundSelectKnownPacks.class, ServerboundSelectKnownPacks::new)
|
||||
).state(ProtocolState.GAME, PacketStateCodec.builder()
|
||||
).state(ProtocolState.GAME, MinecraftPacketRegistry.builder()
|
||||
.registerClientboundPacket(ClientboundDelimiterPacket.class, ClientboundDelimiterPacket::new)
|
||||
.registerClientboundPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new)
|
||||
.registerClientboundPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new)
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.google.gson.JsonElement;
|
|||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
@ -30,7 +29,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.StyledFormat;
|
|||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.BitStorage;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.ChunkSection;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.NibbleArray3d;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.GlobalPalette;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.ListPalette;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.MapPalette;
|
||||
|
@ -53,7 +51,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
|||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.BlockBreakStage;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.PaintingType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
|
@ -79,13 +76,11 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.particle.positionsour
|
|||
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.positionsource.EntityPositionSource;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.positionsource.PositionSource;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.positionsource.PositionSourceType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.SoundCategory;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.statistic.StatisticCategory;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -96,7 +91,6 @@ import java.util.EnumSet;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -112,11 +106,6 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
|
|||
private static final int POSITION_Y_SHIFT = 0xFFF;
|
||||
private static final int POSITION_WRITE_SHIFT = 0x3FFFFFF;
|
||||
|
||||
private final Int2ObjectMap<LevelEventType> levelEvents;
|
||||
private final Map<String, BuiltinSound> soundNames;
|
||||
|
||||
protected NbtMap registry;
|
||||
|
||||
@Nullable
|
||||
public <T> T readNullable(ByteBuf buf, Function<ByteBuf, T> ifPresent) {
|
||||
if (buf.readBoolean()) {
|
||||
|
@ -916,7 +905,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
|
|||
|
||||
public LevelEvent readLevelEvent(ByteBuf buf) {
|
||||
int id = buf.readInt();
|
||||
LevelEventType type = this.levelEvents.get(id);
|
||||
LevelEventType type = LevelEventType.from(id);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
|
@ -943,11 +932,6 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
|
|||
this.writeEnum(buf, category);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BuiltinSound getBuiltinSound(String name) {
|
||||
return this.soundNames.get(name);
|
||||
}
|
||||
|
||||
public EntityEvent readEntityEvent(ByteBuf buf) {
|
||||
return EntityEvent.from(buf.readByte());
|
||||
}
|
||||
|
@ -1127,27 +1111,4 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
|
|||
buf.writeFloat(soundEvent.getRange());
|
||||
}
|
||||
}
|
||||
|
||||
public NibbleArray3d readNibbleArray(ByteBuf buf, int size) {
|
||||
return new NibbleArray3d(this.readByteArray(buf, ignored -> size));
|
||||
}
|
||||
|
||||
public void writeNibbleArray(ByteBuf buf, NibbleArray3d nibbleArray) {
|
||||
buf.writeBytes(nibbleArray.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* The game registry sent to clients from the {@link ClientboundLoginPacket}.
|
||||
* Implementations are required to set this value if they intend to use it.
|
||||
*
|
||||
* @return the game registry
|
||||
*/
|
||||
@Nullable
|
||||
public NbtMap getRegistry() {
|
||||
return this.registry;
|
||||
}
|
||||
|
||||
public void setRegistry(NbtMap registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package org.geysermc.mcprotocollib.protocol.codec;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketDefinition;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketRegistry;
|
||||
|
||||
public class MinecraftPacketRegistry {
|
||||
private final Int2ObjectMap<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> clientboundPackets = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2ObjectMap<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> serverboundPackets = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private int nextClientboundId = 0x00;
|
||||
private int nextServerboundId = 0x00;
|
||||
|
||||
public static MinecraftPacketRegistry builder() {
|
||||
return new MinecraftPacketRegistry();
|
||||
}
|
||||
|
||||
public <T extends MinecraftPacket> MinecraftPacketRegistry registerClientboundPacket(Class<T> packetClass, PacketFactory<T, MinecraftCodecHelper> factory) {
|
||||
this.clientboundPackets.put(nextClientboundId, new PacketDefinition<>(nextClientboundId, packetClass, new MinecraftPacketSerializer<>(factory)));
|
||||
this.nextClientboundId++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T extends MinecraftPacket> MinecraftPacketRegistry registerServerboundPacket(Class<T> packetClass, PacketFactory<T, MinecraftCodecHelper> factory) {
|
||||
this.serverboundPackets.put(nextServerboundId, new PacketDefinition<>(nextServerboundId, packetClass, new MinecraftPacketSerializer<>(factory)));
|
||||
this.nextServerboundId++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PacketRegistry build() {
|
||||
PacketRegistry codec = new PacketRegistry();
|
||||
for (Int2ObjectMap.Entry<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> entry : this.clientboundPackets.int2ObjectEntrySet()) {
|
||||
codec.registerClientbound(entry.getValue());
|
||||
}
|
||||
|
||||
for (Int2ObjectMap.Entry<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> entry : this.serverboundPackets.int2ObjectEntrySet()) {
|
||||
codec.registerServerbound(entry.getValue());
|
||||
}
|
||||
|
||||
return codec;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package org.geysermc.mcprotocollib.protocol.codec;
|
|||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketRegistry;
|
||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
@ -17,12 +18,12 @@ public class PacketCodec {
|
|||
@Getter
|
||||
private final String minecraftVersion;
|
||||
|
||||
private final EnumMap<ProtocolState, PacketStateCodec> stateProtocols;
|
||||
private final EnumMap<ProtocolState, PacketRegistry> stateProtocols;
|
||||
|
||||
@Getter
|
||||
private final Supplier<MinecraftCodecHelper> helperFactory;
|
||||
|
||||
public PacketStateCodec getCodec(ProtocolState protocolState) {
|
||||
public PacketRegistry getCodec(ProtocolState protocolState) {
|
||||
return this.stateProtocols.get(protocolState);
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,7 @@ public class PacketCodec {
|
|||
public static class Builder {
|
||||
private int protocolVersion = -1;
|
||||
private String minecraftVersion = null;
|
||||
private EnumMap<ProtocolState, PacketStateCodec> stateProtocols = new EnumMap<>(ProtocolState.class);
|
||||
private EnumMap<ProtocolState, PacketRegistry> stateProtocols = new EnumMap<>(ProtocolState.class);
|
||||
private Supplier<MinecraftCodecHelper> helperFactory;
|
||||
|
||||
public Builder protocolVersion(int protocolVersion) {
|
||||
|
@ -57,7 +58,7 @@ public class PacketCodec {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder state(ProtocolState state, PacketStateCodec.Builder protocol) {
|
||||
public Builder state(ProtocolState state, MinecraftPacketRegistry protocol) {
|
||||
this.stateProtocols.put(state, protocol.build());
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
package org.geysermc.mcprotocollib.protocol.codec;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.geysermc.mcprotocollib.network.Server;
|
||||
import org.geysermc.mcprotocollib.network.Session;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketDefinition;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketHeader;
|
||||
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
||||
|
||||
public class PacketStateCodec extends PacketProtocol {
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSRVRecordPrefix() {
|
||||
return MinecraftConstants.SRV_RECORD_PREFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketHeader getPacketHeader() {
|
||||
return MinecraftConstants.PACKET_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketCodecHelper createHelper() {
|
||||
throw new UnsupportedOperationException("Not supported!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newClientSession(Session session, boolean transferring) {
|
||||
throw new UnsupportedOperationException("Not supported!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newServerSession(Server server, Session session) {
|
||||
throw new UnsupportedOperationException("Not supported!");
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final Int2ObjectMap<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> clientboundPackets = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2ObjectMap<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> serverboundPackets = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private int nextClientboundId = 0x00;
|
||||
private int nextServerboundId = 0x00;
|
||||
|
||||
public <T extends MinecraftPacket> Builder registerClientboundPacket(int id, Class<T> packetClass, PacketFactory<T, MinecraftCodecHelper> factory) {
|
||||
this.nextClientboundId = id;
|
||||
return registerClientboundPacket(packetClass, factory);
|
||||
}
|
||||
|
||||
public <T extends MinecraftPacket> Builder registerClientboundPacket(Class<T> packetClass, PacketFactory<T, MinecraftCodecHelper> factory) {
|
||||
this.clientboundPackets.put(nextClientboundId, new PacketDefinition<>(nextClientboundId, packetClass, new MinecraftPacketSerializer<>(factory)));
|
||||
this.nextClientboundId++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T extends MinecraftPacket> Builder registerServerboundPacket(int id, Class<T> packetClass, PacketFactory<T, MinecraftCodecHelper> factory) {
|
||||
this.nextServerboundId = id;
|
||||
return registerServerboundPacket(packetClass, factory);
|
||||
}
|
||||
|
||||
public <T extends MinecraftPacket> Builder registerServerboundPacket(Class<T> packetClass, PacketFactory<T, MinecraftCodecHelper> factory) {
|
||||
this.serverboundPackets.put(nextServerboundId, new PacketDefinition<>(nextServerboundId, packetClass, new MinecraftPacketSerializer<>(factory)));
|
||||
this.nextServerboundId++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PacketStateCodec build() {
|
||||
PacketStateCodec codec = new PacketStateCodec();
|
||||
for (Int2ObjectMap.Entry<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> entry : this.clientboundPackets.int2ObjectEntrySet()) {
|
||||
codec.registerClientbound(entry.getValue());
|
||||
}
|
||||
|
||||
for (Int2ObjectMap.Entry<PacketDefinition<? extends MinecraftPacket, MinecraftCodecHelper>> entry : this.serverboundPackets.int2ObjectEntrySet()) {
|
||||
codec.registerServerbound(entry.getValue());
|
||||
}
|
||||
|
||||
return codec;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package org.geysermc.mcprotocollib.protocol.data.game.chunk;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class NibbleArray3d {
|
||||
private final byte @NonNull [] data;
|
||||
|
||||
public NibbleArray3d(int size) {
|
||||
this(new byte[size >> 1]);
|
||||
}
|
||||
|
||||
public int get(int x, int y, int z) {
|
||||
int key = y << 8 | z << 4 | x;
|
||||
int index = key >> 1;
|
||||
int part = key & 1;
|
||||
return part == 0 ? this.data[index] & 15 : this.data[index] >> 4 & 15;
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z, int val) {
|
||||
int key = y << 8 | z << 4 | x;
|
||||
int index = key >> 1;
|
||||
int part = key & 1;
|
||||
if (part == 0) {
|
||||
this.data[index] = (byte) (this.data[index] & 240 | val & 15);
|
||||
} else {
|
||||
this.data[index] = (byte) (this.data[index] & 15 | (val & 15) << 4);
|
||||
}
|
||||
}
|
||||
|
||||
public void fill(int val) {
|
||||
for (int index = 0; index < this.data.length << 1; index++) {
|
||||
int ind = index >> 1;
|
||||
int part = index & 1;
|
||||
if (part == 0) {
|
||||
this.data[ind] = (byte) (this.data[ind] & 240 | val & 15);
|
||||
} else {
|
||||
this.data[ind] = (byte) (this.data[ind] & 15 | (val & 15) << 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.item.component;
|
|||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
@ -19,7 +18,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound;
|
|||
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -29,11 +27,7 @@ import java.util.function.Function;
|
|||
|
||||
|
||||
public class ItemCodecHelper extends MinecraftCodecHelper {
|
||||
public static ItemCodecHelper INSTANCE = new ItemCodecHelper();
|
||||
|
||||
public ItemCodecHelper() {
|
||||
super(Int2ObjectMaps.emptyMap(), Collections.emptyMap());
|
||||
}
|
||||
public static final ItemCodecHelper INSTANCE = new ItemCodecHelper();
|
||||
|
||||
public <T> Filterable<T> readFilterable(ByteBuf buf, Function<ByteBuf, T> reader) {
|
||||
T raw = reader.apply(buf);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.geysermc.mcprotocollib.protocol.data.game.level.event;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
|
@ -90,8 +92,22 @@ public enum LevelEventType implements LevelEvent {
|
|||
PARTICLES_TRIAL_SPAWNER_BECOME_OMINOUS(3020),
|
||||
PARTICLES_TRIAL_SPAWNER_SPAWN_ITEM(3021);
|
||||
|
||||
private static final Int2ObjectMap<LevelEventType> VALUES;
|
||||
|
||||
static {
|
||||
LevelEventType[] values = values();
|
||||
VALUES = new Int2ObjectOpenHashMap<>(values.length);
|
||||
for (LevelEventType value : values) {
|
||||
VALUES.put(value.getId(), value);
|
||||
}
|
||||
}
|
||||
|
||||
private final int id;
|
||||
|
||||
public static LevelEventType from(int id) {
|
||||
return VALUES.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.geysermc.mcprotocollib.protocol.data;
|
|||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.ChunkSection;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette;
|
||||
|
@ -14,7 +13,6 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -41,7 +39,7 @@ public class ChunkTest {
|
|||
|
||||
@Test
|
||||
public void testChunkSectionEncoding() {
|
||||
MinecraftCodecHelper helper = new MinecraftCodecHelper(Int2ObjectMaps.emptyMap(), Collections.emptyMap());
|
||||
MinecraftCodecHelper helper = new MinecraftCodecHelper();
|
||||
for (ChunkSection section : chunkSectionsToTest) {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
helper.writeChunkSection(buf, section);
|
||||
|
|
|
@ -2,13 +2,10 @@ package org.geysermc.mcprotocollib.protocol.data;
|
|||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
|
@ -18,7 +15,7 @@ public class NetworkDataTests {
|
|||
|
||||
@Test
|
||||
public void testEffects() {
|
||||
MinecraftCodecHelper helper = new MinecraftCodecHelper(Int2ObjectMaps.emptyMap(), Collections.emptyMap());
|
||||
MinecraftCodecHelper helper = new MinecraftCodecHelper();
|
||||
for (Effect effect : Effect.VALUES) {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
helper.writeEffect(buf, effect);
|
||||
|
|
|
@ -2,14 +2,12 @@ package org.geysermc.mcprotocollib.protocol.packet;
|
|||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
@ -21,8 +19,8 @@ public abstract class PacketTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPackets() throws Exception {
|
||||
MinecraftCodecHelper helper = new MinecraftCodecHelper(Int2ObjectMaps.emptyMap(), Collections.emptyMap());
|
||||
public void testPackets() {
|
||||
MinecraftCodecHelper helper = new MinecraftCodecHelper();
|
||||
for (MinecraftPacket packet : this.packets) {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
packet.serialize(buf, helper);
|
||||
|
|
Loading…
Reference in a new issue