Skip to content

Commit

Permalink
[1.20.2] Support common registration packets. Add configuration task …
Browse files Browse the repository at this point in the history
…API (#3244)

* Config networking refactor :)

* Add some unit tests for common packets.

* write FabricPacket on network thread.
Split ServerConfigurationConnectionEvents into two.

* Fixes

* Rename event

* Add a testmod + ssome docs

* Improve registry sync fixing deadlock in a number of cases.

* Cleanup channel events.

* Review feedback and fixes.
  • Loading branch information
modmuss50 authored Aug 9, 2023
1 parent 86b1264 commit 0b2eb40
Show file tree
Hide file tree
Showing 41 changed files with 1,637 additions and 298 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ allprojects {

testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}"
testImplementation sourceSets.testmodClient.output
testImplementation 'org.mockito:mockito-core:5.4.0'
}

test {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.client.networking.v1;

import java.util.List;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
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.PacketSender;

/**
* Offers access to events related to the indication of a connected server's ability to receive packets in certain channels.
*/
public final class C2SConfigurationChannelEvents {
/**
* An event for the client configuration 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.
*/
public static final Event<Register> REGISTER = EventFactory.createArrayBacked(Register.class, callbacks -> (handler, sender, client, channels) -> {
for (Register callback : callbacks) {
callback.onChannelRegister(handler, sender, client, channels);
}
});

/**
* An event for the client configuration network handler receiving an update indicating the connected server's lack of ability to receive packets in certain channels.
* This event may be invoked at any time after login and up to disconnection.
*/
public static final Event<Unregister> UNREGISTER = EventFactory.createArrayBacked(Unregister.class, callbacks -> (handler, sender, client, channels) -> {
for (Unregister callback : callbacks) {
callback.onChannelUnregister(handler, sender, client, channels);
}
});

private C2SConfigurationChannelEvents() {
}

/**
* @see C2SConfigurationChannelEvents#REGISTER
*/
@FunctionalInterface
public interface Register {
void onChannelRegister(ClientConfigurationNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}

/**
* @see C2SConfigurationChannelEvents#UNREGISTER
*/
@FunctionalInterface
public interface Unregister {
void onChannelUnregister(ClientConfigurationNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@

import java.util.List;

import org.jetbrains.annotations.ApiStatus;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.util.Identifier;

Expand Down Expand Up @@ -53,28 +50,6 @@ public final class C2SPlayChannelEvents {
}
});

/**
* An event for the client configuration 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.
*/
@ApiStatus.Experimental
public static final Event<RegisterConfiguration> REGISTER_CONFIGURATION = EventFactory.createArrayBacked(RegisterConfiguration.class, callbacks -> (handler, sender, client, channels) -> {
for (RegisterConfiguration callback : callbacks) {
callback.onChannelRegister(handler, sender, client, channels);
}
});

/**
* An event for the client configuration network handler receiving an update indicating the connected server's lack of ability to receive packets in certain channels.
* This event may be invoked at any time after login and up to disconnection.
*/
@ApiStatus.Experimental
public static final Event<UnregisterConfiguration> UNREGISTER_CONFIGURATION = EventFactory.createArrayBacked(UnregisterConfiguration.class, callbacks -> (handler, sender, client, channels) -> {
for (UnregisterConfiguration callback : callbacks) {
callback.onChannelUnregister(handler, sender, client, channels);
}
});

private C2SPlayChannelEvents() {
}

Expand All @@ -93,22 +68,4 @@ public interface Register {
public interface Unregister {
void onChannelUnregister(ClientPlayNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}

/**
* @see C2SPlayChannelEvents#REGISTER_CONFIGURATION
*/
@FunctionalInterface
@ApiStatus.Experimental
public interface RegisterConfiguration {
void onChannelRegister(ClientConfigurationNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}

/**
* @see C2SPlayChannelEvents#UNREGISTER_CONFIGURATION
*/
@FunctionalInterface
@ApiStatus.Experimental
public interface UnregisterConfiguration {
void onChannelUnregister(ClientConfigurationNetworkHandler handler, PacketSender sender, MinecraftClient client, List<Identifier> channels);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import net.minecraft.util.thread.ThreadExecutor;

import net.fabricmc.fabric.api.networking.v1.FabricPacket;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.fabricmc.fabric.api.networking.v1.PacketType;
import net.fabricmc.fabric.api.networking.v1.ServerConfigurationNetworking;
Expand Down Expand Up @@ -384,9 +383,14 @@ public static <T extends FabricPacket> void send(T packet) {
Objects.requireNonNull(packet, "Packet cannot be null");
Objects.requireNonNull(packet.getType(), "Packet#getType cannot return null");

PacketByteBuf buf = PacketByteBufs.create();
packet.write(buf);
send(packet.getType().getId(), buf);
final ClientConfigurationNetworkAddon addon = ClientNetworkingImpl.getClientConfigurationAddon();

if (addon != null) {
addon.sendPacket(packet);
return;
}

throw new IllegalStateException("Cannot send packet while not configuring!");
}

private ClientConfigurationNetworking() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import net.minecraft.util.thread.ThreadExecutor;

import net.fabricmc.fabric.api.networking.v1.FabricPacket;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.fabricmc.fabric.api.networking.v1.PacketType;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
Expand Down Expand Up @@ -339,6 +338,16 @@ public static Packet<ServerCommonPacketListener> createC2SPacket(Identifier chan
return ClientNetworkingImpl.createC2SPacket(channelName, buf);
}

/**
* Creates a packet which may be sent to the connected server.
*
* @param packet the fabric packet
* @return a new packet
*/
public static <T extends FabricPacket> Packet<ServerCommonPacketListener> createC2SPacket(T packet) {
return ClientNetworkingImpl.createC2SPacket(packet);
}

/**
* Gets the packet sender which sends packets to the connected server.
*
Expand Down Expand Up @@ -381,9 +390,13 @@ public static <T extends FabricPacket> void send(T packet) {
Objects.requireNonNull(packet, "Packet cannot be null");
Objects.requireNonNull(packet.getType(), "Packet#getType cannot return null");

PacketByteBuf buf = PacketByteBufs.create();
packet.write(buf);
send(packet.getType().getId(), buf);
// You cant send without a client player, so this is fine
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
MinecraftClient.getInstance().getNetworkHandler().sendPacket(createC2SPacket(packet));
return;
}

throw new IllegalStateException("Cannot send packets when not in game!");
}

private ClientPlayNetworking() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,18 @@
import net.minecraft.network.packet.Packet;
import net.minecraft.util.Identifier;

import net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.C2SConfigurationChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationNetworking;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.FabricPacket;
import net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon;
import net.fabricmc.fabric.impl.networking.ChannelInfoHolder;
import net.fabricmc.fabric.impl.networking.NetworkingImpl;
import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload;
import net.fabricmc.fabric.mixin.networking.client.accessor.ClientCommonNetworkHandlerAccessor;
import net.fabricmc.fabric.mixin.networking.client.accessor.ClientConfigurationNetworkHandlerAccessor;
import net.fabricmc.fabric.mixin.networking.client.accessor.ClientLoginNetworkHandlerAccessor;

public final class ClientConfigurationNetworkAddon extends AbstractChanneledNetworkAddon<ClientConfigurationNetworking.ConfigurationChannelHandler> {
private final ClientConfigurationNetworkHandler handler;
Expand Down Expand Up @@ -65,8 +67,17 @@ public void lateInit() {
}

public void onServerReady() {
this.sendInitialChannelRegistrationPacket();
this.sentInitialRegisterPacket = true;
// Do nothing for now
}

@Override
protected void receiveRegistration(boolean register, PacketByteBuf buf) {
super.receiveRegistration(register, buf);

if (register && !this.sentInitialRegisterPacket) {
this.sendInitialChannelRegistrationPacket();
this.sentInitialRegisterPacket = true;
}
}

/**
Expand Down Expand Up @@ -100,14 +111,19 @@ public Packet<?> createPacket(Identifier channelName, PacketByteBuf buf) {
return ClientPlayNetworking.createC2SPacket(channelName, buf);
}

@Override
public Packet<?> createPacket(FabricPacket packet) {
return ClientPlayNetworking.createC2SPacket(packet);
}

@Override
protected void invokeRegisterEvent(List<Identifier> ids) {
C2SPlayChannelEvents.REGISTER_CONFIGURATION.invoker().onChannelRegister(this.handler, this, this.client, ids);
C2SConfigurationChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.client, ids);
}

@Override
protected void invokeUnregisterEvent(List<Identifier> ids) {
C2SPlayChannelEvents.UNREGISTER_CONFIGURATION.invoker().onChannelUnregister(this.handler, this, this.client, ids);
C2SConfigurationChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.client, ids);
}

@Override
Expand Down Expand Up @@ -147,6 +163,10 @@ protected void invokeDisconnectEvent() {

@Override
protected boolean isReservedChannel(Identifier channelName) {
return NetworkingImpl.isReservedPlayChannel(channelName);
return NetworkingImpl.isReservedCommonChannel(channelName);
}

public ChannelInfoHolder getChannelInfoHolder() {
return (ChannelInfoHolder) ((ClientLoginNetworkHandlerAccessor) handler).getConnection();
}
}
Loading

0 comments on commit 0b2eb40

Please sign in to comment.