Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package io.github.jamalam360.jamlib.client.impl;

import static io.github.jamalam360.jamlib.JamLib.JAR_RENAMING_CHECKER;

import io.github.jamalam360.jamlib.api.network.Network;
import io.github.jamalam360.jamlib.client.api.events.ClientMouseScrollEvents;
import io.github.jamalam360.jamlib.api.network.PacketDirection;
import io.github.jamalam360.jamlib.client.api.events.ClientConnectionEvents;
import io.github.jamalam360.jamlib.client.api.events.ClientMouseScrollEvents;
import io.github.jamalam360.jamlib.client.impl.network.ClientNetworkCapabilitiesImpl;
import io.github.jamalam360.jamlib.impl.network.CapabilitiesPacket;
import net.minecraft.ChatFormatting;
Expand All @@ -13,6 +12,8 @@
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.ApiStatus;

import static io.github.jamalam360.jamlib.JamLib.JAR_RENAMING_CHECKER;

public class JamLibClient {
@ApiStatus.Internal
public static void init() {
Expand All @@ -21,7 +22,7 @@ public static void init() {
ClientMouseScrollEvents.IN_SCREENS.listen((m, a) -> ClientMouseScrollEvents.ALWAYS.invokeCancellable(l -> l.onScroll(m, a)));
ClientMouseScrollEvents.OUT_OF_SCREENS.listen((m, a) -> ClientMouseScrollEvents.ALWAYS.invokeCancellable(l -> l.onScroll(m, a)));

Network.registerHandler(Network.Direction.CLIENT_BOUND, CapabilitiesPacket.TYPE, ClientNetworkCapabilitiesImpl::handleServerCapabilities);
Network.registerHandler(PacketDirection.CLIENTBOUND, CapabilitiesPacket.KIND, ClientNetworkCapabilitiesImpl::handleServerCapabilities);
}

private static void onPlayerJoin(Minecraft minecraft) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@
import io.github.jamalam360.jamlib.JamLib;
import io.github.jamalam360.jamlib.api.network.Network;
import io.github.jamalam360.jamlib.api.network.NetworkContext;
import io.github.jamalam360.jamlib.api.network.PacketDirection;
import io.github.jamalam360.jamlib.client.api.network.ClientNetworkEvents;
import io.github.jamalam360.jamlib.impl.network.CapabilitiesPacket;
import io.github.jamalam360.jamlib.impl.network.NetworkCapabilitiesImpl;
import io.github.jamalam360.jamlib.impl.network.NetworkCapabilityImpl;
import io.github.jamalam360.jamlib.impl.network.NetworkImpl;
import net.minecraft.resources.Identifier;

import java.util.List;

public class ClientNetworkCapabilitiesImpl {
public static void handleServerCapabilities(NetworkContext ctx, CapabilitiesPacket.Payload payload) {
public static void handleServerCapabilities(NetworkContext ctx, CapabilitiesPacket payload) {
NetworkCapabilityImpl capability = NetworkCapabilitiesImpl.getOrCreateServerCapability();
payload.capabilities().forEach(capability::addSupportedPayloadType);
List<Identifier> clientCapabilities = Network.getRegisteredHandlerTypes(Network.Direction.CLIENT_BOUND);
Network.sendToServer(CapabilitiesPacket.TYPE, new CapabilitiesPacket.Payload(clientCapabilities));
List<Identifier> clientCapabilities = NetworkImpl.getRegisteredHandlerTypes(PacketDirection.CLIENTBOUND);
Network.sendToServer(new CapabilitiesPacket(clientCapabilities));
JamLib.LOGGER.info("Received {} network {} from server (responded with {})", payload.capabilities().size(), payload.capabilities().size() > 1 ? "capabilities" : "capability", clientCapabilities.size());
ClientNetworkEvents.SERVER_CAPABILITIES_HANDSHAKE_COMPLETED.invoke(ClientNetworkEvents.ServerCapabilitiesHandshakeCompleted::onServerCapabilitiesHandshakeCompleted);
}
Expand Down
4 changes: 2 additions & 2 deletions common/src/main/java/io/github/jamalam360/jamlib/JamLib.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.github.jamalam360.jamlib.api.events.ServerConnectionEvents;
import io.github.jamalam360.jamlib.api.network.Network;
import io.github.jamalam360.jamlib.api.network.PacketDirection;
import io.github.jamalam360.jamlib.api.platform.Platform;
import io.github.jamalam360.jamlib.impl.JarRenamingChecker;
import io.github.jamalam360.jamlib.impl.network.CapabilitiesPacket;
Expand All @@ -25,8 +26,7 @@ public static void init() {
checkForJarRenaming(JamLib.class);

ServerConnectionEvents.CONNECT.listen(NetworkCapabilitiesImpl::onPlayerJoin);
Network.registerPayloadType(CapabilitiesPacket.TYPE, CapabilitiesPacket.INSTANCE);
Network.registerHandler(Network.Direction.SERVER_BOUND, CapabilitiesPacket.TYPE, NetworkCapabilitiesImpl::handleCapabilities);
Network.registerHandler(PacketDirection.SERVERBOUND, CapabilitiesPacket.KIND, NetworkCapabilitiesImpl::handleCapabilities);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,37 @@
package io.github.jamalam360.jamlib.api.network;

import io.github.jamalam360.jamlib.JamLib;
import io.github.jamalam360.jamlib.impl.network.JamLibPacket;
import io.github.jamalam360.jamlib.impl.network.NetworkCapabilitiesImpl;
import io.github.jamalam360.jamlib.impl.network.PlatformNetwork;
import net.minecraft.resources.Identifier;
import io.github.jamalam360.jamlib.impl.network.NetworkImpl;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.ApiStatus;

import java.util.*;

/**
* A platform-agnostic packet sending system.
* Networking system.
*/
public class Network {
private static final Map<PayloadType<?>, NetworkPayloadType<?>> types = new HashMap<>();
private static final Map<PayloadType<?>, NetworkPayloadHandler<?>> clientBoundHandlers = new HashMap<>();
private static final Map<PayloadType<?>, NetworkPayloadHandler<?>> serverBoundHandlers = new HashMap<>();

/**
* Registers a handler for a payload type.
* Registers a handler for a packet kind.
* @param direction The direction the handler should be registered for.
* @param id The ID of the payload the handler handles.
* @param kind The kind of packet that the handler handles.
* @param handler The handler.
*/
public static <T> void registerHandler(Direction direction, PayloadType<T> id, NetworkPayloadHandler<T> handler) {
Map<PayloadType<?>, NetworkPayloadHandler<?>> handlers = switch (direction) {
case CLIENT_BOUND -> clientBoundHandlers;
case SERVER_BOUND -> serverBoundHandlers;
};

if (handlers.containsKey(id)) {
throw new IllegalArgumentException("A handler for the payload type with the id " + id + " is already registered");
}

handlers.put(id, handler);
public static <T> void registerHandler(PacketDirection direction, PacketKind<T> kind, NetworkPayloadHandler<T> handler) {
NetworkImpl.registerHandler(direction, kind, handler);
}

/**
* @param id The ID of the payload type.
* @param type The type of the payload.
/**
* Sends a packet to the server.
* @param payload The payload.
*/
public static <T> void registerPayloadType(PayloadType<T> id, NetworkPayloadType<T> type) {
if (types.containsKey(id)) {
throw new IllegalArgumentException("A payload type with the id " + id + " is already registered");
}
public static <T> void sendToServer(PacketPayload<T> payload) {
NetworkImpl.sendToServer(payload);
}

types.put(id, type);
JamLib.LOGGER.info("Registered network payload type {}", id.id());
/**
* Sends a payload to the client.
* @param payload The payload.
*/
public static <T> void sendToClient(ServerPlayer player, PacketPayload<T> payload) {
NetworkImpl.sendToClient(player, payload);
}

/**
Expand All @@ -68,65 +52,4 @@ public static NetworkCapability getServerCapability() {
public static NetworkCapability getPlayerCapability(ServerPlayer player) {
return NetworkCapabilitiesImpl.getPlayerCapability(player);
}

/**
* Sends a payload to the server.
* @param id The ID of the payload type.
* @param payload The payload.
*/
@SuppressWarnings("unchecked")
public static <T> void sendToServer(PayloadType<T> id, T payload) {
if (!types.containsKey(id)) {
throw new IllegalArgumentException("No payload type with the id " + id + " is registered");
}

NetworkPayloadType<T> type = (NetworkPayloadType<T>) types.get(id);
PlatformNetwork.sendToServer(id, type.getSerializer(), payload);
}

/**
* Sends a payload to the client.
* @param id The ID of the payload type.
* @param payload The payload.
*/
@SuppressWarnings("unchecked")
public static <T> void sendToClient(ServerPlayer player, PayloadType<T> id, T payload) {
if (!types.containsKey(id)) {
throw new IllegalArgumentException("No payload type with the id " + id + " is registered");
}

NetworkPayloadType<T> type = (NetworkPayloadType<T>) types.get(id);
PlatformNetwork.sendToClient(player, id, type.getSerializer(), payload);
}

@SuppressWarnings("unchecked")
@ApiStatus.Internal
public static <T> void receive(Direction direction, NetworkContext context, JamLibPacket packet) {
Map<PayloadType<?>, NetworkPayloadHandler<?>> handlers = switch (direction) {
case CLIENT_BOUND -> clientBoundHandlers;
case SERVER_BOUND -> serverBoundHandlers;
};

if (!types.containsKey(packet.payloadType())) {
throw new IllegalArgumentException("No payload type with the id " + packet.payloadType() + " (" + direction.name() + ") is registered");
}

if (!handlers.containsKey(packet.payloadType())) {
throw new IllegalStateException("Received a packet with the id " + packet.payloadType() + " (" + direction.name() + ") for which no handler is registered");
}

NetworkPayloadType<T> type = (NetworkPayloadType<T>) types.get(packet.payloadType());
NetworkPayloadHandler<T> handler = (NetworkPayloadHandler<T>) handlers.get(packet.payloadType());
handler.handle(context, type.getDeserializer().deserialize(packet.payload()));
}

@ApiStatus.Internal
public static List<Identifier> getRegisteredHandlerTypes(Direction direction) {
return (direction == Direction.CLIENT_BOUND ? clientBoundHandlers : serverBoundHandlers).keySet().stream().map(PayloadType::id).toList();
}

public enum Direction {
CLIENT_BOUND,
SERVER_BOUND
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@
*/
public interface NetworkCapability {
/**
* @param type The type of payload to check for.
* @return {@code true} if the connection that this capability represents can handle the packet type.
* @param kind The packet kind to check for.
* @return {@code true} if the connection that this capability represents can handle the packet kind.
*/
boolean canReceive(PayloadType<?> type);
default boolean canReceive(PacketKind<?> kind) {
return this.canReceive(kind.getIdentifier());
}

/**
* @param identifier The identifier of packet kind to check for.
* @return {@code true} if the connection that this capability represents can handle the packet kind.
*/
boolean canReceive(PacketIdentifier identifier);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

/**
* Context passed to a {@link NetworkPayloadHandler}.
* @param player The player who received or sent the packet.
*/
public record NetworkContext(Player player) {
public interface NetworkContext {
/**
* @return The player associated with the received packet.
*/
Player getPlayer();
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.jamalam360.jamlib.api.network;

public enum PacketDirection {
SERVERBOUND,
CLIENTBOUND
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.jamalam360.jamlib.api.network;

import net.minecraft.resources.Identifier;

/**
* Uniquely identifies a {@link PacketKind}.
*/
public record PacketIdentifier(Identifier identifier) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.github.jamalam360.jamlib.api.network;

import io.github.jamalam360.jamlib.impl.network.PacketKindImpl;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.Identifier;

/**
* Represents the kind of packet that can be sent over the network.
* @param <T> The type of the payload, usually a record.
*/
public interface PacketKind<T> {
/**
* @param id A unique identifier for this packet kind.
* @param codec A stream codec to encode and decode the payload.
* @param <T> The payload type.
* @return A {@link PacketKind} implementation.
*/
static <T> PacketKind<T> of(Identifier id, StreamCodec<RegistryFriendlyByteBuf, T> codec) {
return new PacketKindImpl<>(new PacketIdentifier(id), codec);
}

/**
* @param id A unique identifier for this packet kind.
* @param codec A stream codec to encode and decode the payload.
* @param <T> The payload type.
* @return A {@link PacketKind} implementation.
*/
static <T> PacketKind<T> of(PacketIdentifier id, StreamCodec<RegistryFriendlyByteBuf, T> codec) {
return new PacketKindImpl<>(id, codec);
}

/**
* @return A unique {@link PacketIdentifier} for this packet kind.
*/
PacketIdentifier getIdentifier();

/**
* @return A serializer instance for the payload type.
*/
Serializer<T> getSerializer();

/**
* @return A deserializer instance for the payload type.
*/
Deserializer<T> getDeserializer();

/**
* A serializer for a payload.
*/
@FunctionalInterface
interface Serializer<T> {
/**
* Serializes a payload to a buffer.
* @param object The payload to serialize.
* @param buf The buffer to write to.
*/
void serialize(T object, RegistryFriendlyByteBuf buf);
}

/**
* A deserializer for a payload.
*/
@FunctionalInterface
interface Deserializer<T> {
/**
* Deserializes a payload from a buffer.
* @param buf The buffer to read from.
* @return The deserialized payload.
*/
T deserialize(RegistryFriendlyByteBuf buf);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.jamalam360.jamlib.api.network;

public interface PacketPayload<T> {
PacketKind<T> getKind();
T getPayload();
}
Loading
Loading