Networking V1: Hopefully the final fix (#1208)

THIS SHOULD WORK.
This commit is contained in:
i509VCB 2020-12-09 12:21:45 -06:00 committed by GitHub
parent b08303c750
commit 4358fbc6b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 88 additions and 45 deletions

View file

@ -32,7 +32,7 @@ import net.fabricmc.fabric.api.networking.v1.PacketSender;
* Offers access to events related to the indication of a connected server's ability to receive packets in certain channels.
*/
@Environment(EnvType.CLIENT)
public final class S2CPlayChannelEvents {
public final class C2SPlayChannelEvents {
/**
* An event for the client play network handler receiving an update indicating the connected server's ability to receive packets in certain channels.
* This event may be invoked at any time after login and up to disconnection.
@ -53,11 +53,11 @@ public final class S2CPlayChannelEvents {
}
});
private S2CPlayChannelEvents() {
private C2SPlayChannelEvents() {
}
/**
* @see S2CPlayChannelEvents#REGISTER
* @see C2SPlayChannelEvents#REGISTER
*/
@Environment(EnvType.CLIENT)
@FunctionalInterface
@ -66,7 +66,7 @@ public final class S2CPlayChannelEvents {
}
/**
* @see S2CPlayChannelEvents#UNREGISTER
* @see C2SPlayChannelEvents#UNREGISTER
*/
@Environment(EnvType.CLIENT)
@FunctionalInterface

View file

@ -32,6 +32,7 @@ import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.fabric.impl.networking.client.ClientNetworkingImpl;
import net.fabricmc.fabric.impl.networking.client.ClientPlayNetworkAddon;
/**
* Offers access to play stage client-side networking functionalities.
@ -104,8 +105,10 @@ public final class ClientPlayNetworking {
* @see ClientPlayConnectionEvents#INIT
*/
public static boolean registerReceiver(Identifier channelName, PlayChannelHandler channelHandler) {
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler()).registerChannel(channelName, channelHandler);
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
if (addon != null) {
return addon.registerChannel(channelName, channelHandler);
}
throw new IllegalStateException("Cannot register receiver while not in game!");
@ -122,8 +125,10 @@ public final class ClientPlayNetworking {
*/
@Nullable
public static PlayChannelHandler unregisterReceiver(Identifier channelName) throws IllegalStateException {
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler()).unregisterChannel(channelName);
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
if (addon != null) {
return addon.unregisterChannel(channelName);
}
throw new IllegalStateException("Cannot unregister receiver while not in game!");
@ -136,8 +141,10 @@ public final class ClientPlayNetworking {
* @throws IllegalStateException if the client is not connected to a server
*/
public static Set<Identifier> getReceived() throws IllegalStateException {
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler()).getReceivableChannels();
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
if (addon != null) {
return addon.getReceivableChannels();
}
throw new IllegalStateException("Cannot get a list of channels the client can receive packets on while not in game!");
@ -150,8 +157,10 @@ public final class ClientPlayNetworking {
* @throws IllegalStateException if the client is not connected to a server
*/
public static Set<Identifier> getSendable() throws IllegalStateException {
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler()).getSendableChannels();
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
if (addon != null) {
return addon.getSendableChannels();
}
throw new IllegalStateException("Cannot get a list of channels the server can receive packets on while not in game!");
@ -165,6 +174,7 @@ public final class ClientPlayNetworking {
* False if the client is not in game.
*/
public static boolean canSend(Identifier channelName) throws IllegalArgumentException {
// You cant send without a client player, so this is fine
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler()).getSendableChannels().contains(channelName);
}
@ -193,6 +203,7 @@ public final class ClientPlayNetworking {
* @throws IllegalStateException if the client is not connected to a server
*/
public static PacketSender getSender() throws IllegalStateException {
// You cant send without a client player, so this is fine
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler());
}
@ -208,6 +219,7 @@ public final class ClientPlayNetworking {
* @throws IllegalStateException if the client is not connected to a server
*/
public static void send(Identifier channelName, PacketByteBuf buf) throws IllegalStateException {
// You cant send without a client player, so this is fine
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
MinecraftClient.getInstance().getNetworkHandler().sendPacket(createC2SPacket(channelName, buf));
return;

View file

@ -23,7 +23,7 @@
* <p>For events related to connection to a server see {@link net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents} for login stage
* or {@link net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents} for play stage.
*
* <p>For events related to the ability of a server to receive packets on a channel of a specific name see {@link net.fabricmc.fabric.api.client.networking.v1.S2CPlayChannelEvents}.
* <p>For events related to the ability of a server to receive packets on a channel of a specific name see {@link net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents}.
*/
package net.fabricmc.fabric.api.client.networking.v1;

View file

@ -28,7 +28,7 @@ import net.fabricmc.fabric.api.event.EventFactory;
/**
* Offers access to events related to the indication of a connected client's ability to receive packets in certain channels.
*/
public final class C2SPlayChannelEvents {
public final class S2CPlayChannelEvents {
/**
* An event for the server play network handler receiving an update indicating the connected client's ability to receive packets in certain channels.
* This event may be invoked at any time after login and up to disconnection.
@ -49,11 +49,11 @@ public final class C2SPlayChannelEvents {
}
});
private C2SPlayChannelEvents() {
private S2CPlayChannelEvents() {
}
/**
* @see C2SPlayChannelEvents#REGISTER
* @see S2CPlayChannelEvents#REGISTER
*/
@FunctionalInterface
public interface Register {
@ -61,7 +61,7 @@ public final class C2SPlayChannelEvents {
}
/**
* @see C2SPlayChannelEvents#UNREGISTER
* @see S2CPlayChannelEvents#UNREGISTER
*/
@FunctionalInterface
public interface Unregister {

View file

@ -23,7 +23,7 @@
* <p>For events related to the connection to a client see {@link net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents} for login stage
* or {@link net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents} for play stage.
*
* <p>For events related to the ability of a client to receive packets on a channel of a specific name see {@link net.fabricmc.fabric.api.networking.v1.C2SPlayChannelEvents}.
* <p>For events related to the ability of a client to receive packets on a channel of a specific name see {@link net.fabricmc.fabric.api.networking.v1.S2CPlayChannelEvents}.
*/
package net.fabricmc.fabric.api.networking.v1;

View file

@ -109,7 +109,7 @@ public abstract class AbstractChanneledNetworkAddon<H> extends AbstractNetworkAd
protected abstract void receive(H handler, PacketByteBuf buf);
protected void sendInitialChannelRegistrationPacket() {
final PacketByteBuf buf = this.createRegistrationPacket(this.receiver.getChannels());
final PacketByteBuf buf = this.createRegistrationPacket(this.getReceivableChannels());
if (buf != null) {
this.sendPacket(NetworkingImpl.REGISTER_CHANNEL, buf);
@ -158,12 +158,12 @@ public abstract class AbstractChanneledNetworkAddon<H> extends AbstractNetworkAd
this.schedule(register ? () -> register(ids) : () -> unregister(ids));
}
public void register(List<Identifier> ids) {
void register(List<Identifier> ids) {
this.sendableChannels.addAll(ids);
this.invokeRegisterEvent(ids);
}
public void unregister(List<Identifier> ids) {
void unregister(List<Identifier> ids) {
this.sendableChannels.removeAll(ids);
this.invokeUnregisterEvent(ids);
}

View file

@ -36,6 +36,7 @@ import net.minecraft.util.Identifier;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginNetworking;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.impl.networking.ChannelInfoHolder;
@ -48,6 +49,7 @@ import net.fabricmc.fabric.mixin.networking.accessor.MinecraftClientAccessor;
public final class ClientNetworkingImpl {
public static final GlobalReceiverRegistry<ClientLoginNetworking.LoginQueryRequestHandler> LOGIN = new GlobalReceiverRegistry<>();
public static final GlobalReceiverRegistry<ClientPlayNetworking.PlayChannelHandler> PLAY = new GlobalReceiverRegistry<>();
private static ClientPlayNetworkAddon currentPlayAddon;
public static ClientPlayNetworkAddon getAddon(ClientPlayNetworkHandler handler) {
return ((ClientPlayNetworkHandlerExtensions) handler).getAddon();
@ -83,7 +85,34 @@ public final class ClientNetworkingImpl {
return null;
}
@Nullable
public static ClientPlayNetworkAddon getClientPlayAddon() {
// Since Minecraft can be a bit weird, we need to check for the play addon in a few ways:
// If the client's player is set this will work
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
currentPlayAddon = null; // Shouldn't need this anymore
return ClientNetworkingImpl.getAddon(MinecraftClient.getInstance().getNetworkHandler());
}
// We haven't hit the end of onGameJoin yet, use our backing field here to access the network handler
if (currentPlayAddon != null) {
return currentPlayAddon;
}
// We are not in play stage
return null;
}
public static void setClientPlayAddon(ClientPlayNetworkAddon addon) {
currentPlayAddon = addon;
}
public static void clientInit() {
// Reference cleanup for the locally stored addon if we are disconnected
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> {
currentPlayAddon = null;
});
// Register a login query handler for early channel registration.
ClientLoginNetworking.registerGlobalReceiver(NetworkingImpl.EARLY_REGISTRATION_CHANNEL, (client, handler, buf, listenerAdder) -> {
int n = buf.readVarInt();

View file

@ -29,7 +29,7 @@ import net.minecraft.util.Identifier;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.S2CPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon;
@ -60,7 +60,7 @@ public final class ClientPlayNetworkAddon extends AbstractChanneledNetworkAddon<
this.registerChannel(entry.getKey(), entry.getValue());
}
ClientPlayConnectionEvents.INIT.invoker().onPlayInit(handler, this.client);
ClientPlayConnectionEvents.INIT.invoker().onPlayInit(this.handler, this.client);
}
public void onServerReady() {
@ -111,12 +111,12 @@ public final class ClientPlayNetworkAddon extends AbstractChanneledNetworkAddon<
@Override
protected void invokeRegisterEvent(List<Identifier> ids) {
S2CPlayChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.client, ids);
C2SPlayChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.client, ids);
}
@Override
protected void invokeUnregisterEvent(List<Identifier> ids) {
S2CPlayChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.client, ids);
C2SPlayChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.client, ids);
}
@Override

View file

@ -27,7 +27,7 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.networking.v1.S2CPlayChannelEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon;
@ -103,12 +103,12 @@ public final class ServerPlayNetworkAddon extends AbstractChanneledNetworkAddon<
@Override
protected void invokeRegisterEvent(List<Identifier> ids) {
C2SPlayChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.server, ids);
S2CPlayChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.server, ids);
}
@Override
protected void invokeUnregisterEvent(List<Identifier> ids) {
C2SPlayChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.server, ids);
S2CPlayChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.server, ids);
}
@Override

View file

@ -31,6 +31,7 @@ import net.minecraft.text.Text;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.impl.networking.client.ClientNetworkingImpl;
import net.fabricmc.fabric.impl.networking.client.ClientPlayNetworkAddon;
import net.fabricmc.fabric.impl.networking.client.ClientPlayNetworkHandlerExtensions;
@ -48,6 +49,7 @@ abstract class ClientPlayNetworkHandlerMixin implements ClientPlayNetworkHandler
private void initAddon(CallbackInfo ci) {
this.addon = new ClientPlayNetworkAddon((ClientPlayNetworkHandler) (Object) this, this.client);
// A bit of a hack but it allows the field above to be set in case someone registers handlers during INIT event which refers to said field
ClientNetworkingImpl.setClientPlayAddon(this.addon);
this.addon.lateInit();
}

View file

@ -30,7 +30,7 @@ import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.S2CPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
public final class NetworkingChannelClientTest implements ClientModInitializer {
@ -47,7 +47,7 @@ public final class NetworkingChannelClientTest implements ClientModInitializer {
}
});
S2CPlayChannelEvents.REGISTER.register((handler, sender, client, channels) -> {
C2SPlayChannelEvents.REGISTER.register((handler, sender, client, channels) -> {
SUPPORTED_C2S_CHANNELS.addAll(channels);
if (MinecraftClient.getInstance().currentScreen instanceof ChannelScreen) {
@ -55,7 +55,7 @@ public final class NetworkingChannelClientTest implements ClientModInitializer {
}
});
S2CPlayChannelEvents.UNREGISTER.register((handler, sender, client, channels) -> {
C2SPlayChannelEvents.UNREGISTER.register((handler, sender, client, channels) -> {
SUPPORTED_C2S_CHANNELS.removeAll(channels);
if (MinecraftClient.getInstance().currentScreen instanceof ChannelScreen) {

View file

@ -21,7 +21,7 @@ import java.util.Collection;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.client.networking.v1.S2CPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
@ -32,12 +32,12 @@ import net.fabricmc.fabric.api.event.EventFactory;
* <p>Registrations received will be for <em>server -&gt; client</em> packets
* that the sending client can understand.
*
* @deprecated Please migrate to {@link S2CPlayChannelEvents}.
* @deprecated Please migrate to {@link C2SPlayChannelEvents}.
*/
@Deprecated
public interface C2SPacketTypeCallback {
/**
* @deprecated Please migrate to {@link S2CPlayChannelEvents#REGISTER}.
* @deprecated Please migrate to {@link C2SPlayChannelEvents#REGISTER}.
*/
@Deprecated
Event<C2SPacketTypeCallback> REGISTERED = EventFactory.createArrayBacked(
@ -50,7 +50,7 @@ public interface C2SPacketTypeCallback {
);
/**
* @deprecated Please migrate to {@link S2CPlayChannelEvents#UNREGISTER}.
* @deprecated Please migrate to {@link C2SPlayChannelEvents#UNREGISTER}.
*/
@Deprecated
Event<C2SPacketTypeCallback> UNREGISTERED = EventFactory.createArrayBacked(

View file

@ -22,7 +22,7 @@ import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.fabricmc.fabric.api.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.networking.v1.S2CPlayChannelEvents;
/**
* Event for listening to packet type registration and unregistration notifications
@ -31,12 +31,12 @@ import net.fabricmc.fabric.api.networking.v1.C2SPlayChannelEvents;
* <p>Registrations received will be for <em>client -&gt; server</em> packets
* that the sending server can understand.
*
* @deprecated Please migrate to {@link C2SPlayChannelEvents}.
* @deprecated Please migrate to {@link S2CPlayChannelEvents}.
*/
@Deprecated
public interface S2CPacketTypeCallback {
/**
* @deprecated Please migrate to {@link C2SPlayChannelEvents#REGISTER}.
* @deprecated Please migrate to {@link S2CPlayChannelEvents#REGISTER}.
*/
@Deprecated
Event<S2CPacketTypeCallback> REGISTERED = EventFactory.createArrayBacked(
@ -49,7 +49,7 @@ public interface S2CPacketTypeCallback {
);
/**
* @deprecated Please migrate to {@link C2SPlayChannelEvents#UNREGISTER}.
* @deprecated Please migrate to {@link S2CPlayChannelEvents#UNREGISTER}.
*/
@Deprecated
Event<S2CPacketTypeCallback> UNREGISTERED = EventFactory.createArrayBacked(

View file

@ -18,13 +18,13 @@ package net.fabricmc.fabric.impl.networking;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.event.network.S2CPacketTypeCallback;
import net.fabricmc.fabric.api.client.networking.v1.S2CPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents;
public final class OldClientNetworkingHooks implements ClientModInitializer {
@Override
public void onInitializeClient() {
// Must be lambdas below
S2CPlayChannelEvents.REGISTER.register((handler, client, sender, channels) -> S2CPacketTypeCallback.REGISTERED.invoker().accept(channels));
S2CPlayChannelEvents.UNREGISTER.register((handler, client, sender, channels) -> S2CPacketTypeCallback.UNREGISTERED.invoker().accept(channels));
C2SPlayChannelEvents.REGISTER.register((handler, client, sender, channels) -> S2CPacketTypeCallback.REGISTERED.invoker().accept(channels));
C2SPlayChannelEvents.UNREGISTER.register((handler, client, sender, channels) -> S2CPacketTypeCallback.UNREGISTERED.invoker().accept(channels));
}
}

View file

@ -18,16 +18,16 @@ package net.fabricmc.fabric.impl.networking;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.network.C2SPacketTypeCallback;
import net.fabricmc.fabric.api.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.networking.v1.S2CPlayChannelEvents;
public final class OldNetworkingHooks implements ModInitializer {
@Override
public void onInitialize() {
// Must be lambdas below
C2SPlayChannelEvents.REGISTER.register((handler, server, sender, channels) -> {
S2CPlayChannelEvents.REGISTER.register((handler, server, sender, channels) -> {
C2SPacketTypeCallback.REGISTERED.invoker().accept(handler.player, channels);
});
C2SPlayChannelEvents.UNREGISTER.register((handler, server, sender, channels) -> {
S2CPlayChannelEvents.UNREGISTER.register((handler, server, sender, channels) -> {
C2SPacketTypeCallback.UNREGISTERED.invoker().accept(handler.player, channels);
});
}