mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-17 10:24:23 +01:00
Extract the networking wrapper to a separate package.
This commit is contained in:
parent
fdcb9508a8
commit
5b398c27c7
13 changed files with 227 additions and 116 deletions
|
@ -11,6 +11,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
|||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -120,13 +121,17 @@ public class BlockDestructionManager {
|
|||
|
||||
MsgBlockDestruction msg = new MsgBlockDestruction(values);
|
||||
|
||||
if (Channel.toBuffer(msg).writerIndex() > 1048576) {
|
||||
if (msg.toBuffer().writerIndex() > 1048576) {
|
||||
throw new IllegalStateException("Payload may not be larger than 1048576 bytes. Here's what we were trying to send: ["
|
||||
+ values.size() + "]\n"
|
||||
+ Arrays.toString(values.values().stream().mapToInt(Integer::intValue).toArray()));
|
||||
}
|
||||
|
||||
players.forEach(player -> Channel.SERVER_BLOCK_DESTRUCTION.send(player, msg));
|
||||
players.forEach(player -> {
|
||||
if (player instanceof ServerPlayerEntity) {
|
||||
Channel.SERVER_BLOCK_DESTRUCTION.send((ServerPlayerEntity)player, msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
|||
|
||||
if (entity instanceof ServerPlayerEntity) {
|
||||
MsgOtherPlayerCapabilities packet = new MsgOtherPlayerCapabilities(full, this);
|
||||
Channel.SERVER_PLAYER_CAPABILITIES.send(entity, packet);
|
||||
Channel.SERVER_PLAYER_CAPABILITIES.send((ServerPlayerEntity)entity, packet);
|
||||
Channel.SERVER_OTHER_PLAYER_CAPABILITIES.send(entity.world, packet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,114 +1,20 @@
|
|||
package com.minelittlepony.unicopia.network;
|
||||
|
||||
import java.util.function.Function;
|
||||
import com.minelittlepony.unicopia.util.network.S2CBroadcastPacketType;
|
||||
import com.minelittlepony.unicopia.util.network.C2SPacketType;
|
||||
import com.minelittlepony.unicopia.util.network.S2CPacketType;
|
||||
import com.minelittlepony.unicopia.util.network.SimpleNetworking;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
public interface Channel {
|
||||
SPacketType<MsgPlayerAbility<?>> CLIENT_PLAYER_ABILITY = clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new);
|
||||
SPacketType<MsgRequestCapabilities> CLIENT_REQUEST_CAPABILITIES = clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestCapabilities::new);
|
||||
S2CPacketType<MsgPlayerAbility<?>> CLIENT_PLAYER_ABILITY = SimpleNetworking.clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new);
|
||||
S2CPacketType<MsgRequestCapabilities> CLIENT_REQUEST_CAPABILITIES = SimpleNetworking.clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestCapabilities::new);
|
||||
S2CBroadcastPacketType<MsgOtherPlayerCapabilities> SERVER_OTHER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClients(new Identifier("unicopia", "other_player_capabilities"), MsgOtherPlayerCapabilities::new);
|
||||
|
||||
CPacketType<MsgPlayerCapabilities> SERVER_PLAYER_CAPABILITIES = serverToClient(new Identifier("unicopia", "player_capabilities"), MsgPlayerCapabilities::new);
|
||||
BPacketType<MsgOtherPlayerCapabilities> SERVER_OTHER_PLAYER_CAPABILITIES = serverToClients(new Identifier("unicopia", "other_player_capabilities"), MsgOtherPlayerCapabilities::new);
|
||||
CPacketType<MsgSpawnProjectile> SERVER_SPAWN_PROJECTILE = serverToClient(new Identifier("unicopia", "projectile_entity"), MsgSpawnProjectile::new);
|
||||
|
||||
CPacketType<MsgBlockDestruction> SERVER_BLOCK_DESTRUCTION = serverToClient(new Identifier("unicopia", "block_destruction"), MsgBlockDestruction::new);
|
||||
C2SPacketType<MsgPlayerCapabilities> SERVER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(new Identifier("unicopia", "player_capabilities"), MsgPlayerCapabilities::new);
|
||||
C2SPacketType<MsgSpawnProjectile> SERVER_SPAWN_PROJECTILE = SimpleNetworking.serverToClient(new Identifier("unicopia", "projectile_entity"), MsgSpawnProjectile::new);
|
||||
C2SPacketType<MsgBlockDestruction> SERVER_BLOCK_DESTRUCTION = SimpleNetworking.serverToClient(new Identifier("unicopia", "block_destruction"), MsgBlockDestruction::new);
|
||||
|
||||
static void bootstrap() { }
|
||||
|
||||
static <T extends Packet> SPacketType<T> clientToServer(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
ServerPlayNetworking.registerGlobalReceiver(id, (server, player, handler, buffer, responder) -> {
|
||||
T packet = factory.apply(buffer);
|
||||
server.execute(() -> packet.handle(player));
|
||||
});
|
||||
return () -> id;
|
||||
}
|
||||
|
||||
static <T extends Packet> CPacketType<T> serverToClient(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||
ClientProxy.register(id, factory);
|
||||
}
|
||||
return () -> id;
|
||||
}
|
||||
|
||||
static <T extends Packet> BPacketType<T> serverToClients(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||
ClientProxy.register(id, factory);
|
||||
}
|
||||
return () -> id;
|
||||
}
|
||||
|
||||
/**
|
||||
* A broadcast packet type. Sent by the server to all surrounding players.
|
||||
*/
|
||||
interface BPacketType<T extends Packet> {
|
||||
Identifier getId();
|
||||
|
||||
default void send(World world, T packet) {
|
||||
world.getPlayers().forEach(player -> {
|
||||
if (player instanceof ServerPlayerEntity) {
|
||||
ServerPlayNetworking.send((ServerPlayerEntity)player, getId(), toBuffer(packet));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A client packet type. Sent by the server to a specific player.
|
||||
*/
|
||||
interface CPacketType<T extends Packet> {
|
||||
Identifier getId();
|
||||
|
||||
default void send(PlayerEntity recipient, T packet) {
|
||||
ServerPlayNetworking.send(((ServerPlayerEntity)recipient), getId(), toBuffer(packet));
|
||||
}
|
||||
|
||||
default net.minecraft.network.Packet<?> toPacket(T packet) {
|
||||
return ServerPlayNetworking.createS2CPacket(getId(), toBuffer(packet));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A server packet type. Sent by the client to the server.
|
||||
*/
|
||||
interface SPacketType<T extends Packet> {
|
||||
Identifier getId();
|
||||
|
||||
default void send(T packet) {
|
||||
Preconditions.checkState(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT, "Client packet send called by the server");
|
||||
ClientPlayNetworking.send(getId(), toBuffer(packet));
|
||||
}
|
||||
}
|
||||
|
||||
interface Packet {
|
||||
void handle(PlayerEntity sender);
|
||||
|
||||
void toBuffer(PacketByteBuf buffer);
|
||||
}
|
||||
|
||||
static PacketByteBuf toBuffer(Packet packet) {
|
||||
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
|
||||
packet.toBuffer(buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
class ClientProxy {
|
||||
static <T extends Packet> void register(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
ClientPlayNetworking.registerGlobalReceiver(id, (client, ignore1, buffer, ignore2) -> {
|
||||
T packet = factory.apply(buffer);
|
||||
client.execute(() -> packet.handle(client.player));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.network;
|
||||
|
||||
import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
|
||||
import com.minelittlepony.unicopia.util.network.Packet;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
@ -8,7 +9,7 @@ import net.minecraft.network.PacketByteBuf;
|
|||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
||||
public class MsgBlockDestruction implements Channel.Packet {
|
||||
public class MsgBlockDestruction implements Packet<PlayerEntity> {
|
||||
|
||||
private final Long2ObjectMap<Integer> destructions;
|
||||
|
||||
|
|
|
@ -3,13 +3,14 @@ package com.minelittlepony.unicopia.network;
|
|||
import com.minelittlepony.unicopia.ability.Ability;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.network.Packet;
|
||||
import com.minelittlepony.unicopia.ability.Abilities;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
public class MsgPlayerAbility<T extends Hit> implements Channel.Packet {
|
||||
public class MsgPlayerAbility<T extends Hit> implements Packet<ServerPlayerEntity> {
|
||||
|
||||
private final Ability<T> power;
|
||||
|
||||
|
@ -33,7 +34,7 @@ public class MsgPlayerAbility<T extends Hit> implements Channel.Packet {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handle(PlayerEntity sender) {
|
||||
public void handle(ServerPlayerEntity sender) {
|
||||
Pony player = Pony.of(sender);
|
||||
if (player == null) {
|
||||
return;
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.UUID;
|
|||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.network.Packet;
|
||||
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
|
@ -16,7 +17,7 @@ import net.minecraft.entity.player.PlayerEntity;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
|
||||
public class MsgPlayerCapabilities implements Channel.Packet {
|
||||
public class MsgPlayerCapabilities implements Packet<PlayerEntity> {
|
||||
|
||||
protected final UUID playerId;
|
||||
|
||||
|
|
|
@ -3,12 +3,13 @@ package com.minelittlepony.unicopia.network;
|
|||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.WorldTribeManager;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.network.Packet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
public class MsgRequestCapabilities implements Channel.Packet {
|
||||
public class MsgRequestCapabilities implements Packet<ServerPlayerEntity> {
|
||||
|
||||
private final Race clientPreferredRace;
|
||||
|
||||
|
@ -26,7 +27,7 @@ public class MsgRequestCapabilities implements Channel.Packet {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handle(PlayerEntity sender) {
|
||||
public void handle(ServerPlayerEntity sender) {
|
||||
Pony player = Pony.of(sender);
|
||||
|
||||
Race worldDefaultRace = WorldTribeManager.forWorld((ServerWorld)player.getWorld()).getDefaultRace();
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
|||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Owned;
|
||||
import com.minelittlepony.unicopia.util.network.Packet;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
@ -14,7 +15,7 @@ import net.minecraft.entity.player.PlayerEntity;
|
|||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
|
||||
|
||||
public class MsgSpawnProjectile extends EntitySpawnS2CPacket implements Channel.Packet {
|
||||
public class MsgSpawnProjectile extends EntitySpawnS2CPacket implements Packet<PlayerEntity> {
|
||||
|
||||
MsgSpawnProjectile(PacketByteBuf buffer) {
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.minelittlepony.unicopia.util.network;
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
/**
|
||||
* A client packet type. Sent by the server to a specific player.
|
||||
*/
|
||||
public interface C2SPacketType<T extends Packet<PlayerEntity>> {
|
||||
Identifier getId();
|
||||
|
||||
default void send(ServerPlayerEntity recipient, T packet) {
|
||||
ServerPlayNetworking.send(recipient, getId(), packet.toBuffer());
|
||||
}
|
||||
|
||||
default net.minecraft.network.Packet<?> toPacket(T packet) {
|
||||
return ServerPlayNetworking.createS2CPacket(getId(), packet.toBuffer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.minelittlepony.unicopia.util.network;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
/**
|
||||
* Represents a message that can be either send from the client to the server or back.
|
||||
*/
|
||||
public interface Packet<P extends PlayerEntity> {
|
||||
/**
|
||||
* Called to handle this packet on the receiving end.
|
||||
*
|
||||
* @param sender The player who initially sent this packet.
|
||||
*/
|
||||
void handle(P sender);
|
||||
|
||||
/**
|
||||
* Writes this packet to the supplied buffer prior to transmission.
|
||||
*
|
||||
* @param buffer The buffer to write to.
|
||||
*/
|
||||
void toBuffer(PacketByteBuf buffer);
|
||||
|
||||
/**
|
||||
* Writes this packet to a new buffer.
|
||||
*
|
||||
* @return The resulting buffer for transmission
|
||||
*/
|
||||
default PacketByteBuf toBuffer() {
|
||||
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
|
||||
toBuffer(buf);
|
||||
return buf;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.minelittlepony.unicopia.util.network;
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* A broadcast packet type. Sent by the server to all surrounding players.
|
||||
*/
|
||||
public interface S2CBroadcastPacketType<T extends Packet<PlayerEntity>> {
|
||||
Identifier getId();
|
||||
|
||||
default void send(World world, T packet) {
|
||||
world.getPlayers().forEach(player -> {
|
||||
if (player instanceof ServerPlayerEntity) {
|
||||
ServerPlayNetworking.send((ServerPlayerEntity)player, getId(), packet.toBuffer());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.minelittlepony.unicopia.util.network;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
/**
|
||||
* A server packet type. Sent by the client to the server.
|
||||
*/
|
||||
public interface S2CPacketType<T extends Packet<ServerPlayerEntity>> {
|
||||
Identifier getId();
|
||||
|
||||
default void send(T packet) {
|
||||
Preconditions.checkState(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT, "Client packet send called by the server");
|
||||
ClientPlayNetworking.send(getId(), packet.toBuffer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package com.minelittlepony.unicopia.util.network;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
/**
|
||||
* A simplified, side-agnostic, and declaritive wrapper around {@link ServerPlayNetworking} and {@link ClientPlayNetworking}
|
||||
* designed to bring networking in line with the declaritive/registered nature of other parts of Mojang's echosystem.
|
||||
* <p>
|
||||
* It is safe to call these methods from either the client or the server, so modders can implement a
|
||||
* single static <code>PacketTypes</code> class with which they can easily send packets without worrying
|
||||
* about the complexities of the network thread, which side to register a global receiver on,
|
||||
* which method to use to send, or even whether their receiver is registered for a given player or not.
|
||||
* <p>
|
||||
* All of the above is handled in a black-box style by this class.
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>Packets are automatically reigstered on the appropriate sides.</li>
|
||||
* <li>Sending is done in the same way by calling `send` on your packet type.</li>
|
||||
* <li>Your packet's <code>handle</code> method is executed on the main thread where it is safe to interact with the world.</li>
|
||||
*/
|
||||
public final class SimpleNetworking {
|
||||
private SimpleNetworking() {throw new RuntimeException("new SimpleNetworking()");}
|
||||
/**
|
||||
* Registers a packet type for transmisison to the server.
|
||||
* <p>
|
||||
* The returned handle can be used by the client to send messages to the active minecraft server.
|
||||
* <p>
|
||||
*
|
||||
* @param <T> The type of packet to implement
|
||||
* @param id The message's unique used for serialization
|
||||
* @param factory A constructor returning new instances of the packet type
|
||||
*
|
||||
* @return A registered PacketType
|
||||
*/
|
||||
public static <T extends Packet<ServerPlayerEntity>> S2CPacketType<T> clientToServer(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
ServerPlayNetworking.registerGlobalReceiver(id, (server, player, handler, buffer, responder) -> {
|
||||
T packet = factory.apply(buffer);
|
||||
server.execute(() -> packet.handle(player));
|
||||
});
|
||||
return () -> id;
|
||||
}
|
||||
/**
|
||||
* Registers a packet type for transmission to the client.
|
||||
*
|
||||
* The returned handle can be used by the server to send messages to a given recipient.
|
||||
*
|
||||
* @param <T> The type of packet to implement
|
||||
* @param id The message's unique used for serialization
|
||||
* @param factory A constructor returning new instances of the packet type
|
||||
*
|
||||
* @return A registered PacketType
|
||||
*/
|
||||
public static <T extends Packet<PlayerEntity>> C2SPacketType<T> serverToClient(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||
ClientProxy.register(id, factory);
|
||||
}
|
||||
return () -> id;
|
||||
}
|
||||
/**
|
||||
* Registers a packet type for transmission to all clients.
|
||||
*
|
||||
* The returned handle can be used by the server to broadcast a message to all connected clients in a given dimension.
|
||||
*
|
||||
* @param <T> The type of packet to implement
|
||||
* @param id The message's unique used for serialization
|
||||
* @param factory A constructor returning new instances of the packet type
|
||||
*
|
||||
* @return A registered PacketType
|
||||
*/
|
||||
public static <T extends Packet<PlayerEntity>> S2CBroadcastPacketType<T> serverToClients(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||
ClientProxy.register(id, factory);
|
||||
}
|
||||
return () -> id;
|
||||
}
|
||||
// Fabric's APIs are not side-agnostic.
|
||||
// We punt this to a separate class file to keep it from being eager-loaded on a server environment.
|
||||
private static final class ClientProxy {
|
||||
private ClientProxy() {throw new RuntimeException("new ClientProxy()");}
|
||||
public static <T extends Packet<PlayerEntity>> void register(Identifier id, Function<PacketByteBuf, T> factory) {
|
||||
ClientPlayNetworking.registerGlobalReceiver(id, (client, ignore1, buffer, ignore2) -> {
|
||||
T packet = factory.apply(buffer);
|
||||
client.execute(() -> packet.handle(client.player));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue