From 502008466385890f66b92b2ea4ec7d7c6ebb2ec0 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 8 Apr 2022 21:07:12 -0500 Subject: [PATCH] Remove the fabric networking code The code isn't currently in use and is causing issues in 1.16.5. I put the code in zip files in case someone wants to quickly re-add it. --- .../main/java/com/seibel/lod/forge/fabric.zip | Bin 0 -> 65732 bytes .../networking/v1/C2SPlayChannelEvents.java | 72 ----- .../v1/ClientLoginConnectionEvents.java | 103 ------ .../networking/v1/ClientLoginNetworking.java | 161 ---------- .../v1/ClientPlayConnectionEvents.java | 85 ----- .../networking/v1/ClientPlayNetworking.java | 256 --------------- .../client/networking/v1/package-info.java | 29 -- .../fabric/api/event/AutoInvokingEvent.java | 55 ---- .../lod/forge/fabric/api/event/Event.java | 91 ------ .../forge/fabric/api/event/EventFactory.java | 141 --------- .../networking/v1/EntityTrackingEvents.java | 74 ----- .../api/networking/v1/FutureListeners.java | 94 ------ .../api/networking/v1/PacketByteBufs.java | 204 ------------ .../api/networking/v1/PacketSender.java | 83 ----- .../api/networking/v1/PlayerLookup.java | 203 ------------ .../networking/v1/S2CPlayChannelEvents.java | 68 ---- .../v1/ServerLoginConnectionEvents.java | 91 ------ .../networking/v1/ServerLoginNetworking.java | 196 ------------ .../v1/ServerPlayConnectionEvents.java | 79 ----- .../networking/v1/ServerPlayNetworking.java | 295 ------------------ .../api/networking/v1/package-info.java | 29 -- .../fabric/api/util/BooleanFunction.java | 33 -- .../lod/forge/fabric/api/util/NbtType.java | 50 --- .../lod/forge/fabric/api/util/TriState.java | 139 --------- .../impl/base/event/ArrayBackedEvent.java | 130 -------- .../impl/base/event/EventFactoryImpl.java | 122 -------- .../impl/base/event/EventPhaseData.java | 47 --- .../fabric/impl/base/event/PhaseSorting.java | 164 ---------- .../AbstractChanneledNetworkAddon.java | 205 ------------ .../impl/networking/AbstractNetworkAddon.java | 143 --------- .../impl/networking/ChannelInfoHolder.java | 27 -- .../networking/DisconnectPacketSource.java | 24 -- .../networking/GlobalReceiverRegistry.java | 173 ---------- .../networking/NetworkHandlerExtensions.java | 21 -- .../impl/networking/NetworkingImpl.java | 86 ----- .../networking/PacketCallbackListener.java | 28 -- .../client/ClientLoginNetworkAddon.java | 121 ------- .../client/ClientNetworkingImpl.java | 136 -------- .../client/ClientPlayNetworkAddon.java | 151 --------- .../networking/server/QueryIdFactory.java | 38 --- .../server/ServerLoginNetworkAddon.java | 207 ------------ .../server/ServerNetworkingImpl.java | 45 --- .../server/ServerPlayNetworkAddon.java | 146 --------- .../forge/mixins/fabric/mixin/networking.zip | Bin 0 -> 14579 bytes .../networking/ClientConnectionMixin.java | 95 ------ .../networking/EntityTrackerEntryMixin.java | 45 --- .../mixin/networking/PlayerManagerMixin.java | 34 -- .../ServerLoginNetworkHandlerMixin.java | 104 ------ .../ServerPlayNetworkHandlerMixin.java | 78 ----- .../accessor/ConnectScreenAccessor.java | 28 -- .../CustomPayloadC2SPacketAccessor.java | 32 -- .../accessor/EntityTrackerAccessor.java | 28 -- .../LoginQueryResponseC2SPacketAccessor.java | 33 -- .../accessor/MinecraftClientAccessor.java | 30 -- .../ServerLoginNetworkHandlerAccessor.java | 29 -- .../ThreadedAnvilChunkStorageAccessor.java | 28 -- .../ClientLoginNetworkHandlerMixin.java | 68 ---- .../client/ClientPlayNetworkHandlerMixin.java | 73 ----- .../lod/forge/networking/NetworkHandler.java | 16 +- 59 files changed, 8 insertions(+), 5358 deletions(-) create mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric.zip delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/C2SPlayChannelEvents.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginConnectionEvents.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginNetworking.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayConnectionEvents.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayNetworking.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/package-info.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/event/AutoInvokingEvent.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/event/Event.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/event/EventFactory.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/EntityTrackingEvents.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/FutureListeners.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketByteBufs.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketSender.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PlayerLookup.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/S2CPlayChannelEvents.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginConnectionEvents.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginNetworking.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayConnectionEvents.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayNetworking.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/package-info.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/util/BooleanFunction.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/util/NbtType.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/api/util/TriState.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/ArrayBackedEvent.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventFactoryImpl.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventPhaseData.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/PhaseSorting.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractChanneledNetworkAddon.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractNetworkAddon.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/ChannelInfoHolder.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/DisconnectPacketSource.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/GlobalReceiverRegistry.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkHandlerExtensions.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkingImpl.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/PacketCallbackListener.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientLoginNetworkAddon.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientNetworkingImpl.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientPlayNetworkAddon.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/QueryIdFactory.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerLoginNetworkAddon.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerNetworkingImpl.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerPlayNetworkAddon.java create mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking.zip delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ClientConnectionMixin.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/EntityTrackerEntryMixin.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/PlayerManagerMixin.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerLoginNetworkHandlerMixin.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerPlayNetworkHandlerMixin.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ConnectScreenAccessor.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/CustomPayloadC2SPacketAccessor.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/EntityTrackerAccessor.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/LoginQueryResponseC2SPacketAccessor.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/MinecraftClientAccessor.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ServerLoginNetworkHandlerAccessor.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ThreadedAnvilChunkStorageAccessor.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientLoginNetworkHandlerMixin.java delete mode 100644 forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientPlayNetworkHandlerMixin.java diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric.zip b/forge/src/main/java/com/seibel/lod/forge/fabric.zip new file mode 100644 index 0000000000000000000000000000000000000000..44833cbb8a05d475da8402058b75153486aa0b38 GIT binary patch literal 65732 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 z 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
ZV>_pUxDO$A;q2Vo09- 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 literal 0 HcmV?d00001 diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/C2SPlayChannelEvents.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/C2SPlayChannelEvents.java deleted file mode 100644 index e2380f8de..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/C2SPlayChannelEvents.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.client.networking.v1; - -import java.util.List; -import com.seibel.lod.forge.fabric.api.event.Event; -import com.seibel.lod.forge.fabric.api.event.EventFactory; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.resources.ResourceLocation; - -/** - * Offers access to events related to the indication of a connected server's ability to receive packets in certain channels. - */ - -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. - */ - public static final Event 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 play 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 = EventFactory.createArrayBacked(Unregister.class, callbacks -> (handler, sender, client, channels) -> { - for (Unregister callback : callbacks) { - callback.onChannelUnregister(handler, sender, client, channels); - } - }); - - private C2SPlayChannelEvents() { - } - - /** - * @see C2SPlayChannelEvents#REGISTER - */ - - @FunctionalInterface - public interface Register { - void onChannelRegister(ClientPacketListener handler, PacketSender sender, Minecraft client, List channels); - } - - /** - * @see C2SPlayChannelEvents#UNREGISTER - */ - - @FunctionalInterface - public interface Unregister { - void onChannelUnregister(ClientPacketListener handler, PacketSender sender, Minecraft client, List channels); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginConnectionEvents.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginConnectionEvents.java deleted file mode 100644 index e6dcfdc43..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginConnectionEvents.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.client.networking.v1; - -import com.seibel.lod.forge.fabric.api.event.Event; -import com.seibel.lod.forge.fabric.api.event.EventFactory; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; -import net.minecraft.resources.ResourceLocation; - -/** - * Offers access to events related to the connection to a server on the client while the server is processing the client's login request. - */ - -public final class ClientLoginConnectionEvents { - /** - * Event indicating a connection entered the LOGIN state, ready for registering query request handlers. - * This event may be used by mods to prepare their client side state. - * This event does not guarantee that a login attempt will be successful. - * - * @see ClientLoginNetworking#registerReceiver(ResourceLocation, ClientLoginNetworking.LoginQueryRequestHandler) - */ - public static final Event INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, client) -> { - for (Init callback : callbacks) { - callback.onLoginStart(handler, client); - } - }); - - /** - * An event for when the client has started receiving login queries. - * A client can only start receiving login queries when a server has sent the first login query. - * Vanilla servers will typically never make the client enter this login phase, but it is not a guarantee that the - * connected server is a vanilla server since a modded server or proxy may have no login queries to send to the client - * and therefore bypass the login query phase. - * If this event is fired then it is a sign that a server is not a vanilla server or the server is behind a proxy which - * is capable of handling login queries. - * - *

This event may be used to {@link ClientLoginNetworking.LoginQueryRequestHandler register login query handlers} - * which may be used to send a response to a server. - * - *

No packets should be sent when this event is invoked. - */ - public static final Event QUERY_START = EventFactory.createArrayBacked(QueryStart.class, callbacks -> (handler, client) -> { - for (QueryStart callback : callbacks) { - callback.onLoginQueryStart(handler, client); - } - }); - - /** - * An event for when the client's login process has ended due to disconnection. - * - *

No packets should be sent when this event is invoked. - */ - public static final Event DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, client) -> { - for (Disconnect callback : callbacks) { - callback.onLoginDisconnect(handler, client); - } - }); - - private ClientLoginConnectionEvents() { - } - - /** - * @see ClientLoginConnectionEvents#INIT - */ - - @FunctionalInterface - public interface Init { - void onLoginStart(ClientHandshakePacketListenerImpl handler, Minecraft client); - } - - /** - * @see ClientLoginConnectionEvents#QUERY_START - */ - - @FunctionalInterface - public interface QueryStart { - void onLoginQueryStart(ClientHandshakePacketListenerImpl handler, Minecraft client); - } - - /** - * @see ClientLoginConnectionEvents#DISCONNECT - */ - - @FunctionalInterface - public interface Disconnect { - void onLoginDisconnect(ClientHandshakePacketListenerImpl handler, Minecraft client); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginNetworking.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginNetworking.java deleted file mode 100644 index ac80b1b27..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientLoginNetworking.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.client.networking.v1; - -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import org.jetbrains.annotations.Nullable; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginNetworking; -import com.seibel.lod.forge.fabric.impl.networking.client.ClientNetworkingImpl; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; -import net.minecraft.network.Connection; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.PacketListener; -import net.minecraft.resources.ResourceLocation; - -/** - * Offers access to login stage client-side networking functionalities. - * - *

The Minecraft login protocol only allows the client to respond to a server's request, but not initiate one of its own. - * - * @see ClientPlayNetworking - * @see ServerLoginNetworking - */ - -public final class ClientLoginNetworking { - /** - * Registers a handler to a query request channel. - * A global receiver is registered to all connections, in the present and future. - * - *

If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler. - * - * @param channelName the id of the channel - * @param queryHandler the handler - * @return false if a handler is already registered to the channel - * @see ClientLoginNetworking#unregisterGlobalReceiver(ResourceLocation) - * @see ClientLoginNetworking#registerReceiver(ResourceLocation, LoginQueryRequestHandler) - */ - public static boolean registerGlobalReceiver(ResourceLocation channelName, LoginQueryRequestHandler queryHandler) { - return ClientNetworkingImpl.LOGIN.registerGlobalReceiver(channelName, queryHandler); - } - - /** - * Removes the handler of a query request channel. - * A global receiver is registered to all connections, in the present and future. - * - *

The {@code channel} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel - * @see ClientLoginNetworking#registerGlobalReceiver(ResourceLocation, LoginQueryRequestHandler) - * @see ClientLoginNetworking#unregisterReceiver(ResourceLocation) - */ - @Nullable - public static ClientLoginNetworking.LoginQueryRequestHandler unregisterGlobalReceiver(ResourceLocation channelName) { - return ClientNetworkingImpl.LOGIN.unregisterGlobalReceiver(channelName); - } - - /** - * Gets all query request channel names which global receivers are registered for. - * A global receiver is registered to all connections, in the present and future. - * - * @return all channel names which global receivers are registered for. - */ - public static Set getGlobalReceivers() { - return ClientNetworkingImpl.LOGIN.getChannels(); - } - - /** - * Registers a handler to a query request channel. - * - *

If a handler is already registered to the {@code channelName}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterReceiver(ResourceLocation)} to unregister the existing handler. - * - * @param channelName the id of the channel - * @param queryHandler the handler - * @return false if a handler is already registered to the channel name - * @throws IllegalStateException if the client is not logging in - */ - public static boolean registerReceiver(ResourceLocation channelName, LoginQueryRequestHandler queryHandler) throws IllegalStateException { - final Connection connection = ClientNetworkingImpl.getLoginConnection(); - - if (connection != null) { - final PacketListener packetListener = connection.getPacketListener(); - - if (packetListener instanceof ClientHandshakePacketListenerImpl) { - return ClientNetworkingImpl.getAddon(((ClientHandshakePacketListenerImpl) packetListener)).registerChannel(channelName, queryHandler); - } - } - - throw new IllegalStateException("Cannot register receiver while client is not logging in!"); - } - - /** - * Removes the handler of a query request channel. - * - *

The {@code channelName} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel name - * @throws IllegalStateException if the client is not logging in - */ - @Nullable - public static LoginQueryRequestHandler unregisterReceiver(ResourceLocation channelName) throws IllegalStateException { - final Connection connection = ClientNetworkingImpl.getLoginConnection(); - - if (connection != null) { - final PacketListener packetListener = connection.getPacketListener(); - - if (packetListener instanceof ClientHandshakePacketListenerImpl) { - return ClientNetworkingImpl.getAddon(((ClientHandshakePacketListenerImpl) packetListener)).unregisterChannel(channelName); - } - } - - throw new IllegalStateException("Cannot unregister receiver while client is not logging in!"); - } - - private ClientLoginNetworking() { - } - - @FunctionalInterface - public interface LoginQueryRequestHandler { - /** - * Handles an incoming query request from a server. - * - *

This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}. - * Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance. - * - *

The return value of this method is a completable future that may be used to delay the login process to the server until a task {@link CompletableFuture#isDone() is done}. - * The future should complete in reasonably time to prevent disconnection by the server. - * If your request processes instantly, you may use {@link CompletableFuture#completedFuture(Object)} to wrap your response for immediate sending. - * - * @param client the client - * @param handler the network handler that received this packet - * @param buf the payload of the packet - * @param listenerAdder listeners to be called when the response packet is sent to the server - * @return a completable future which contains the payload to respond to the server with. - * If the future contains {@code null}, then the server will be notified that the client did not understand the query. - */ - CompletableFuture<@Nullable FriendlyByteBuf> receive(Minecraft client, ClientHandshakePacketListenerImpl handler, FriendlyByteBuf buf, Consumer>> listenerAdder); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayConnectionEvents.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayConnectionEvents.java deleted file mode 100644 index ad4e16a33..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayConnectionEvents.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.client.networking.v1; - -import com.seibel.lod.forge.fabric.api.event.Event; -import com.seibel.lod.forge.fabric.api.event.EventFactory; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.resources.ResourceLocation; - -/** - * Offers access to events related to the connection to a server on a logical client. - */ - -public final class ClientPlayConnectionEvents { - /** - * Event indicating a connection entered the PLAY state, ready for registering channel handlers. - * - * @see ClientPlayNetworking#registerReceiver(ResourceLocation, ClientPlayNetworking.PlayChannelHandler) - */ - public static final Event INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, client) -> { - for (Init callback : callbacks) { - callback.onPlayInit(handler, client); - } - }); - - /** - * An event for notification when the client play network handler is ready to send packets to the server. - * - *

At this stage, the network handler is ready to send packets to the server. - * Since the client's local state has been setup. - */ - public static final Event JOIN = EventFactory.createArrayBacked(Join.class, callbacks -> (handler, sender, client) -> { - for (Join callback : callbacks) { - callback.onPlayReady(handler, sender, client); - } - }); - - /** - * An event for the disconnection of the client play network handler. - * - *

No packets should be sent when this event is invoked. - */ - public static final Event DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, client) -> { - for (Disconnect callback : callbacks) { - callback.onPlayDisconnect(handler, client); - } - }); - - private ClientPlayConnectionEvents() { - } - - - @FunctionalInterface - public interface Init { - void onPlayInit(ClientPacketListener handler, Minecraft client); - } - - - @FunctionalInterface - public interface Join { - void onPlayReady(ClientPacketListener handler, PacketSender sender, Minecraft client); - } - - - @FunctionalInterface - public interface Disconnect { - void onPlayDisconnect(ClientPacketListener handler, Minecraft client); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayNetworking.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayNetworking.java deleted file mode 100644 index 7ebcfe9c1..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/ClientPlayNetworking.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.client.networking.v1; - -import java.util.Objects; -import java.util.Set; - -import org.jetbrains.annotations.Nullable; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking; -import com.seibel.lod.forge.fabric.impl.networking.client.ClientNetworkingImpl; -import com.seibel.lod.forge.fabric.impl.networking.client.ClientPlayNetworkAddon; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.resources.ResourceLocation; - -/** - * Offers access to play stage client-side networking functionalities. - * - *

Client-side networking functionalities include receiving clientbound packets, - * sending serverbound packets, and events related to client-side network handlers. - * - *

This class should be only used on the physical client and for the logical client. - * - * @see ClientLoginNetworking - * @see ServerPlayNetworking - */ - -public final class ClientPlayNetworking { - /** - * Registers a handler to a channel. - * A global receiver is registered to all connections, in the present and future. - * - *

If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler. - * - * @param channelName the id of the channel - * @param channelHandler the handler - * @return false if a handler is already registered to the channel - * @see ClientPlayNetworking#unregisterGlobalReceiver(ResourceLocation) - * @see ClientPlayNetworking#registerReceiver(ResourceLocation, PlayChannelHandler) - */ - public static boolean registerGlobalReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) { - return ClientNetworkingImpl.PLAY.registerGlobalReceiver(channelName, channelHandler); - } - - /** - * Removes the handler of a channel. - * A global receiver is registered to all connections, in the present and future. - * - *

The {@code channel} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel - * @see ClientPlayNetworking#registerGlobalReceiver(ResourceLocation, PlayChannelHandler) - * @see ClientPlayNetworking#unregisterReceiver(ResourceLocation) - */ - @Nullable - public static PlayChannelHandler unregisterGlobalReceiver(ResourceLocation channelName) { - return ClientNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName); - } - - /** - * Gets all channel names which global receivers are registered for. - * A global receiver is registered to all connections, in the present and future. - * - * @return all channel names which global receivers are registered for. - */ - public static Set getGlobalReceivers() { - return ClientNetworkingImpl.PLAY.getChannels(); - } - - /** - * Registers a handler to a channel. - * - *

If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterReceiver(ResourceLocation)} to unregister the existing handler. - * - *

For example, if you only register a receiver using this method when a {@linkplain ClientLoginNetworking#registerGlobalReceiver(ResourceLocation, ClientLoginNetworking.LoginQueryRequestHandler)} - * login query has been received, you should use {@link ClientPlayConnectionEvents#INIT} to register the channel handler. - * - * @param channelName the id of the channel - * @return false if a handler is already registered to the channel - * @throws IllegalStateException if the client is not connected to a server - * @see ClientPlayConnectionEvents#INIT - */ - public static boolean registerReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) { - final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon(); - - if (addon != null) { - return addon.registerChannel(channelName, channelHandler); - } - - throw new IllegalStateException("Cannot register receiver while not in game!"); - } - - /** - * Removes the handler of a channel. - * - *

The {@code channelName} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel - * @throws IllegalStateException if the client is not connected to a server - */ - @Nullable - public static PlayChannelHandler unregisterReceiver(ResourceLocation channelName) throws IllegalStateException { - final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon(); - - if (addon != null) { - return addon.unregisterChannel(channelName); - } - - throw new IllegalStateException("Cannot unregister receiver while not in game!"); - } - - /** - * Gets all the channel names that the client can receive packets on. - * - * @return All the channel names that the client can receive packets on - * @throws IllegalStateException if the client is not connected to a server - */ - public static Set getReceived() throws IllegalStateException { - 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!"); - } - - /** - * Gets all channel names that the connected server declared the ability to receive a packets on. - * - * @return All the channel names the connected server declared the ability to receive a packets on - * @throws IllegalStateException if the client is not connected to a server - */ - public static Set getSendable() throws IllegalStateException { - 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!"); - } - - /** - * Checks if the connected server declared the ability to receive a packet on a specified channel name. - * - * @param channelName the channel name - * @return True if the connected server has declared the ability to receive a packet on the specified channel. - * False if the client is not in game. - */ - public static boolean canSend(ResourceLocation channelName) throws IllegalArgumentException { - // You cant send without a client player, so this is fine - if (Minecraft.getInstance().getConnection() != null) { - return ClientNetworkingImpl.getAddon(Minecraft.getInstance().getConnection()).getSendableChannels().contains(channelName); - } - - return false; - } - - /** - * Creates a packet which may be sent to a the connected server. - * - * @param channelName the channel name - * @param buf the packet byte buf which represents the payload of the packet - * @return a new packet - */ - public static Packet createC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) { - Objects.requireNonNull(channelName, "Channel name cannot be null"); - Objects.requireNonNull(buf, "Buf cannot be null"); - - return ClientNetworkingImpl.createPlayC2SPacket(channelName, buf); - } - - /** - * Gets the packet sender which sends packets to the connected server. - * - * @return the client's packet sender - * @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 (Minecraft.getInstance().getConnection() != null) { - return ClientNetworkingImpl.getAddon(Minecraft.getInstance().getConnection()); - } - - throw new IllegalStateException("Cannot get packet sender when not in game!"); - } - - /** - * Sends a packet to the connected server. - * - * @param channelName the channel of the packet - * @param buf the payload of the packet - * @throws IllegalStateException if the client is not connected to a server - */ - public static void send(ResourceLocation channelName, FriendlyByteBuf buf) throws IllegalStateException { - // You cant send without a client player, so this is fine - if (Minecraft.getInstance().getConnection() != null) { - Minecraft.getInstance().getConnection().send(createC2SPacket(channelName, buf)); - return; - } - - throw new IllegalStateException("Cannot send packets when not in game!"); - } - - private ClientPlayNetworking() { - } - - @FunctionalInterface - public interface PlayChannelHandler { - /** - * Handles an incoming packet. - * - *

This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}. - * Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance. - * - *

An example usage of this is to display an overlay message: - *

{@code
-		 * ClientPlayNetworking.registerReceiver(new Identifier("mymod", "overlay"), (client, handler, buf, responseSender) -&rt; {
-		 * 	String message = buf.readString(32767);
-		 *
-		 * 	// All operations on the server or world must be executed on the server thread
-		 * 	client.execute(() -&rt; {
-		 * 		client.inGameHud.setOverlayMessage(message, true);
-		 * 	});
-		 * });
-		 * }
- * @param client the client - * @param handler the network handler that received this packet - * @param buf the payload of the packet - * @param responseSender the packet sender - */ - void receive(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/package-info.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/package-info.java deleted file mode 100644 index 903beb181..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/client/networking/v1/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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. - */ - -/** - * The Networking API (client side), version 1. - * - *

For login stage networking see {@link net.fabricmc.fabric.api.client.networking.v1.ClientLoginNetworking}. - * For play stage networking see {@link net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking}. - * - *

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. - * - *

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 com.seibel.lod.forge.fabric.api.client.networking.v1; diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/AutoInvokingEvent.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/AutoInvokingEvent.java deleted file mode 100644 index c06415af8..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/AutoInvokingEvent.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.event; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates that this {@link Event} is auto-invoking: - * it calls the event callback implemented by a context parameter type automatically and without registration. - * - *

This means that this event can be listened to in two ways: - *

    - *
  • If the consumer is the context parameter and it implements the callback, it will be automatically invoked, don't register manually. - *
  • Otherwise, there is no invocation and the listener needs manual registration as usual. - *
- * - *

Do note that there may be more than one context parameter. - * - *

A typical use case is feature augmentation, for example to expose raw clicks to slots. - * The event callback has a slot parameter - the context parameter - and the event itself is carrying this annotation. - * All the slot needs to receive slot clicks is to implement {@code SlotClickCallback} on itself. - * It shouldn't do any explicit event registration like {@code SLOT_CLICK_EVENT.register(this::onSlotClick)}, - * otherwise it will see extraneous callback invocations. - * - *

In general, an auto-invoking event bridges the gap between the flexibility of an event with global reach, - * and the convenience of implementing an interface that gets detected automatically. - * - *

This is a documentation-only annotation, the event factory has to implement the functionality explicitly by checking the parameter type and invoking it. - * On top of adding this annotation, the event field or method should document which parameters are context parameters, - * and under which circumstances they are invoked. - */ - -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.FIELD, ElementType.METHOD }) -public @interface AutoInvokingEvent { -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/Event.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/Event.java deleted file mode 100644 index bc6dc704d..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/Event.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.event; - -import org.jetbrains.annotations.ApiStatus; - -import net.minecraft.resources.ResourceLocation; - -/** - * Base class for Fabric's event implementations. - * - * @param The listener type. - * @see EventFactory - */ -@ApiStatus.NonExtendable // Should only be extended by fabric API. -public abstract class Event { - /** - * The invoker field. This should be updated by the implementation to - * always refer to an instance containing all code that should be - * executed upon event emission. - */ - protected volatile T invoker; - - /** - * Returns the invoker instance. - * - *

An "invoker" is an object which hides multiple registered - * listeners of type T under one instance of type T, executing - * them and leaving early as necessary. - * - * @return The invoker instance. - */ - public final T invoker() { - return invoker; - } - - /** - * Register a listener to the event, in the default phase. - * Have a look at {@link #addPhaseOrdering} for an explanation of event phases. - * - * @param listener The desired listener. - */ - public abstract void register(T listener); - - /** - * The ResourceLocation of the default phase. - * Have a look at {@link EventFactory#createWithPhases} for an explanation of event phases. - */ - public static final ResourceLocation DEFAULT_PHASE = new ResourceLocation("fabric", "default"); - - /** - * Register a listener to the event for the specified phase. - * Have a look at {@link EventFactory#createWithPhases} for an explanation of event phases. - * - * @param phase ResourceLocation of the phase this listener should be registered for. It will be created if it didn't exist yet. - * @param listener The desired listener. - */ - public void register(ResourceLocation phase, T listener) { - // This is done to keep compatibility with existing Event subclasses, but they should really not be subclassing Event. - register(listener); - } - - /** - * Request that listeners registered for one phase be executed before listeners registered for another phase. - * Relying on the default phases supplied to {@link EventFactory#createWithPhases} should be preferred over manually - * registering phase ordering dependencies. - * - *

Incompatible ordering constraints such as cycles will lead to inconsistent behavior: - * some constraints will be respected and some will be ignored. If this happens, a warning will be logged. - * - * @param firstPhase The ResourceLocation of the phase that should run before the other. It will be created if it didn't exist yet. - * @param secondPhase The ResourceLocation of the phase that should run after the other. It will be created if it didn't exist yet. - */ - public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) { - // This is not abstract to avoid breaking existing Event subclasses, but they should really not be subclassing Event. - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/EventFactory.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/EventFactory.java deleted file mode 100644 index 97808e030..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/event/EventFactory.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.event; - -import java.util.function.Function; - -import net.minecraft.resources.ResourceLocation; - -import com.seibel.lod.forge.fabric.impl.base.event.EventFactoryImpl; - -/** - * Helper for creating {@link Event} classes. - */ -public final class EventFactory { - private static boolean profilingEnabled = true; - - private EventFactory() { } - - /** - * @return True if events are supposed to be profiled. - */ - public static boolean isProfilingEnabled() { - return profilingEnabled; - } - - /** - * Invalidate and re-create all existing "invoker" instances across - * events created by this EventFactory. Use this if, for instance, - * the profilingEnabled field changes. - */ - // TODO: Turn this into an event? - public static void invalidate() { - EventFactoryImpl.invalidate(); - } - - /** - * Create an "array-backed" Event instance. - * - *

If your factory simply delegates to the listeners without adding custom behavior, - * consider using {@linkplain #createArrayBacked(Class, Object, Function) the other overload} - * if performance of this event is critical. - * - * @param type The listener class type. - * @param invokerFactory The invoker factory, combining multiple listeners into one instance. - * @param The listener type. - * @return The Event instance. - */ - public static Event createArrayBacked(Class type, Function invokerFactory) { - return EventFactoryImpl.createArrayBacked(type, invokerFactory); - } - - /** - * Create an "array-backed" Event instance with a custom empty invoker, - * for an event whose {@code invokerFactory} only delegates to the listeners. - *

    - *
  • If there is no listener, the custom empty invoker will be used.
  • - *
  • If there is only one listener, that one will be used as the invoker - * and the factory will not be called.
  • - *
  • Only when there are at least two listeners will the factory be used.
  • - *
- * - *

Having a custom empty invoker (of type (...) -> {}) increases performance - * relative to iterating over an empty array; however, it only really matters - * if the event is executed thousands of times a second. - * - * @param type The listener class type. - * @param emptyInvoker The custom empty invoker. - * @param invokerFactory The invoker factory, combining multiple listeners into one instance. - * @param The listener type. - * @return The Event instance. - */ - public static Event createArrayBacked(Class type, T emptyInvoker, Function invokerFactory) { - return createArrayBacked(type, listeners -> { - if (listeners.length == 0) { - return emptyInvoker; - } else if (listeners.length == 1) { - return listeners[0]; - } else { - return invokerFactory.apply(listeners); - } - }); - } - - /** - * Create an array-backed event with a list of default phases that get invoked in order. - * Exposing the ResourceLocations of the default phases as {@code public static final} constants is encouraged. - * - *

An event phase is a named group of listeners, which may be ordered before or after other groups of listeners. - * This allows some listeners to take priority over other listeners. - * Adding separate events should be considered before making use of multiple event phases. - * - *

Phases may be freely added to events created with any of the factory functions, - * however using this function is preferred for widely used event phases. - * If more phases are necessary, discussion with the author of the Event is encouraged. - * - *

Refer to {@link Event#addPhaseOrdering} for an explanation of event phases. - * - * @param type The listener class type. - * @param invokerFactory The invoker factory, combining multiple listeners into one instance. - * @param defaultPhases The default phases of this event, in the correct order. Must contain {@link Event#DEFAULT_PHASE}. - * @param The listener type. - * @return The Event instance. - */ - public static Event createWithPhases(Class type, Function invokerFactory, ResourceLocation... defaultPhases) { - EventFactoryImpl.ensureContainsDefault(defaultPhases); - EventFactoryImpl.ensureNoDuplicates(defaultPhases); - - Event event = createArrayBacked(type, invokerFactory); - - for (int i = 1; i < defaultPhases.length; ++i) { - event.addPhaseOrdering(defaultPhases[i-1], defaultPhases[i]); - } - - return event; - } - - /** - * Get the listener object name. This can be used in debugging/profiling - * scenarios. - * - * @param handler The listener object. - * @return The listener name. - */ - public static String getHandlerName(Object handler) { - return handler.getClass().getName(); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/EntityTrackingEvents.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/EntityTrackingEvents.java deleted file mode 100644 index c369b64d8..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/EntityTrackingEvents.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import com.seibel.lod.forge.fabric.api.event.Event; -import com.seibel.lod.forge.fabric.api.event.EventFactory; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; - -/** - * Events related to a tracking entities within a player's view distance. - */ -public final class EntityTrackingEvents { - /** - * An event that is called before player starts tracking an entity. - * Typically this occurs when an entity enters a client's view distance. - * This event is called before the player's client is sent the entity's {@link Entity#getAddEntityPacket() spawn packet}. - */ - public static final Event START_TRACKING = EventFactory.createArrayBacked(StartTracking.class, callbacks -> (trackedEntity, player) -> { - for (StartTracking callback : callbacks) { - callback.onStartTracking(trackedEntity, player); - } - }); - - /** - * An event that is called after a player has stopped tracking an entity. - * The client at this point was sent a packet to {@link net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket destroy} the entity on the client. - * The entity still exists on the server. - */ - public static final Event STOP_TRACKING = EventFactory.createArrayBacked(StopTracking.class, callbacks -> (trackedEntity, player) -> { - for (StopTracking callback : callbacks) { - callback.onStopTracking(trackedEntity, player); - } - }); - - @FunctionalInterface - public interface StartTracking { - /** - * Called before an entity starts getting tracked by a player. - * - * @param trackedEntity the entity that will be tracked - * @param player the player that will track the entity - */ - void onStartTracking(Entity trackedEntity, ServerPlayer player); - } - - @FunctionalInterface - public interface StopTracking { - /** - * Called after an entity stops getting tracked by a player. - * - * @param trackedEntity the entity that is no longer being tracked - * @param player the player that is no longer tracking the entity - */ - void onStopTracking(Entity trackedEntity, ServerPlayer player); - } - - private EntityTrackingEvents() { - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/FutureListeners.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/FutureListeners.java deleted file mode 100644 index 88fee7bd1..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/FutureListeners.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import java.util.Objects; -import net.minecraft.network.FriendlyByteBuf; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.local.LocalServerChannel; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.FutureListener; -import io.netty.util.concurrent.GenericFutureListener; - -/** - * Utilities for working with netty's future listeners. - * @see FutureListener - * @see ChannelFutureListener - */ -public final class FutureListeners { - /** - * Returns a future listener that releases a packet byte buf when the buffer has been sent to a remote connection. - * - * @param buf the buffer - * @return the future listener - */ - public static ChannelFutureListener free(FriendlyByteBuf buf) { - Objects.requireNonNull(buf, "PacketByteBuf cannot be null"); - - return (future) -> { - if (!isLocalChannel(future.channel())) { - buf.release(); - } - }; - } - - /** - * Returns whether a netty channel performs local transportation, or if the message objects in the channel are directly passed than written to and read from a byte buf. - * - * @param channel the channel to check - * @return whether the channel is local - */ - public static boolean isLocalChannel(Channel channel) { - return channel instanceof LocalServerChannel || channel instanceof LocalChannel; - } - - /** - * Combines two future listeners. - * - * @param first the first future listener - * @param second the second future listener - * @param the future type of the first listener, used for casting - * @param the future type of the second listener, used for casting - * @return the combined future listener. - */ - // A, B exist just to allow casting - @SuppressWarnings("unchecked") - public static , B extends Future> GenericFutureListener> union(GenericFutureListener first, GenericFutureListener second) { - // Return an empty future listener in the case of both parameters somehow being null - if (first == null && second == null) { - return future -> { }; - } - - if (first == null) { - return second; - } - - if (second == null) { - return first; - } - - return future -> { - first.operationComplete((A) future); - second.operationComplete((B) future); - }; - } - - private FutureListeners() { - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketByteBufs.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketByteBufs.java deleted file mode 100644 index dcec0210e..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketByteBufs.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import java.util.Objects; -import net.minecraft.network.FriendlyByteBuf; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - -/** - * Helper methods for working with and creating {@link FriendlyByteBuf}s. - */ -public final class PacketByteBufs { - private static final FriendlyByteBuf EMPTY_PACKET_BYTE_BUF = new FriendlyByteBuf(Unpooled.EMPTY_BUFFER); - - /** - * Returns an empty instance of packet byte buf. - * - * @return an empty buf - */ - public static FriendlyByteBuf empty() { - return EMPTY_PACKET_BYTE_BUF; - } - - /** - * Returns a new heap memory-backed instance of packet byte buf. - * - * @return a new buf - */ - public static FriendlyByteBuf create() { - return new FriendlyByteBuf(Unpooled.buffer()); - } - - // Convenience methods for byte buf methods that return a new byte buf - - /** - * Wraps the newly created buf from {@code buf.readBytes} in a packet byte buf. - * - * @param buf the original buf - * @param length the number of bytes to transfer - * @return the transferred bytes - * @see ByteBuf#readBytes(int) - */ - public static FriendlyByteBuf readBytes(ByteBuf buf, int length) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.readBytes(length)); - } - - /** - * Wraps the newly created buf from {@code buf.readSlice} in a packet byte buf. - * - * @param buf the original buf - * @param length the size of the new slice - * @return the newly created slice - * @see ByteBuf#readSlice(int) - */ - public static FriendlyByteBuf readSlice(ByteBuf buf, int length) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.readSlice(length)); - } - - /** - * Wraps the newly created buf from {@code buf.readRetainedSlice} in a packet byte buf. - * - * @param buf the original buf - * @param length the size of the new slice - * @return the newly created slice - * @see ByteBuf#readRetainedSlice(int) - */ - public static FriendlyByteBuf readRetainedSlice(ByteBuf buf, int length) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.readRetainedSlice(length)); - } - - /** - * Wraps the newly created buf from {@code buf.copy} in a packet byte buf. - * - * @param buf the original buf - * @return a copy of the buf - * @see ByteBuf#copy() - */ - public static FriendlyByteBuf copy(ByteBuf buf) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.copy()); - } - - /** - * Wraps the newly created buf from {@code buf.copy} in a packet byte buf. - * - * @param buf the original buf - * @param index the starting index - * @param length the size of the copy - * @return a copy of the buf - * @see ByteBuf#copy(int, int) - */ - public static FriendlyByteBuf copy(ByteBuf buf, int index, int length) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.copy(index, length)); - } - - /** - * Wraps the newly created buf from {@code buf.slice} in a packet byte buf. - * - * @param buf the original buf - * @return a slice of the buf - * @see ByteBuf#slice() - */ - public static FriendlyByteBuf slice(ByteBuf buf) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.slice()); - } - - /** - * Wraps the newly created buf from {@code buf.retainedSlice} in a packet byte buf. - * - * @param buf the original buf - * @return a slice of the buf - * @see ByteBuf#retainedSlice() - */ - public static FriendlyByteBuf retainedSlice(ByteBuf buf) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.retainedSlice()); - } - - /** - * Wraps the newly created buf from {@code buf.slice} in a packet byte buf. - * - * @param buf the original buf - * @param index the starting index - * @param length the size of the copy - * @return a slice of the buf - * @see ByteBuf#slice(int, int) - */ - public static FriendlyByteBuf slice(ByteBuf buf, int index, int length) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.slice(index, length)); - } - - /** - * Wraps the newly created buf from {@code buf.retainedSlice} in a packet byte buf. - * - * @param buf the original buf - * @param index the starting index - * @param length the size of the copy - * @return a slice of the buf - * @see ByteBuf#retainedSlice(int, int) - */ - public static FriendlyByteBuf retainedSlice(ByteBuf buf, int index, int length) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.retainedSlice(index, length)); - } - - /** - * Wraps the newly created buf from {@code buf.duplicate} in a packet byte buf. - * - * @param buf the original buf - * @return a duplicate of the buf - * @see ByteBuf#duplicate() - */ - public static FriendlyByteBuf duplicate(ByteBuf buf) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.duplicate()); - } - - /** - * Wraps the newly created buf from {@code buf.retainedDuplicate} in a packet byte buf. - * - * @param buf the original buf - * @return a duplicate of the buf - * @see ByteBuf#retainedDuplicate() - */ - public static FriendlyByteBuf retainedDuplicate(ByteBuf buf) { - Objects.requireNonNull(buf, "ByteBuf cannot be null"); - - return new FriendlyByteBuf(buf.retainedDuplicate()); - } - - private PacketByteBufs() { - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketSender.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketSender.java deleted file mode 100644 index 28b23c1d5..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PacketSender.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import java.util.Objects; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.resources.ResourceLocation; -import io.netty.channel.ChannelFutureListener; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import org.jetbrains.annotations.Nullable; - -/** - * Represents something that supports sending packets to channels. - * @see PacketByteBufs - */ -public interface PacketSender { - /** - * Makes a packet for a channel. - * - * @param channelName the id of the channel - * @param buf the content of the packet - */ - Packet createPacket(ResourceLocation channelName, FriendlyByteBuf buf); - - /** - * Sends a packet. - * - * @param packet the packet - */ - void sendPacket(Packet packet); - - /** - * Sends a packet. - * - * @param packet the packet - * @param callback an optional callback to execute after the packet is sent, may be {@code null}. The callback may also accept a {@link ChannelFutureListener}. - */ - void sendPacket(Packet packet, @Nullable GenericFutureListener> callback); - - /** - * Sends a packet to a channel. - * - * @param channel the id of the channel - * @param buf the content of the packet - */ - default void sendPacket(ResourceLocation channel, FriendlyByteBuf buf) { - Objects.requireNonNull(channel, "Channel cannot be null"); - Objects.requireNonNull(buf, "Payload cannot be null"); - - this.sendPacket(this.createPacket(channel, buf)); - } - - /** - * Sends a packet to a channel. - * - * @param channel the id of the channel - * @param buf the content of the packet - * @param callback an optional callback to execute after the packet is sent, may be {@code null} - */ - // the generic future listener can accept ChannelFutureListener - default void sendPacket(ResourceLocation channel, FriendlyByteBuf buf, @Nullable GenericFutureListener> callback) { - Objects.requireNonNull(channel, "Channel cannot be null"); - Objects.requireNonNull(buf, "Payload cannot be null"); - - this.sendPacket(this.createPacket(channel, buf), callback); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PlayerLookup.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PlayerLookup.java deleted file mode 100644 index 891351ed5..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/PlayerLookup.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerPlayerConnection; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.ChunkSource; -import net.minecraft.world.phys.Vec3; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.EntityTrackerAccessor; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.ThreadedAnvilChunkStorageAccessor; - -/** - * For example, a block entity may use the methods in this class to send a packet to all clients which can see the block entity in order notify clients about a change. - * - *

The word "tracking" means that an entity/chunk on the server is known to a player's client (within in view distance) and the (block) entity should notify tracking clients of changes. - * - *

These methods should only be called on the server thread and only be used on logical a server. - */ -public final class PlayerLookup { - /** - * Gets all the players on the minecraft server. - * - *

The returned collection is immutable. - * - * @param server the server - * @return all players on the server - */ - public static Collection all(MinecraftServer server) { - Objects.requireNonNull(server, "The server cannot be null"); - - // return an immutable collection to guard against accidental removals. - if (server.getPlayerList() != null) { - return Collections.unmodifiableCollection(server.getPlayerList().getPlayers()); - } - - return Collections.emptyList(); - } - - /** - * Gets all the players in a server world. - * - *

The returned collection is immutable. - * - * @param world the server world - * @return the players in the server world - */ - public static Collection world(ServerLevel world) { - Objects.requireNonNull(world, "The world cannot be null"); - - // return an immutable collection to guard against accidental removals. - return Collections.unmodifiableCollection(world.players()); - } - - /** - * Gets all players tracking a chunk in a server world. - * - * @param world the server world - * @param pos the chunk in question - * @return the players tracking the chunk - */ - public static Collection tracking(ServerLevel world, ChunkPos pos) { - Objects.requireNonNull(world, "The world cannot be null"); - Objects.requireNonNull(pos, "The chunk pos cannot be null"); - #if MC_VERSION_1_18_1 || MC_VERSION_1_18_2 - return world.getChunkSource().chunkMap.getPlayers(pos, false); - #else - return world.getChunkSource().chunkMap.getPlayers(pos, false).toList(); - #endif - } - - /** - * Gets all players tracking an entity in a server world. - * - *

The returned collection is immutable. - * - *

Warning: If the provided entity is a player, it is not - * guaranteed by the contract that said player is included in the - * resulting stream. - * - * @param entity the entity being tracked - * @return the players tracking the entity - * @throws IllegalArgumentException if the entity is not in a server world - */ - public static Collection tracking(Entity entity) { - Objects.requireNonNull(entity, "Entity cannot be null"); - ChunkSource manager = entity.level.getChunkSource(); - - if (manager instanceof ServerChunkCache) { - ChunkMap storage = ((ServerChunkCache) manager).chunkMap; - EntityTrackerAccessor tracker = ((ThreadedAnvilChunkStorageAccessor) storage).getEntityMap().get(entity.getId()); - - // return an immutable collection to guard against accidental removals. - if (tracker != null) { - return Collections.unmodifiableCollection(tracker.getPlayersTracking() - .stream().map(ServerPlayerConnection::getPlayer).collect(Collectors.toSet())); - } - - return Collections.emptySet(); - } - - throw new IllegalArgumentException("Only supported on server worlds!"); - } - - /** - * Gets all players tracking a block entity in a server world. - * - * @param blockEntity the block entity - * @return the players tracking the block position - * @throws IllegalArgumentException if the block entity is not in a server world - */ - public static Collection tracking(BlockEntity blockEntity) { - Objects.requireNonNull(blockEntity, "BlockEntity cannot be null"); - - //noinspection ConstantConditions - IJ intrinsics don't know hasWorld == true will result in no null - if (!blockEntity.hasLevel() || blockEntity.getLevel().isClientSide()) { - throw new IllegalArgumentException("Only supported on server worlds!"); - } - - return tracking((ServerLevel) blockEntity.getLevel(), blockEntity.getBlockPos()); - } - - /** - * Gets all players tracking a block position in a server world. - * - * @param world the server world - * @param pos the block position - * @return the players tracking the block position - */ - public static Collection tracking(ServerLevel world, BlockPos pos) { - Objects.requireNonNull(pos, "BlockPos cannot be null"); - - return tracking(world, new ChunkPos(pos)); - } - - /** - * Gets all players around a position in a world. - * - *

The distance check is done in the three-dimensional space instead of in the horizontal plane. - * - * @param world the world - * @param pos the position - * @param radius the maximum distance from the position in blocks - * @return the players around the position - */ - public static Collection around(ServerLevel world, Vec3 pos, double radius) { - double radiusSq = radius * radius; - - return world(world) - .stream() - .filter((p) -> p.distanceToSqr(pos) <= radiusSq) - .collect(Collectors.toList()); - } - - /** - * Gets all players around a position in a world. - * - *

The distance check is done in the three-dimensional space instead of in the horizontal plane. - * - * @param world the world - * @param pos the position (can be a block pos) - * @param radius the maximum distance from the position in blocks - * @return the players around the position - */ - public static Collection around(ServerLevel world, Vec3i pos, double radius) { - double radiusSq = radius * radius; - - return world(world) - .stream() - .filter((p) -> p.distanceToSqr(pos.getX(), pos.getY(), pos.getZ()) <= radiusSq) - .collect(Collectors.toList()); - } - - private PlayerLookup() { - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/S2CPlayChannelEvents.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/S2CPlayChannelEvents.java deleted file mode 100644 index 9d17c21cb..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/S2CPlayChannelEvents.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import java.util.List; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import com.seibel.lod.forge.fabric.api.event.Event; -import com.seibel.lod.forge.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 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. - */ - public static final Event REGISTER = EventFactory.createArrayBacked(Register.class, callbacks -> (handler, sender, server, channels) -> { - for (Register callback : callbacks) { - callback.onChannelRegister(handler, sender, server, channels); - } - }); - - /** - * An event for the server play network handler receiving an update indicating the connected client'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 = EventFactory.createArrayBacked(Unregister.class, callbacks -> (handler, sender, server, channels) -> { - for (Unregister callback : callbacks) { - callback.onChannelUnregister(handler, sender, server, channels); - } - }); - - private S2CPlayChannelEvents() { - } - - /** - * @see S2CPlayChannelEvents#REGISTER - */ - @FunctionalInterface - public interface Register { - void onChannelRegister(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server, List channels); - } - - /** - * @see S2CPlayChannelEvents#UNREGISTER - */ - @FunctionalInterface - public interface Unregister { - void onChannelUnregister(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server, List channels); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginConnectionEvents.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginConnectionEvents.java deleted file mode 100644 index 20683c8fa..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginConnectionEvents.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginPacketListenerImpl; -import com.seibel.lod.forge.fabric.api.event.Event; -import com.seibel.lod.forge.fabric.api.event.EventFactory; - -/** - * Offers access to events related to the connection to a client on a logical server while a client is logging in. - */ -public final class ServerLoginConnectionEvents { - /** - * Event indicating a connection entered the LOGIN state, ready for registering query response handlers. - * - * @see ServerLoginNetworking#registerReceiver(ServerLoginPacketListenerImpl, ResourceLocation, ServerLoginNetworking.LoginQueryResponseHandler) - */ - public static final Event INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, server) -> { - for (Init callback : callbacks) { - callback.onLoginInit(handler, server); - } - }); - - /** - * An event for the start of login queries of the server login network handler. - * This event may be used to register {@link ServerLoginNetworking.LoginQueryResponseHandler login query response handlers} - * using {@link ServerLoginNetworking#registerReceiver(ServerLoginPacketListenerImpl, ResourceLocation, ServerLoginNetworking.LoginQueryResponseHandler)} - * since this event is fired just before the first login query response is processed. - * - *

You may send login queries to the connected client using the provided {@link PacketSender}. - */ - public static final Event QUERY_START = EventFactory.createArrayBacked(QueryStart.class, callbacks -> (handler, server, sender, synchronizer) -> { - for (QueryStart callback : callbacks) { - callback.onLoginStart(handler, server, sender, synchronizer); - } - }); - - /** - * An event for the disconnection of the server login network handler. - * - *

No packets should be sent when this event is invoked. - */ - public static final Event DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, server) -> { - for (Disconnect callback : callbacks) { - callback.onLoginDisconnect(handler, server); - } - }); - - private ServerLoginConnectionEvents() { - } - - /** - * @see ServerLoginConnectionEvents#INIT - */ - @FunctionalInterface - public interface Init { - void onLoginInit(ServerLoginPacketListenerImpl handler, MinecraftServer server); - } - - /** - * @see ServerLoginConnectionEvents#QUERY_START - */ - @FunctionalInterface - public interface QueryStart { - void onLoginStart(ServerLoginPacketListenerImpl handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer); - } - - /** - * @see ServerLoginConnectionEvents#DISCONNECT - */ - @FunctionalInterface - public interface Disconnect { - void onLoginDisconnect(ServerLoginPacketListenerImpl handler, MinecraftServer server); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginNetworking.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginNetworking.java deleted file mode 100644 index 8ca4a24ed..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerLoginNetworking.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Future; - -import org.jetbrains.annotations.Nullable; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginPacketListenerImpl; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientLoginNetworking; -import com.seibel.lod.forge.fabric.impl.networking.server.ServerNetworkingImpl; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.ServerLoginNetworkHandlerAccessor; - -/** - * Offers access to login stage server-side networking functionalities. - * - *

Server-side networking functionalities include receiving serverbound query responses and sending clientbound query requests. - * - * @see ServerPlayNetworking - * @see ClientLoginNetworking - */ -public final class ServerLoginNetworking { - /** - * Registers a handler to a query response channel. - * A global receiver is registered to all connections, in the present and future. - * - *

If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler. - * - * @param channelName the id of the channel - * @param channelHandler the handler - * @return false if a handler is already registered to the channel - * @see ServerLoginNetworking#unregisterGlobalReceiver(ResourceLocation) - * @see ServerLoginNetworking#registerReceiver(ServerLoginPacketListenerImpl, ResourceLocation, LoginQueryResponseHandler) - */ - public static boolean registerGlobalReceiver(ResourceLocation channelName, LoginQueryResponseHandler channelHandler) { - return ServerNetworkingImpl.LOGIN.registerGlobalReceiver(channelName, channelHandler); - } - - /** - * Removes the handler of a query response channel. - * A global receiver is registered to all connections, in the present and future. - * - *

The {@code channel} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel - * @see ServerLoginNetworking#registerGlobalReceiver(ResourceLocation, LoginQueryResponseHandler) - * @see ServerLoginNetworking#unregisterReceiver(ServerLoginPacketListenerImpl, ResourceLocation) - */ - @Nullable - public static ServerLoginNetworking.LoginQueryResponseHandler unregisterGlobalReceiver(ResourceLocation channelName) { - return ServerNetworkingImpl.LOGIN.unregisterGlobalReceiver(channelName); - } - - /** - * Gets all channel names which global receivers are registered for. - * A global receiver is registered to all connections, in the present and future. - * - * @return all channel names which global receivers are registered for. - */ - public static Set getGlobalReceivers() { - return ServerNetworkingImpl.LOGIN.getChannels(); - } - - /** - * Registers a handler to a query response channel. - * - *

If a handler is already registered to the {@code channelName}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterReceiver(ServerLoginPacketListenerImpl, ResourceLocation)} to unregister the existing handler. - * - * @param networkHandler the handler - * @param channelName the id of the channel - * @param responseHandler the handler - * @return false if a handler is already registered to the channel name - */ - public static boolean registerReceiver(ServerLoginPacketListenerImpl networkHandler, ResourceLocation channelName, LoginQueryResponseHandler responseHandler) { - Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - - return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, responseHandler); - } - - /** - * Removes the handler of a query response channel. - * - *

The {@code channelName} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel name - */ - @Nullable - public static ServerLoginNetworking.LoginQueryResponseHandler unregisterReceiver(ServerLoginPacketListenerImpl networkHandler, ResourceLocation channelName) { - Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - - return ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName); - } - - // Helper methods - - /** - * Returns the Minecraft Server of a server login network handler. - * - * @param handler the server login network handler - */ - public static MinecraftServer getServer(ServerLoginPacketListenerImpl handler) { - Objects.requireNonNull(handler, "Network handler cannot be null"); - - return ((ServerLoginNetworkHandlerAccessor) handler).getServer(); - } - - private ServerLoginNetworking() { - } - - @FunctionalInterface - public interface LoginQueryResponseHandler { - /** - * Handles an incoming query response from a client. - * - *

This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}. - * Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance. - * - *

Whether the client understood the query should be checked before reading from the payload of the packet. - * @param server the server - * @param handler the network handler that received this packet, representing the player/client who sent the response - * @param understood whether the client understood the packet - * @param buf the payload of the packet - * @param synchronizer the synchronizer which may be used to delay log-in till a {@link Future} is completed. - * @param responseSender the packet sender - */ - void receive(MinecraftServer server, ServerLoginPacketListenerImpl handler, boolean understood, FriendlyByteBuf buf, LoginSynchronizer synchronizer, PacketSender responseSender); - } - - /** - * Allows blocking client log-in until all all futures passed into {@link LoginSynchronizer#waitFor(Future)} are completed. - * - * @apiNote this interface is not intended to be implemented by users of api. - */ - @FunctionalInterface - public interface LoginSynchronizer { - /** - * Allows blocking client log-in until the {@code future} is {@link Future#isDone() done}. - * - *

Since packet reception happens on netty's event loops, this allows handlers to - * perform logic on the Server Thread, etc. For instance, a handler can prepare an - * upcoming query request or check necessary login data on the server thread.

- * - *

Here is an example where the player log-in is blocked so that a credential check and - * building of a followup query request can be performed properly on the logical server - * thread before the player successfully logs in: - *

{@code
-		 * ServerLoginNetworking.registerGlobalReceiver(CHECK_CHANNEL, (server, handler, understood, buf, synchronizer, responseSender) -> {
-		 * 	if (!understood) {
-		 * 		handler.disconnect(new LiteralText("Only accept clients that can check!"));
-		 * 		return;
-		 * 	}
-		 *
-		 * 	String checkMessage = buf.readString(32767);
-		 *
-		 * 	// Just send the CompletableFuture returned by the server's submit method
-		 * 	synchronizer.waitFor(server.submit(() -> {
-		 * 		LoginInfoChecker checker = LoginInfoChecker.get(server);
-		 *
-		 * 		if (!checker.check(handler.getConnectionInfo(), checkMessage)) {
-		 * 			handler.disconnect(new LiteralText("Invalid credentials!"));
-		 * 			return;
-		 * 		}
-		 *
-		 * 		responseSender.send(UPCOMING_CHECK, checker.buildSecondQueryPacket(handler, checkMessage));
-		 * 	}));
-		 * });
-		 * }
- * Usually it is enough to pass the return value for {@link net.minecraft.util.thread.BlockableEventLoop#submit(Runnable)} for {@code future}.

- * - * @param future the future that must be done before the player can log in - */ - void waitFor(Future future); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayConnectionEvents.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayConnectionEvents.java deleted file mode 100644 index ad2134761..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayConnectionEvents.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import com.seibel.lod.forge.fabric.api.event.Event; -import com.seibel.lod.forge.fabric.api.event.EventFactory; - -/** - * Offers access to events related to the connection to a client on a logical server while a client is in game. - */ -public final class ServerPlayConnectionEvents { - /** - * Event indicating a connection entered the PLAY state, ready for registering channel handlers. - * - * @see ServerPlayNetworking#registerReceiver(ServerGamePacketListenerImpl, ResourceLocation, ServerPlayNetworking.PlayChannelHandler) - */ - public static final Event INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, server) -> { - for (Init callback : callbacks) { - callback.onPlayInit(handler, server); - } - }); - - /** - * An event for notification when the server play network handler is ready to send packets to the client. - * - *

At this stage, the network handler is ready to send packets to the client. - */ - public static final Event JOIN = EventFactory.createArrayBacked(Join.class, callbacks -> (handler, sender, server) -> { - for (Join callback : callbacks) { - callback.onPlayReady(handler, sender, server); - } - }); - - /** - * An event for the disconnection of the server play network handler. - * - *

No packets should be sent when this event is invoked. - */ - public static final Event DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, server) -> { - for (Disconnect callback : callbacks) { - callback.onPlayDisconnect(handler, server); - } - }); - - private ServerPlayConnectionEvents() { - } - - @FunctionalInterface - public interface Init { - void onPlayInit(ServerGamePacketListenerImpl handler, MinecraftServer server); - } - - @FunctionalInterface - public interface Join { - void onPlayReady(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server); - } - - @FunctionalInterface - public interface Disconnect { - void onPlayDisconnect(ServerGamePacketListenerImpl handler, MinecraftServer server); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayNetworking.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayNetworking.java deleted file mode 100644 index 5e27f260d..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/ServerPlayNetworking.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.networking.v1; - -import java.util.Objects; -import java.util.Set; - -import org.jetbrains.annotations.Nullable; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayNetworking; -import com.seibel.lod.forge.fabric.impl.networking.server.ServerNetworkingImpl; - -/** - * Offers access to play stage server-side networking functionalities. - * - *

Server-side networking functionalities include receiving serverbound packets, sending clientbound packets, and events related to server-side network handlers. - * - *

This class should be only used for the logical server. - * - * @see ServerLoginNetworking - * @see ClientPlayNetworking - */ -public final class ServerPlayNetworking { - /** - * Registers a handler to a channel. - * A global receiver is registered to all connections, in the present and future. - * - *

If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterReceiver(ServerGamePacketListenerImpl, ResourceLocation)} to unregister the existing handler. - * - * @param channelName the id of the channel - * @param channelHandler the handler - * @return false if a handler is already registered to the channel - * @see ServerPlayNetworking#unregisterGlobalReceiver(ResourceLocation) - * @see ServerPlayNetworking#registerReceiver(ServerGamePacketListenerImpl, ResourceLocation, PlayChannelHandler) - */ - public static boolean registerGlobalReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) { - return ServerNetworkingImpl.PLAY.registerGlobalReceiver(channelName, channelHandler); - } - - /** - * Removes the handler of a channel. - * A global receiver is registered to all connections, in the present and future. - * - *

The {@code channel} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel - * @see ServerPlayNetworking#registerGlobalReceiver(ResourceLocation, PlayChannelHandler) - * @see ServerPlayNetworking#unregisterReceiver(ServerGamePacketListenerImpl, ResourceLocation) - */ - @Nullable - public static PlayChannelHandler unregisterGlobalReceiver(ResourceLocation channelName) { - return ServerNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName); - } - - /** - * Gets all channel names which global receivers are registered for. - * A global receiver is registered to all connections, in the present and future. - * - * @return all channel names which global receivers are registered for. - */ - public static Set getGlobalReceivers() { - return ServerNetworkingImpl.PLAY.getChannels(); - } - - /** - * Registers a handler to a channel. - * This method differs from {@link ServerPlayNetworking#registerGlobalReceiver(ResourceLocation, PlayChannelHandler)} since - * the channel handler will only be applied to the player represented by the {@link ServerGamePacketListenerImpl}. - * - *

For example, if you only register a receiver using this method when a {@linkplain ServerLoginNetworking#registerGlobalReceiver(ResourceLocation, ServerLoginNetworking.LoginQueryResponseHandler)} - * login response has been received, you should use {@link ServerPlayConnectionEvents#INIT} to register the channel handler. - * - *

If a handler is already registered to the {@code channelName}, this method will return {@code false}, and no change will be made. - * Use {@link #unregisterReceiver(ServerGamePacketListenerImpl, ResourceLocation)} to unregister the existing handler. - * - * @param networkHandler the handler - * @param channelName the id of the channel - * @param channelHandler the handler - * @return false if a handler is already registered to the channel name - * @see ServerPlayConnectionEvents#INIT - */ - public static boolean registerReceiver(ServerGamePacketListenerImpl networkHandler, ResourceLocation channelName, PlayChannelHandler channelHandler) { - Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - - return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, channelHandler); - } - - /** - * Removes the handler of a channel. - * - *

The {@code channelName} is guaranteed not to have a handler after this call. - * - * @param channelName the id of the channel - * @return the previous handler, or {@code null} if no handler was bound to the channel name - */ - @Nullable - public static PlayChannelHandler unregisterReceiver(ServerGamePacketListenerImpl networkHandler, ResourceLocation channelName) { - Objects.requireNonNull(networkHandler, "Network handler cannot be null"); - - return ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName); - } - - /** - * Gets all the channel names that the server can receive packets on. - * - * @param player the player - * @return All the channel names that the server can receive packets on - */ - public static Set getReceived(ServerPlayer player) { - Objects.requireNonNull(player, "Server player entity cannot be null"); - - return getReceived(player.connection); - } - - /** - * Gets all the channel names that the server can receive packets on. - * - * @param handler the network handler - * @return All the channel names that the server can receive packets on - */ - public static Set getReceived(ServerGamePacketListenerImpl handler) { - Objects.requireNonNull(handler, "Server play network handler cannot be null"); - - return ServerNetworkingImpl.getAddon(handler).getReceivableChannels(); - } - - /** - * Gets all channel names that the connected client declared the ability to receive a packets on. - * - * @param player the player - * @return All the channel names the connected client declared the ability to receive a packets on - */ - public static Set getSendable(ServerPlayer player) { - Objects.requireNonNull(player, "Server player entity cannot be null"); - - return getSendable(player.connection); - } - - /** - * Gets all channel names that a the connected client declared the ability to receive a packets on. - * - * @param handler the network handler - * @return True if the connected client has declared the ability to receive a packet on the specified channel - */ - public static Set getSendable(ServerGamePacketListenerImpl handler) { - Objects.requireNonNull(handler, "Server play network handler cannot be null"); - - return ServerNetworkingImpl.getAddon(handler).getSendableChannels(); - } - - /** - * Checks if the connected client declared the ability to receive a packet on a specified channel name. - * - * @param player the player - * @param channelName the channel name - * @return True if the connected client has declared the ability to receive a packet on the specified channel - */ - public static boolean canSend(ServerPlayer player, ResourceLocation channelName) { - Objects.requireNonNull(player, "Server player entity cannot be null"); - - return canSend(player.connection, channelName); - } - - /** - * Checks if the connected client declared the ability to receive a packet on a specified channel name. - * - * @param handler the network handler - * @param channelName the channel name - * @return True if the connected client has declared the ability to receive a packet on the specified channel - */ - public static boolean canSend(ServerGamePacketListenerImpl handler, ResourceLocation channelName) { - Objects.requireNonNull(handler, "Server play network handler cannot be null"); - Objects.requireNonNull(channelName, "Channel name cannot be null"); - - return ServerNetworkingImpl.getAddon(handler).getSendableChannels().contains(channelName); - } - - /** - * Creates a packet which may be sent to a the connected client. - * - * @param channelName the channel name - * @param buf the packet byte buf which represents the payload of the packet - * @return a new packet - */ - public static Packet createS2CPacket(ResourceLocation channelName, FriendlyByteBuf buf) { - Objects.requireNonNull(channelName, "Channel cannot be null"); - Objects.requireNonNull(buf, "Buf cannot be null"); - - return ServerNetworkingImpl.createPlayC2SPacket(channelName, buf); - } - - /** - * Gets the packet sender which sends packets to the connected client. - * - * @param player the player - * @return the packet sender - */ - public static PacketSender getSender(ServerPlayer player) { - Objects.requireNonNull(player, "Server player entity cannot be null"); - - return getSender(player.connection); - } - - /** - * Gets the packet sender which sends packets to the connected client. - * - * @param handler the network handler, representing the connection to the player/client - * @return the packet sender - */ - public static PacketSender getSender(ServerGamePacketListenerImpl handler) { - Objects.requireNonNull(handler, "Server play network handler cannot be null"); - - return ServerNetworkingImpl.getAddon(handler); - } - - /** - * Sends a packet to a player. - * - * @param player the player to send the packet to - * @param channelName the channel of the packet - * @param buf the payload of the packet. - */ - public static void send(ServerPlayer player, ResourceLocation channelName, FriendlyByteBuf buf) { - Objects.requireNonNull(player, "Server player entity cannot be null"); - Objects.requireNonNull(channelName, "Channel name cannot be null"); - Objects.requireNonNull(buf, "Packet byte buf cannot be null"); - - player.connection.send(createS2CPacket(channelName, buf)); - } - - // Helper methods - - /** - * Returns the Minecraft Server of a server play network handler. - * - * @param handler the server play network handler - */ - public static MinecraftServer getServer(ServerGamePacketListenerImpl handler) { - Objects.requireNonNull(handler, "Network handler cannot be null"); - - return handler.player.server; - } - - private ServerPlayNetworking() { - } - - @FunctionalInterface - public interface PlayChannelHandler { - /** - * Handles an incoming packet. - * - *

This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}. - * Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft server instance. - * - *

An example usage of this is to create an explosion where the player is looking: - *

{@code
-		 * ServerPlayNetworking.registerReceiver(new Identifier("mymod", "boom"), (server, player, handler, buf, responseSender) -&rt; {
-		 * 	boolean fire = buf.readBoolean();
-		 *
-		 * 	// All operations on the server or world must be executed on the server thread
-		 * 	server.execute(() -&rt; {
-		 * 		ModPacketHandler.createExplosion(player, fire);
-		 * 	});
-		 * });
-		 * }
- * @param server the server - * @param player the player - * @param handler the network handler that received this packet, representing the player/client who sent the packet - * @param buf the payload of the packet - * @param responseSender the packet sender - */ - void receive(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/package-info.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/package-info.java deleted file mode 100644 index 1746b78ca..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/networking/v1/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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. - */ - -/** - * The Networking API, version 1. - * - *

For login stage networking see {@link net.fabricmc.fabric.api.networking.v1.ServerLoginNetworking}. - * For play stage networking see {@link net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking}. - * - *

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. - * - *

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 com.seibel.lod.forge.fabric.api.networking.v1; diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/BooleanFunction.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/BooleanFunction.java deleted file mode 100644 index 8e5ebf2d5..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/BooleanFunction.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.util; - -/** - * Represents a function that accepts an boolean-valued argument and produces a result. - * - *

This is the {@code boolean}-consuming primitive specialization for {@link java.util.function.Function}. - */ -@FunctionalInterface -public interface BooleanFunction { - /** - * Applies this function to the given argument. - * - * @param value the function argument - * @return the function result - */ - R apply(boolean value); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/NbtType.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/NbtType.java deleted file mode 100644 index f4a61fb75..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/NbtType.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.util; - -/** - * NBT type ID constants. Useful for filtering by value type in a few cases. - * - *

For the current list of types, check with {@link NbtElement#TYPES}. - * - * @see NbtCompound#contains(String, int) - * @see net.minecraft.nbt.NbtTypes#byId(int) - */ -public final class NbtType { - public static final int END = 0; - public static final int BYTE = 1; - public static final int SHORT = 2; - public static final int INT = 3; - public static final int LONG = 4; - public static final int FLOAT = 5; - public static final int DOUBLE = 6; - public static final int BYTE_ARRAY = 7; - public static final int STRING = 8; - public static final int LIST = 9; - public static final int COMPOUND = 10; - public static final int INT_ARRAY = 11; - public static final int LONG_ARRAY = 12; - - /** - * Any numeric value: byte, short, int, long, float, double. - * - * @see NbtCompound#contains(String, int) - */ - public static final int NUMBER = 99; - - private NbtType() { } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/TriState.java b/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/TriState.java deleted file mode 100644 index 4a24f30ea..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/api/util/TriState.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.api.util; - -import java.util.Objects; -import java.util.Optional; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -import org.jetbrains.annotations.Nullable; - -/** - * Represents a boolean value which can be true, false or refer to a default value. - */ -public enum TriState { - /** - * Represents the boolean value of {@code false}. - */ - FALSE, - /** - * Represents a value that refers to a "default" value, often as a fallback. - */ - DEFAULT, - /** - * Represents the boolean value of {@code true}. - */ - TRUE; - - /** - * Gets the corresponding tri-state from a boolean value. - * - * @param bool the boolean value - * @return {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean. - */ - public static TriState of(boolean bool) { - return bool ? TRUE : FALSE; - } - - /** - * Gets a tri-state from a nullable boxed boolean. - * - * @param bool the boolean value - * @return {@link TriState#DEFAULT} if {@code null}. - * Otherwise {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean. - */ - public static TriState of(@Nullable Boolean bool) { - return bool == null ? DEFAULT : of(bool.booleanValue()); - } - - /** - * Gets the value of the tri-state. - * - * @return true if the tri-state is {@link TriState#TRUE}. - * Otherwise false. - */ - public boolean get() { - return this == TRUE; - } - - /** - * Gets the value of the tri-state as a boxed, nullable boolean. - * - * @return {@code null} if {@link TriState#DEFAULT}. - * Otherwise {@code true} if {@link TriState#TRUE} or {@code false} if {@link TriState#FALSE}. - */ - @Nullable - public Boolean getBoxed() { - return this == DEFAULT ? null : this.get(); - } - - /** - * Gets the value of this tri-state. - * If the value is {@link TriState#DEFAULT} then use the supplied value. - * - * @param value the value to fallback to - * @return the value of the tri-state or the supplied value if {@link TriState#DEFAULT}. - */ - public boolean orElse(boolean value) { - return this == DEFAULT ? value : this.get(); - } - - /** - * Gets the value of this tri-state. - * If the value is {@link TriState#DEFAULT} then use the supplied value. - * - * @param supplier the supplier used to get the value to fallback to - * @return the value of the tri-state or the value of the supplier if the tri-state is {@link TriState#DEFAULT}. - */ - public boolean orElseGet(BooleanSupplier supplier) { - return this == DEFAULT ? supplier.getAsBoolean() : this.get(); - } - - /** - * Maps the boolean value of this tri-state if it is {@link TriState#TRUE} or {@link TriState#FALSE}. - * - * @param mapper the mapper to use - * @param the type of object being supplier by the mapper - * @return an optional containing the mapped value; {@link Optional#empty()} if the tri-state is {@link TriState#DEFAULT} or the value provided by the mapper is {@code null}. - */ - public Optional map(BooleanFunction<@Nullable ? extends T> mapper) { - Objects.requireNonNull(mapper, "Mapper function cannot be null"); - - if (this == DEFAULT) { - return Optional.empty(); - } - - return Optional.ofNullable(mapper.apply(this.get())); - } - - /** - * Gets the value of this tri-state, or throws an exception if this tri-state's value is {@link TriState#DEFAULT}. - * - * @param exceptionSupplier the supplying function that produces an exception to be thrown - * @param Type of the exception to be thrown - * @return the value - * @throws X if the value is {@link TriState#DEFAULT} - */ - public boolean orElseThrow(Supplier exceptionSupplier) throws X { - if (this != DEFAULT) { - return this.get(); - } - - throw exceptionSupplier.get(); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/ArrayBackedEvent.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/ArrayBackedEvent.java deleted file mode 100644 index 276112496..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/ArrayBackedEvent.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.base.event; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; - -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; - -import net.minecraft.resources.ResourceLocation; - -import com.seibel.lod.forge.fabric.api.event.Event; - -class ArrayBackedEvent extends Event { - static final Logger LOGGER = LoggerFactory.getLogger("fabric-api-base"); - - private final Function invokerFactory; - private final Object lock = new Object(); - private T[] handlers; - /** - * Registered event phases. - */ - private final Map> phases = new LinkedHashMap<>(); - /** - * Phases sorted in the correct dependency order. - */ - private final List> sortedPhases = new ArrayList<>(); - - @SuppressWarnings("unchecked") - ArrayBackedEvent(Class type, Function invokerFactory) { - this.invokerFactory = invokerFactory; - this.handlers = (T[]) Array.newInstance(type, 0); - update(); - } - - void update() { - this.invoker = invokerFactory.apply(handlers); - } - - @Override - public void register(T listener) { - register(DEFAULT_PHASE, listener); - } - - @Override - public void register(ResourceLocation phaseResourceLocation, T listener) { - Objects.requireNonNull(phaseResourceLocation, "Tried to register a listener for a null phase!"); - Objects.requireNonNull(listener, "Tried to register a null listener!"); - - synchronized (lock) { - getOrCreatePhase(phaseResourceLocation, true).addListener(listener); - rebuildInvoker(handlers.length + 1); - } - } - - private EventPhaseData getOrCreatePhase(ResourceLocation id, boolean sortIfCreate) { - EventPhaseData phase = phases.get(id); - - if (phase == null) { - phase = new EventPhaseData<>(id, handlers.getClass().getComponentType()); - phases.put(id, phase); - sortedPhases.add(phase); - - if (sortIfCreate) { - PhaseSorting.sortPhases(sortedPhases); - } - } - - return phase; - } - - private void rebuildInvoker(int newLength) { - // Rebuild handlers. - if (sortedPhases.size() == 1) { - // Special case with a single phase: use the array of the phase directly. - handlers = sortedPhases.get(0).listeners; - } else { - @SuppressWarnings("unchecked") - T[] newHandlers = (T[]) Array.newInstance(handlers.getClass().getComponentType(), newLength); - int newHandlersIndex = 0; - - for (EventPhaseData existingPhase : sortedPhases) { - int length = existingPhase.listeners.length; - System.arraycopy(existingPhase.listeners, 0, newHandlers, newHandlersIndex, length); - newHandlersIndex += length; - } - - handlers = newHandlers; - } - - // Rebuild invoker. - update(); - } - - @Override - public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) { - Objects.requireNonNull(firstPhase, "Tried to add an ordering for a null phase."); - Objects.requireNonNull(secondPhase, "Tried to add an ordering for a null phase."); - if (firstPhase.equals(secondPhase)) throw new IllegalArgumentException("Tried to add a phase that depends on itself."); - - synchronized (lock) { - EventPhaseData first = getOrCreatePhase(firstPhase, false); - EventPhaseData second = getOrCreatePhase(secondPhase, false); - first.subsequentPhases.add(second); - second.previousPhases.add(first); - PhaseSorting.sortPhases(this.sortedPhases); - rebuildInvoker(handlers.length); - } - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventFactoryImpl.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventFactoryImpl.java deleted file mode 100644 index cfe5c86ba..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventFactoryImpl.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.base.event; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import net.minecraft.resources.ResourceLocation; - -import com.seibel.lod.forge.fabric.api.event.Event; - -public final class EventFactoryImpl { - private static final List> ARRAY_BACKED_EVENTS = new ArrayList<>(); - - private EventFactoryImpl() { } - - public static void invalidate() { - ARRAY_BACKED_EVENTS.forEach(ArrayBackedEvent::update); - } - - public static Event createArrayBacked(Class type, Function invokerFactory) { - ArrayBackedEvent event = new ArrayBackedEvent<>(type, invokerFactory); - ARRAY_BACKED_EVENTS.add(event); - return event; - } - - public static void ensureContainsDefault(ResourceLocation[] defaultPhases) { - for (ResourceLocation id : defaultPhases) { - if (id.equals(Event.DEFAULT_PHASE)) { - return; - } - } - - throw new IllegalArgumentException("The event phases must contain Event.DEFAULT_PHASE."); - } - - public static void ensureNoDuplicates(ResourceLocation[] defaultPhases) { - for (int i = 0; i < defaultPhases.length; ++i) { - for (int j = i+1; j < defaultPhases.length; ++j) { - if (defaultPhases[i].equals(defaultPhases[j])) { - throw new IllegalArgumentException("Duplicate event phase: " + defaultPhases[i]); - } - } - } - } - - // Code originally by sfPlayer1. - // Unfortunately, it's slightly slower than just passing an empty array in the first place. - private static T buildEmptyInvoker(Class handlerClass, Function invokerSetup) { - // find the functional interface method - Method funcIfMethod = null; - - for (Method m : handlerClass.getMethods()) { - if ((m.getModifiers() & (Modifier.STRICT | Modifier.PRIVATE)) == 0) { - if (funcIfMethod != null) { - throw new IllegalStateException("Multiple virtual methods in " + handlerClass + "; cannot build empty invoker!"); - } - - funcIfMethod = m; - } - } - - if (funcIfMethod == null) { - throw new IllegalStateException("No virtual methods in " + handlerClass + "; cannot build empty invoker!"); - } - - Object defValue = null; - - try { - // concert to mh, determine its type without the "this" reference - MethodHandle target = MethodHandles.lookup().unreflect(funcIfMethod); - MethodType type = target.type().dropParameterTypes(0, 1); - - if (type.returnType() != void.class) { - // determine default return value by invoking invokerSetup.apply(T[0]) with all-jvm-default args (null for refs, false for boolean, etc.) - // explicitCastArguments is being used to cast Object=null to the jvm default value for the correct type - - // construct method desc (TLjava/lang/Object;Ljava/lang/Object;...)R where T = invoker ref ("this"), R = invoker ret type and args 1+ are Object for each non-"this" invoker arg - MethodType objTargetType = MethodType.genericMethodType(type.parameterCount()).changeReturnType(type.returnType()).insertParameterTypes(0, target.type().parameterType(0)); - // explicit cast to translate to the invoker args from Object to their real type, inferring jvm default values - MethodHandle objTarget = MethodHandles.explicitCastArguments(target, objTargetType); - - // build invocation args with 0 = "this", 1+ = null - Object[] args = new Object[target.type().parameterCount()]; - //noinspection unchecked - args[0] = invokerSetup.apply((T[]) Array.newInstance(handlerClass, 0)); - - // retrieve default by invoking invokerSetup.apply(T[0]).targetName(def,def,...) - defValue = objTarget.invokeWithArguments(args); - } - } catch (Throwable t) { - throw new RuntimeException(t); - } - - final Object returnValue = defValue; - //noinspection unchecked - return (T) Proxy.newProxyInstance(EventFactoryImpl.class.getClassLoader(), new Class[]{handlerClass}, - (proxy, method, args) -> returnValue); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventPhaseData.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventPhaseData.java deleted file mode 100644 index 5c2eeeec7..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/EventPhaseData.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.base.event; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import net.minecraft.resources.ResourceLocation; - -/** - * Data of an {@link ArrayBackedEvent} phase. - */ -class EventPhaseData { - final ResourceLocation id; - T[] listeners; - final List> subsequentPhases = new ArrayList<>(); - final List> previousPhases = new ArrayList<>(); - int visitStatus = 0; // 0: not visited, 1: visiting, 2: visited - - @SuppressWarnings("unchecked") - EventPhaseData(ResourceLocation id, Class listenerClass) { - this.id = id; - this.listeners = (T[]) Array.newInstance(listenerClass, 0); - } - - void addListener(T listener) { - int oldLength = listeners.length; - listeners = Arrays.copyOf(listeners, oldLength + 1); - listeners[oldLength] = listener; - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/PhaseSorting.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/PhaseSorting.java deleted file mode 100644 index 8cb24fa68..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/base/event/PhaseSorting.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.base.event; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; - -import com.google.common.annotations.VisibleForTesting; -import org.jetbrains.annotations.ApiStatus; - -/** - * Contains phase-sorting logic for {@link ArrayBackedEvent}. - */ -@ApiStatus.Internal -public class PhaseSorting { - @VisibleForTesting - public static boolean ENABLE_CYCLE_WARNING = true; - - /** - * Deterministically sort a list of phases. - * 1) Compute phase SCCs (i.e. cycles). - * 2) Sort phases by id within SCCs. - * 3) Sort SCCs with respect to each other by respecting constraints, and by id in case of a tie. - */ - static void sortPhases(List> sortedPhases) { - // FIRST KOSARAJU SCC VISIT - List> toposort = new ArrayList<>(sortedPhases.size()); - - for (EventPhaseData phase : sortedPhases) { - forwardVisit(phase, null, toposort); - } - - clearStatus(toposort); - Collections.reverse(toposort); - - // SECOND KOSARAJU SCC VISIT - Map, PhaseScc> phaseToScc = new IdentityHashMap<>(); - - for (EventPhaseData phase : toposort) { - if (phase.visitStatus == 0) { - List> sccPhases = new ArrayList<>(); - // Collect phases in SCC. - backwardVisit(phase, sccPhases); - // Sort phases by id. - sccPhases.sort(Comparator.comparing(p -> p.id)); - // Mark phases as belonging to this SCC. - PhaseScc scc = new PhaseScc<>(sccPhases); - - for (EventPhaseData phaseInScc : sccPhases) { - phaseToScc.put(phaseInScc, scc); - } - } - } - - clearStatus(toposort); - - // Build SCC graph - for (PhaseScc scc : phaseToScc.values()) { - for (EventPhaseData phase : scc.phases) { - for (EventPhaseData subsequentPhase : phase.subsequentPhases) { - PhaseScc subsequentScc = phaseToScc.get(subsequentPhase); - - if (subsequentScc != scc) { - scc.subsequentSccs.add(subsequentScc); - subsequentScc.inDegree++; - } - } - } - } - - // Order SCCs according to priorities. When there is a choice, use the SCC with the lowest id. - // The priority queue contains all SCCs that currently have 0 in-degree. - PriorityQueue> pq = new PriorityQueue<>(Comparator.comparing(scc -> scc.phases.get(0).id)); - sortedPhases.clear(); - - for (PhaseScc scc : phaseToScc.values()) { - if (scc.inDegree == 0) { - pq.add(scc); - // Prevent adding the same SCC multiple times, as phaseToScc may contain the same value multiple times. - scc.inDegree = -1; - } - } - - while (!pq.isEmpty()) { - PhaseScc scc = pq.poll(); - sortedPhases.addAll(scc.phases); - - for (PhaseScc subsequentScc : scc.subsequentSccs) { - subsequentScc.inDegree--; - - if (subsequentScc.inDegree == 0) { - pq.add(subsequentScc); - } - } - } - } - - private static void forwardVisit(EventPhaseData phase, EventPhaseData parent, List> toposort) { - if (phase.visitStatus == 0) { - // Not yet visited. - phase.visitStatus = 1; - - for (EventPhaseData data : phase.subsequentPhases) { - forwardVisit(data, phase, toposort); - } - - toposort.add(phase); - phase.visitStatus = 2; - } else if (phase.visitStatus == 1 && ENABLE_CYCLE_WARNING) { - // Already visiting, so we have found a cycle. - ArrayBackedEvent.LOGGER.warn(String.format( - "Event phase ordering conflict detected.%nEvent phase %s is ordered both before and after event phase %s.", - phase.id, - parent.id - )); - } - } - - private static void clearStatus(List> phases) { - for (EventPhaseData phase : phases) { - phase.visitStatus = 0; - } - } - - private static void backwardVisit(EventPhaseData phase, List> sccPhases) { - if (phase.visitStatus == 0) { - phase.visitStatus = 1; - sccPhases.add(phase); - - for (EventPhaseData data : phase.previousPhases) { - backwardVisit(data, sccPhases); - } - } - } - - private static class PhaseScc { - final List> phases; - final List> subsequentSccs = new ArrayList<>(); - int inDegree = 0; - - private PhaseScc(List> phases) { - this.phases = phases; - } - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractChanneledNetworkAddon.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractChanneledNetworkAddon.java deleted file mode 100644 index 9c3ba39f7..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractChanneledNetworkAddon.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -import io.netty.util.AsciiString; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import org.jetbrains.annotations.Nullable; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketByteBufs; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender; -import net.minecraft.ResourceLocationException; -import net.minecraft.network.Connection; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.resources.ResourceLocation; - -/** - * A network addon which is aware of the channels the other side may receive. - * - * @param the channel handler type - */ -public abstract class AbstractChanneledNetworkAddon extends AbstractNetworkAddon implements PacketSender { - protected final Connection connection; - protected final GlobalReceiverRegistry receiver; - protected final Set sendableChannels; - protected final Set sendableChannelsView; - - protected AbstractChanneledNetworkAddon(GlobalReceiverRegistry receiver, Connection connection, String description) { - this(receiver, connection, new HashSet<>(), description); - } - - protected AbstractChanneledNetworkAddon(GlobalReceiverRegistry receiver, Connection connection, Set sendableChannels, String description) { - super(receiver, description); - this.connection = connection; - this.receiver = receiver; - this.sendableChannels = sendableChannels; - this.sendableChannelsView = Collections.unmodifiableSet(sendableChannels); - } - - public abstract void lateInit(); - - protected void registerPendingChannels(ChannelInfoHolder holder) { - final Collection pending = holder.getPendingChannelsNames(); - - if (!pending.isEmpty()) { - register(new ArrayList<>(pending)); - pending.clear(); - } - } - - // always supposed to handle async! - protected boolean handle(ResourceLocation channelName, FriendlyByteBuf originalBuf) { - this.logger.debug("Handling inbound packet from channel with name \"{}\"", channelName); - - // Handle reserved packets - if (NetworkingImpl.REGISTER_CHANNEL.equals(channelName)) { - this.receiveRegistration(true, PacketByteBufs.slice(originalBuf)); - return true; - } - - if (NetworkingImpl.UNREGISTER_CHANNEL.equals(channelName)) { - this.receiveRegistration(false, PacketByteBufs.slice(originalBuf)); - return true; - } - - @Nullable H handler = this.getHandler(channelName); - - if (handler == null) { - return false; - } - - FriendlyByteBuf buf = PacketByteBufs.slice(originalBuf); - - try { - this.receive(handler, buf); - } catch (Throwable ex) { - this.logger.error("Encountered exception while handling in channel with name \"{}\"", channelName, ex); - throw ex; - } - - return true; - } - - protected abstract void receive(H handler, FriendlyByteBuf buf); - - protected void sendInitialChannelRegistrationPacket() { - final FriendlyByteBuf buf = this.createRegistrationPacket(this.getReceivableChannels()); - - if (buf != null) { - this.sendPacket(NetworkingImpl.REGISTER_CHANNEL, buf); - } - } - - @Nullable - protected FriendlyByteBuf createRegistrationPacket(Collection channels) { - if (channels.isEmpty()) { - return null; - } - - FriendlyByteBuf buf = PacketByteBufs.create(); - boolean first = true; - - for (ResourceLocation channel : channels) { - if (first) { - first = false; - } else { - buf.writeByte(0); - } - - buf.writeBytes(channel.toString().getBytes(StandardCharsets.US_ASCII)); - } - - return buf; - } - - // wrap in try with res (buf) - protected void receiveRegistration(boolean register, FriendlyByteBuf buf) { - List ids = new ArrayList<>(); - StringBuilder active = new StringBuilder(); - - while (buf.isReadable()) { - byte b = buf.readByte(); - - if (b != 0) { - active.append(AsciiString.b2c(b)); - } else { - this.addId(ids, active); - active = new StringBuilder(); - } - } - - this.addId(ids, active); - this.schedule(register ? () -> register(ids) : () -> unregister(ids)); - } - - void register(List ids) { - this.sendableChannels.addAll(ids); - this.invokeRegisterEvent(ids); - } - - void unregister(List ids) { - this.sendableChannels.removeAll(ids); - this.invokeUnregisterEvent(ids); - } - - @Override - public void sendPacket(Packet packet) { - Objects.requireNonNull(packet, "Packet cannot be null"); - - this.connection.send(packet); - } - - @Override - public void sendPacket(Packet packet, GenericFutureListener> callback) { - Objects.requireNonNull(packet, "Packet cannot be null"); - - this.connection.send(packet, callback); - } - - /** - * Schedules a task to run on the main thread. - */ - protected abstract void schedule(Runnable task); - - protected abstract void invokeRegisterEvent(List ids); - - protected abstract void invokeUnregisterEvent(List ids); - - private void addId(List ids, StringBuilder sb) { - String literal = sb.toString(); - - try { - ids.add(new ResourceLocation(literal)); - } catch (ResourceLocationException ex) { - this.logger.warn("Received invalid channel identifier \"{}\" from connection {}", literal, this.connection); - } - } - - public Set getSendableChannels() { - return this.sendableChannelsView; - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractNetworkAddon.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractNetworkAddon.java deleted file mode 100644 index b07029a7a..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/AbstractNetworkAddon.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import net.minecraft.resources.ResourceLocation; -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; -import org.jetbrains.annotations.Nullable; - -/** - * A network addon is a simple abstraction to hold information about a player's registered channels. - * - * @param the channel handler type - */ -public abstract class AbstractNetworkAddon { - protected final GlobalReceiverRegistry receiver; - protected final Logger logger; - // A lock is used due to possible access on netty's event loops and game thread at same times such as during dynamic registration - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - // Sync map should be fine as there is little read write competition - // All access to this map is guarded by the lock - private final Map handlers = new HashMap<>(); - private final AtomicBoolean disconnected = new AtomicBoolean(); // blocks redundant disconnect notifications - - protected AbstractNetworkAddon(GlobalReceiverRegistry receiver, String description) { - this.receiver = receiver; - this.logger = LoggerFactory.getLogger(description); - } - - @Nullable - public H getHandler(ResourceLocation channel) { - Lock lock = this.lock.readLock(); - lock.lock(); - - try { - return this.handlers.get(channel); - } finally { - lock.unlock(); - } - } - - public boolean registerChannel(ResourceLocation channelName, H handler) { - Objects.requireNonNull(channelName, "Channel name cannot be null"); - Objects.requireNonNull(handler, "Packet handler cannot be null"); - - if (this.isReservedChannel(channelName)) { - throw new IllegalArgumentException(String.format("Cannot register handler for reserved channel with name \"%s\"", channelName)); - } - - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - final boolean replaced = this.handlers.putIfAbsent(channelName, handler) == null; - - if (replaced) { - this.handleRegistration(channelName); - } - - return replaced; - } finally { - lock.unlock(); - } - } - - public H unregisterChannel(ResourceLocation channelName) { - Objects.requireNonNull(channelName, "Channel name cannot be null"); - - if (this.isReservedChannel(channelName)) { - throw new IllegalArgumentException(String.format("Cannot register handler for reserved channel with name \"%s\"", channelName)); - } - - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - final H removed = this.handlers.remove(channelName); - - if (removed != null) { - this.handleUnregistration(channelName); - } - - return removed; - } finally { - lock.unlock(); - } - } - - public Set getReceivableChannels() { - Lock lock = this.lock.readLock(); - lock.lock(); - - try { - return new HashSet<>(this.handlers.keySet()); - } finally { - lock.unlock(); - } - } - - protected abstract void handleRegistration(ResourceLocation channelName); - - protected abstract void handleUnregistration(ResourceLocation channelName); - - public final void handleDisconnect() { - if (disconnected.compareAndSet(false, true)) { - invokeDisconnectEvent(); - } - } - - protected abstract void invokeDisconnectEvent(); - - /** - * Checks if a channel is considered a "reserved" channel. - * A reserved channel such as "minecraft:(un)register" has special handling and should not have any channel handlers registered for it. - * - * @param channelName the channel name - * @return whether the channel is reserved - */ - protected abstract boolean isReservedChannel(ResourceLocation channelName); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/ChannelInfoHolder.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/ChannelInfoHolder.java deleted file mode 100644 index e713fe157..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/ChannelInfoHolder.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -import java.util.Collection; -import net.minecraft.resources.ResourceLocation; - -public interface ChannelInfoHolder { - /** - * @return Channels which are declared as receivable by the other side but have not been declared yet. - */ - Collection getPendingChannelsNames(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/DisconnectPacketSource.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/DisconnectPacketSource.java deleted file mode 100644 index be14224b1..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/DisconnectPacketSource.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.Packet; - -public interface DisconnectPacketSource { - Packet createDisconnectPacket(Component message); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/GlobalReceiverRegistry.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/GlobalReceiverRegistry.java deleted file mode 100644 index 4454385a4..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/GlobalReceiverRegistry.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.Nullable; - -public final class GlobalReceiverRegistry { - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private final Map handlers; - private final Set> trackedAddons = new HashSet<>(); - - public GlobalReceiverRegistry() { - this(new HashMap<>()); // sync map should be fine as there is little read write competitions - } - - public GlobalReceiverRegistry(Map map) { - this.handlers = map; - } - - @Nullable - public H getHandler(ResourceLocation channelName) { - Lock lock = this.lock.readLock(); - lock.lock(); - - try { - return this.handlers.get(channelName); - } finally { - lock.unlock(); - } - } - - public boolean registerGlobalReceiver(ResourceLocation channelName, H handler) { - Objects.requireNonNull(channelName, "Channel name cannot be null"); - Objects.requireNonNull(handler, "Channel handler cannot be null"); - - if (NetworkingImpl.isReservedPlayChannel(channelName)) { - throw new IllegalArgumentException(String.format("Cannot register handler for reserved channel with name \"%s\"", channelName)); - } - - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - final boolean replaced = this.handlers.putIfAbsent(channelName, handler) == null; - - if (!replaced) { - this.handleRegistration(channelName, handler); - } - - return replaced; - } finally { - lock.unlock(); - } - } - - public H unregisterGlobalReceiver(ResourceLocation channelName) { - Objects.requireNonNull(channelName, "Channel name cannot be null"); - - if (NetworkingImpl.isReservedPlayChannel(channelName)) { - throw new IllegalArgumentException(String.format("Cannot unregister packet handler for reserved channel with name \"%s\"", channelName)); - } - - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - final H removed = this.handlers.remove(channelName); - - if (removed != null) { - this.handleUnregistration(channelName); - } - - return removed; - } finally { - lock.unlock(); - } - } - - public Map getHandlers() { - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - return new HashMap<>(this.handlers); - } finally { - lock.unlock(); - } - } - - public Set getChannels() { - Lock lock = this.lock.readLock(); - lock.lock(); - - try { - return new HashSet<>(this.handlers.keySet()); - } finally { - lock.unlock(); - } - } - - // State tracking methods - - public void startSession(AbstractNetworkAddon addon) { - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - this.trackedAddons.add(addon); - } finally { - lock.unlock(); - } - } - - public void endSession(AbstractNetworkAddon addon) { - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - this.trackedAddons.remove(addon); - } finally { - lock.unlock(); - } - } - - private void handleRegistration(ResourceLocation channelName, H handler) { - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - for (AbstractNetworkAddon addon : this.trackedAddons) { - addon.registerChannel(channelName, handler); - } - } finally { - lock.unlock(); - } - } - - private void handleUnregistration(ResourceLocation channelName) { - Lock lock = this.lock.writeLock(); - lock.lock(); - - try { - for (AbstractNetworkAddon addon : this.trackedAddons) { - addon.unregisterChannel(channelName); - } - } finally { - lock.unlock(); - } - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkHandlerExtensions.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkHandlerExtensions.java deleted file mode 100644 index ec2919a03..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkHandlerExtensions.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -public interface NetworkHandlerExtensions { - AbstractNetworkAddon getAddon(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkingImpl.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkingImpl.java deleted file mode 100644 index 01edeef2d..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/NetworkingImpl.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import net.minecraft.network.FriendlyByteBuf; -import org.slf4j.LoggerFactory; -import org.slf4j.Logger; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketByteBufs; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginConnectionEvents; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginNetworking; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.resources.ResourceLocation; - -public final class NetworkingImpl { - public static final String MOD_ID = "fabric-networking-api-v1"; - public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - /** - * Id of packet used to register supported channels. - */ - public static final ResourceLocation REGISTER_CHANNEL = new ResourceLocation("minecraft", "register"); - /** - * Id of packet used to unregister supported channels. - */ - public static final ResourceLocation UNREGISTER_CHANNEL = new ResourceLocation("minecraft", "unregister"); - /** - * Id of the packet used to declare all currently supported channels. - * Dynamic registration of supported channels is still allowed using {@link NetworkingImpl#REGISTER_CHANNEL} and {@link NetworkingImpl#UNREGISTER_CHANNEL}. - */ - public static final ResourceLocation EARLY_REGISTRATION_CHANNEL = new ResourceLocation(MOD_ID, "early_registration"); - - public static void init() { - // Login setup - ServerLoginConnectionEvents.QUERY_START.register((handler, server, sender, synchronizer) -> { - // Send early registration packet - FriendlyByteBuf buf = PacketByteBufs.create(); - Collection channelsNames = ServerPlayNetworking.getGlobalReceivers(); - buf.writeVarInt(channelsNames.size()); - - for (ResourceLocation id : channelsNames) { - buf.writeResourceLocation(id); - } - - sender.sendPacket(EARLY_REGISTRATION_CHANNEL, buf); - NetworkingImpl.LOGGER.debug("Sent accepted channels to the client for \"{}\"", handler.getUserName()); - }); - - ServerLoginNetworking.registerGlobalReceiver(EARLY_REGISTRATION_CHANNEL, (server, handler, understood, buf, synchronizer, sender) -> { - if (!understood) { - // The client is likely a vanilla client. - return; - } - - int n = buf.readVarInt(); - List ids = new ArrayList<>(n); - - for (int i = 0; i < n; i++) { - ids.add(buf.readResourceLocation()); - } - - ((ChannelInfoHolder) handler.getConnection()).getPendingChannelsNames().addAll(ids); - NetworkingImpl.LOGGER.debug("Received accepted channels from the client for \"{}\"", handler.getUserName()); - }); - } - - public static boolean isReservedPlayChannel(ResourceLocation channelName) { - return channelName.equals(REGISTER_CHANNEL) || channelName.equals(UNREGISTER_CHANNEL); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/PacketCallbackListener.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/PacketCallbackListener.java deleted file mode 100644 index e7e2ecefc..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/PacketCallbackListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking; - -import net.minecraft.network.protocol.Packet; - -public interface PacketCallbackListener { - /** - * Called after a packet has been sent. - * - * @param packet the packet - */ - void sent(Packet packet); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientLoginNetworkAddon.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientLoginNetworkAddon.java deleted file mode 100644 index dcd655ae4..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientLoginNetworkAddon.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking.client; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import org.jetbrains.annotations.Nullable; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientLoginConnectionEvents; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientLoginNetworking; -import com.seibel.lod.forge.fabric.api.networking.v1.FutureListeners; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketByteBufs; -import com.seibel.lod.forge.fabric.impl.networking.AbstractNetworkAddon; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; -import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; -import net.minecraft.resources.ResourceLocation; - -public final class ClientLoginNetworkAddon extends AbstractNetworkAddon { - private final ClientHandshakePacketListenerImpl handler; - private final Minecraft client; - private boolean firstResponse = true; - - public ClientLoginNetworkAddon(ClientHandshakePacketListenerImpl handler, Minecraft client) { - super(ClientNetworkingImpl.LOGIN, "ClientLoginNetworkAddon for Client"); - this.handler = handler; - this.client = client; - - ClientLoginConnectionEvents.INIT.invoker().onLoginStart(this.handler, this.client); - this.receiver.startSession(this); - } - - public boolean handlePacket(ClientboundCustomQueryPacket packet) { - return handlePacket(packet.getTransactionId(), packet.getIdentifier(), packet.getData()); - } - - private boolean handlePacket(int queryId, ResourceLocation channelName, FriendlyByteBuf originalBuf) { - this.logger.debug("Handling inbound login response with id {} and channel with name {}", queryId, channelName); - - if (this.firstResponse) { - // Register global handlers - for (Map.Entry entry : ClientNetworkingImpl.LOGIN.getHandlers().entrySet()) { - ClientLoginNetworking.registerReceiver(entry.getKey(), entry.getValue()); - } - - ClientLoginConnectionEvents.QUERY_START.invoker().onLoginQueryStart(this.handler, this.client); - this.firstResponse = false; - } - - @Nullable ClientLoginNetworking.LoginQueryRequestHandler handler = this.getHandler(channelName); - - if (handler == null) { - return false; - } - - FriendlyByteBuf buf = PacketByteBufs.slice(originalBuf); - List>> futureListeners = new ArrayList<>(); - - try { - CompletableFuture<@Nullable FriendlyByteBuf> future = handler.receive(this.client, this.handler, buf, futureListeners::add); - future.thenAccept(result -> { - ServerboundCustomQueryPacket packet = new ServerboundCustomQueryPacket(queryId, result); - GenericFutureListener> listener = null; - - for (GenericFutureListener> each : futureListeners) { - listener = FutureListeners.union(listener, each); - } - - this.handler.getConnection().send(packet, listener); - }); - } catch (Throwable ex) { - this.logger.error("Encountered exception while handling in channel with name \"{}\"", channelName, ex); - throw ex; - } - - return true; - } - - @Override - protected void handleRegistration(ResourceLocation channelName) { - } - - @Override - protected void handleUnregistration(ResourceLocation channelName) { - } - - @Override - protected void invokeDisconnectEvent() { - ClientLoginConnectionEvents.DISCONNECT.invoker().onLoginDisconnect(this.handler, this.client); - this.receiver.endSession(this); - } - - public void handlePlayTransition() { - this.receiver.endSession(this); - } - - @Override - protected boolean isReservedChannel(ResourceLocation channelName) { - return false; - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientNetworkingImpl.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientNetworkingImpl.java deleted file mode 100644 index e2576d1cd..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientNetworkingImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking.client; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import org.jetbrains.annotations.Nullable; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientLoginNetworking; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayNetworking; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketByteBufs; -import com.seibel.lod.forge.fabric.impl.networking.ChannelInfoHolder; -import com.seibel.lod.forge.fabric.impl.networking.GlobalReceiverRegistry; -import com.seibel.lod.forge.fabric.impl.networking.NetworkHandlerExtensions; -import com.seibel.lod.forge.fabric.impl.networking.NetworkingImpl; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.ConnectScreenAccessor; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.MinecraftClientAccessor; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.ConnectScreen; -import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.Connection; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket; -import net.minecraft.resources.ResourceLocation; - -public final class ClientNetworkingImpl { - public static final GlobalReceiverRegistry LOGIN = new GlobalReceiverRegistry<>(); - public static final GlobalReceiverRegistry PLAY = new GlobalReceiverRegistry<>(); - private static ClientPlayNetworkAddon currentPlayAddon; - - public static ClientPlayNetworkAddon getAddon(ClientPacketListener handler) { - return (ClientPlayNetworkAddon) ((NetworkHandlerExtensions) handler).getAddon(); - } - - public static ClientLoginNetworkAddon getAddon(ClientHandshakePacketListenerImpl handler) { - return (ClientLoginNetworkAddon) ((NetworkHandlerExtensions) handler).getAddon(); - } - - public static Packet createPlayC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) { - return new ServerboundCustomPayloadPacket(channelName, buf); - } - - /** - * Due to the way logging into a integrated or remote dedicated server will differ, we need to obtain the login client connection differently. - */ - @Nullable - public static Connection getLoginConnection() { - final Connection connection = ((MinecraftClientAccessor) Minecraft.getInstance()).getConnection(); - - // Check if we are connecting to an integrated server. This will set the field on MinecraftClient - if (connection != null) { - return connection; - } else { - // We are probably connecting to a remote server. - // Check if the ConnectScreen is the currentScreen to determine that: - if (Minecraft.getInstance().screen instanceof ConnectScreen) { - return ((ConnectScreenAccessor) Minecraft.getInstance().screen).getConnection(); - } - } - - // We are not connected to a server at all. - 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 (Minecraft.getInstance().getConnection() != null) { - currentPlayAddon = null; // Shouldn't need this anymore - return ClientNetworkingImpl.getAddon(Minecraft.getInstance().getConnection()); - } - - // 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(); - List ids = new ArrayList<>(n); - - for (int i = 0; i < n; i++) { - ids.add(buf.readResourceLocation()); - } - - ((ChannelInfoHolder) handler.getConnection()).getPendingChannelsNames().addAll(ids); - NetworkingImpl.LOGGER.debug("Received accepted channels from the server"); - - FriendlyByteBuf response = PacketByteBufs.create(); - Collection channels = ClientPlayNetworking.getGlobalReceivers(); - response.writeVarInt(channels.size()); - - for (ResourceLocation id : channels) { - response.writeResourceLocation(id); - } - - NetworkingImpl.LOGGER.debug("Sent accepted channels to the server"); - return CompletableFuture.completedFuture(response); - }); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientPlayNetworkAddon.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientPlayNetworkAddon.java deleted file mode 100644 index 001136712..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/client/ClientPlayNetworkAddon.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking.client; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import com.seibel.lod.forge.fabric.api.client.networking.v1.C2SPlayChannelEvents; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayNetworking; -import com.seibel.lod.forge.fabric.impl.networking.AbstractChanneledNetworkAddon; -import com.seibel.lod.forge.fabric.impl.networking.ChannelInfoHolder; -import com.seibel.lod.forge.fabric.impl.networking.NetworkingImpl; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; -import net.minecraft.resources.ResourceLocation; - -public final class ClientPlayNetworkAddon extends AbstractChanneledNetworkAddon { - private final ClientPacketListener handler; - private final Minecraft client; - private boolean sentInitialRegisterPacket; - - public ClientPlayNetworkAddon(ClientPacketListener handler, Minecraft client) { - super(ClientNetworkingImpl.PLAY, handler.getConnection(), "ClientPlayNetworkAddon for " + handler.getLocalGameProfile().getName()); - this.handler = handler; - this.client = client; - - // Must register pending channels via lateinit - this.registerPendingChannels((ChannelInfoHolder) this.connection); - - // Register global receivers and attach to session - this.receiver.startSession(this); - } - - @Override - public void lateInit() { - for (Map.Entry entry : this.receiver.getHandlers().entrySet()) { - this.registerChannel(entry.getKey(), entry.getValue()); - } - - ClientPlayConnectionEvents.INIT.invoker().onPlayInit(this.handler, this.client); - } - - public void onServerReady() { - ClientPlayConnectionEvents.JOIN.invoker().onPlayReady(this.handler, this, this.client); - - // The client cannot send any packets, including `minecraft:register` until after GameJoinS2CPacket is received. - this.sendInitialChannelRegistrationPacket(); - this.sentInitialRegisterPacket = true; - } - - /** - * Handles an incoming packet. - * - * @param packet the packet to handle - * @return true if the packet has been handled - */ - public boolean handle(ClientboundCustomPayloadPacket packet) { - // Do not handle the packet on game thread - if (this.client.isSameThread()) { - return false; - } - - FriendlyByteBuf buf = packet.getData(); - - try { - return this.handle(packet.getIdentifier(), buf); - } finally { - buf.release(); - } - } - - @Override - protected void receive(ClientPlayNetworking.PlayChannelHandler handler, FriendlyByteBuf buf) { - handler.receive(this.client, this.handler, buf, this); - } - - // impl details - - @Override - protected void schedule(Runnable task) { - Minecraft.getInstance().execute(task); - } - - @Override - public Packet createPacket(ResourceLocation channelName, FriendlyByteBuf buf) { - return ClientPlayNetworking.createC2SPacket(channelName, buf); - } - - @Override - protected void invokeRegisterEvent(List ids) { - C2SPlayChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.client, ids); - } - - @Override - protected void invokeUnregisterEvent(List ids) { - C2SPlayChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.client, ids); - } - - @Override - protected void handleRegistration(ResourceLocation channelName) { - // If we can already send packets, immediately send the register packet for this channel - if (this.sentInitialRegisterPacket) { - final FriendlyByteBuf buf = this.createRegistrationPacket(Collections.singleton(channelName)); - - if (buf != null) { - this.sendPacket(NetworkingImpl.REGISTER_CHANNEL, buf); - } - } - } - - @Override - protected void handleUnregistration(ResourceLocation channelName) { - // If we can already send packets, immediately send the unregister packet for this channel - if (this.sentInitialRegisterPacket) { - final FriendlyByteBuf buf = this.createRegistrationPacket(Collections.singleton(channelName)); - - if (buf != null) { - this.sendPacket(NetworkingImpl.UNREGISTER_CHANNEL, buf); - } - } - } - - @Override - protected void invokeDisconnectEvent() { - ClientPlayConnectionEvents.DISCONNECT.invoker().onPlayDisconnect(this.handler, this.client); - this.receiver.endSession(this); - } - - @Override - protected boolean isReservedChannel(ResourceLocation channelName) { - return NetworkingImpl.isReservedPlayChannel(channelName); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/QueryIdFactory.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/QueryIdFactory.java deleted file mode 100644 index 99d09272e..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/QueryIdFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking.server; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Tracks the current query id used for login query responses. - */ -interface QueryIdFactory { - static QueryIdFactory create() { - return new QueryIdFactory() { - private final AtomicInteger currentId = new AtomicInteger(); - - @Override - public int nextId() { - return this.currentId.getAndIncrement(); - } - }; - } - - // called async prob. - int nextId(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerLoginNetworkAddon.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerLoginNetworkAddon.java deleted file mode 100644 index 1cf0aa3ae..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerLoginNetworkAddon.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking.server; - -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReference; - -import io.netty.util.concurrent.GenericFutureListener; -import org.jetbrains.annotations.Nullable; -import net.minecraft.network.Connection; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; -import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; -import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginPacketListenerImpl; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketByteBufs; -import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginConnectionEvents; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginNetworking; -import com.seibel.lod.forge.fabric.impl.networking.AbstractNetworkAddon; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.LoginQueryResponseC2SPacketAccessor; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.ServerLoginNetworkHandlerAccessor; - -public final class ServerLoginNetworkAddon extends AbstractNetworkAddon implements PacketSender { - private final Connection connection; - private final ServerLoginPacketListenerImpl handler; - private final MinecraftServer server; - private final QueryIdFactory queryIdFactory; - private final Collection> waits = new ConcurrentLinkedQueue<>(); - private final Map channels = new ConcurrentHashMap<>(); - private boolean firstQueryTick = true; - - public ServerLoginNetworkAddon(ServerLoginPacketListenerImpl handler) { - super(ServerNetworkingImpl.LOGIN, "ServerLoginNetworkAddon for " + handler.getUserName()); - this.connection = handler.connection; - this.handler = handler; - this.server = ((ServerLoginNetworkHandlerAccessor) handler).getServer(); - this.queryIdFactory = QueryIdFactory.create(); - - ServerLoginConnectionEvents.INIT.invoker().onLoginInit(handler, this.server); - this.receiver.startSession(this); - } - - // return true if no longer ticks query - public boolean queryTick() { - if (this.firstQueryTick) { - // Send the compression packet now so clients receive compressed login queries - this.sendCompressionPacket(); - - // Register global receivers. - for (Map.Entry entry : ServerNetworkingImpl.LOGIN.getHandlers().entrySet()) { - ServerLoginNetworking.registerReceiver(this.handler, entry.getKey(), entry.getValue()); - } - - ServerLoginConnectionEvents.QUERY_START.invoker().onLoginStart(this.handler, this.server, this, this.waits::add); - this.firstQueryTick = false; - } - - AtomicReference error = new AtomicReference<>(); - this.waits.removeIf(future -> { - if (!future.isDone()) { - return false; - } - - try { - future.get(); - } catch (ExecutionException ex) { - Throwable caught = ex.getCause(); - error.getAndUpdate(oldEx -> { - if (oldEx == null) { - return caught; - } - - oldEx.addSuppressed(caught); - return oldEx; - }); - } catch (InterruptedException | CancellationException ignored) { - // ignore - } - - return true; - }); - - return this.channels.isEmpty() && this.waits.isEmpty(); - } - - private void sendCompressionPacket() { - // Compression is not needed for local transport - if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) { - this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), (channelFuture) -> - this.connection.setupCompression(this.server.getCompressionThreshold(), true) - ); - } - } - - /** - * Handles an incoming query response during login. - * - * @param packet the packet to handle - * @return true if the packet was handled - */ - public boolean handle(ServerboundCustomQueryPacket packet) { - LoginQueryResponseC2SPacketAccessor access = (LoginQueryResponseC2SPacketAccessor) packet; - return handle(access.getTransactionId(), access.getData()); - } - - private boolean handle(int queryId, @Nullable FriendlyByteBuf originalBuf) { - this.logger.debug("Handling inbound login query with id {}", queryId); - ResourceLocation channel = this.channels.remove(queryId); - - if (channel == null) { - this.logger.warn("Query ID {} was received but no query has been associated in {}!", queryId, this.connection); - return false; - } - - boolean understood = originalBuf != null; - @Nullable ServerLoginNetworking.LoginQueryResponseHandler handler = ServerNetworkingImpl.LOGIN.getHandler(channel); - - if (handler == null) { - return false; - } - - FriendlyByteBuf buf = understood ? PacketByteBufs.slice(originalBuf) : PacketByteBufs.empty(); - - try { - handler.receive(this.server, this.handler, understood, buf, this.waits::add, this); - } catch (Throwable ex) { - this.logger.error("Encountered exception while handling in channel \"{}\"", channel, ex); - throw ex; - } - - return true; - } - - @Override - public Packet createPacket(ResourceLocation channelName, FriendlyByteBuf buf) { - int queryId = this.queryIdFactory.nextId(); - - ClientboundCustomQueryPacket ret = new ClientboundCustomQueryPacket(queryId, channelName, buf); - return ret; - } - - @Override - public void sendPacket(Packet packet) { - Objects.requireNonNull(packet, "Packet cannot be null"); - - this.connection.send(packet); - } - - @Override - public void sendPacket(Packet packet, GenericFutureListener> callback) { - Objects.requireNonNull(packet, "Packet cannot be null"); - - this.connection.send(packet, callback); - } - - public void registerOutgoingPacket(ClientboundCustomQueryPacket packet) { - this.channels.put(packet.getTransactionId(), packet.getIdentifier()); - } - - @Override - protected void handleRegistration(ResourceLocation channelName) { - } - - @Override - protected void handleUnregistration(ResourceLocation channelName) { - } - - @Override - protected void invokeDisconnectEvent() { - ServerLoginConnectionEvents.DISCONNECT.invoker().onLoginDisconnect(this.handler, this.server); - this.receiver.endSession(this); - } - - public void handlePlayTransition() { - this.receiver.endSession(this); - } - - @Override - protected boolean isReservedChannel(ResourceLocation channelName) { - return false; - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerNetworkingImpl.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerNetworkingImpl.java deleted file mode 100644 index 11dfaf284..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerNetworkingImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking.server; - -import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginNetworking; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking; -import com.seibel.lod.forge.fabric.impl.networking.GlobalReceiverRegistry; -import com.seibel.lod.forge.fabric.impl.networking.NetworkHandlerExtensions; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.server.network.ServerLoginPacketListenerImpl; - -public final class ServerNetworkingImpl { - public static final GlobalReceiverRegistry LOGIN = new GlobalReceiverRegistry<>(); - public static final GlobalReceiverRegistry PLAY = new GlobalReceiverRegistry<>(); - - public static ServerPlayNetworkAddon getAddon(ServerGamePacketListenerImpl handler) { - return (ServerPlayNetworkAddon) ((NetworkHandlerExtensions) handler).getAddon(); - } - - public static ServerLoginNetworkAddon getAddon(ServerLoginPacketListenerImpl handler) { - return (ServerLoginNetworkAddon) ((NetworkHandlerExtensions) handler).getAddon(); - } - - public static Packet createPlayC2SPacket(ResourceLocation channel, FriendlyByteBuf buf) { - return new ClientboundCustomPayloadPacket(channel, buf); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerPlayNetworkAddon.java b/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerPlayNetworkAddon.java deleted file mode 100644 index df419e63d..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/fabric/impl/networking/server/ServerPlayNetworkAddon.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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 com.seibel.lod.forge.fabric.impl.networking.server; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import com.seibel.lod.forge.fabric.api.networking.v1.S2CPlayChannelEvents; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayConnectionEvents; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking; -import com.seibel.lod.forge.fabric.impl.networking.AbstractChanneledNetworkAddon; -import com.seibel.lod.forge.fabric.impl.networking.ChannelInfoHolder; -import com.seibel.lod.forge.fabric.impl.networking.NetworkingImpl; -import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.CustomPayloadC2SPacketAccessor; - -public final class ServerPlayNetworkAddon extends AbstractChanneledNetworkAddon { - private final ServerGamePacketListenerImpl handler; - private final MinecraftServer server; - private boolean sentInitialRegisterPacket; - - public ServerPlayNetworkAddon(ServerGamePacketListenerImpl handler, MinecraftServer server) { - super(ServerNetworkingImpl.PLAY, handler.getConnection(), "ServerPlayNetworkAddon for " + handler.player.getScoreboardName()); - this.handler = handler; - this.server = server; - - // Must register pending channels via lateinit - this.registerPendingChannels((ChannelInfoHolder) this.connection); - - // Register global receivers and attach to session - this.receiver.startSession(this); - } - - @Override - public void lateInit() { - for (Map.Entry entry : this.receiver.getHandlers().entrySet()) { - this.registerChannel(entry.getKey(), entry.getValue()); - } - - ServerPlayConnectionEvents.INIT.invoker().onPlayInit(this.handler, this.server); - } - - public void onClientReady() { - ServerPlayConnectionEvents.JOIN.invoker().onPlayReady(this.handler, this, this.server); - - this.sendInitialChannelRegistrationPacket(); - this.sentInitialRegisterPacket = true; - } - - /** - * Handles an incoming packet. - * - * @param packet the packet to handle - * @return true if the packet has been handled - */ - public boolean handle(ServerboundCustomPayloadPacket packet) { - // Do not handle the packet on game thread - if (this.server.isSameThread()) { - return false; - } - - CustomPayloadC2SPacketAccessor access = (CustomPayloadC2SPacketAccessor) packet; - return this.handle(access.getIdentifier(), access.getData()); - } - - @Override - protected void receive(ServerPlayNetworking.PlayChannelHandler handler, FriendlyByteBuf buf) { - handler.receive(this.server, this.handler.player, this.handler, buf, this); - } - - // impl details - - @Override - protected void schedule(Runnable task) { - this.handler.player.server.execute(task); - } - - @Override - public Packet createPacket(ResourceLocation channelName, FriendlyByteBuf buf) { - return ServerPlayNetworking.createS2CPacket(channelName, buf); - } - - @Override - protected void invokeRegisterEvent(List ids) { - S2CPlayChannelEvents.REGISTER.invoker().onChannelRegister(this.handler, this, this.server, ids); - } - - @Override - protected void invokeUnregisterEvent(List ids) { - S2CPlayChannelEvents.UNREGISTER.invoker().onChannelUnregister(this.handler, this, this.server, ids); - } - - @Override - protected void handleRegistration(ResourceLocation channelName) { - // If we can already send packets, immediately send the register packet for this channel - if (this.sentInitialRegisterPacket) { - final FriendlyByteBuf buf = this.createRegistrationPacket(Collections.singleton(channelName)); - - if (buf != null) { - this.sendPacket(NetworkingImpl.REGISTER_CHANNEL, buf); - } - } - } - - @Override - protected void handleUnregistration(ResourceLocation channelName) { - // If we can already send packets, immediately send the unregister packet for this channel - if (this.sentInitialRegisterPacket) { - final FriendlyByteBuf buf = this.createRegistrationPacket(Collections.singleton(channelName)); - - if (buf != null) { - this.sendPacket(NetworkingImpl.UNREGISTER_CHANNEL, buf); - } - } - } - - @Override - protected void invokeDisconnectEvent() { - ServerPlayConnectionEvents.DISCONNECT.invoker().onPlayDisconnect(this.handler, this.server); - this.receiver.endSession(this); - } - - @Override - protected boolean isReservedChannel(ResourceLocation channelName) { - return NetworkingImpl.isReservedPlayChannel(channelName); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking.zip b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking.zip new file mode 100644 index 0000000000000000000000000000000000000000..0c4c6af3b214a60c58595998880e97e7f5eb1ecd GIT binary patch literal 14579 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 literal 0 HcmV?d00001 diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ClientConnectionMixin.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ClientConnectionMixin.java deleted file mode 100644 index 5f2d74b1d..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ClientConnectionMixin.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking; - -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.ConcurrentHashMap; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.seibel.lod.forge.fabric.impl.networking.ChannelInfoHolder; -import com.seibel.lod.forge.fabric.impl.networking.DisconnectPacketSource; -import com.seibel.lod.forge.fabric.impl.networking.NetworkHandlerExtensions; -import com.seibel.lod.forge.fabric.impl.networking.PacketCallbackListener; -import net.minecraft.network.Connection; -import net.minecraft.network.PacketListener; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.PacketFlow; -import net.minecraft.resources.ResourceLocation; - -@Mixin(Connection.class) -abstract class ClientConnectionMixin implements ChannelInfoHolder { - @Shadow - private PacketListener packetListener; - - @Shadow - public abstract void send(Packet packet, GenericFutureListener> callback); - - @Shadow - public abstract void disconnect(Component disconnectReason); - - @Unique - private Collection playChannels; - - @Inject(method = "", at = @At("RETURN")) - private void initAddedFields(PacketFlow side, CallbackInfo ci) { - this.playChannels = Collections.newSetFromMap(new ConcurrentHashMap<>()); - } - - // Must be fully qualified due to mixin not working in production without it - @SuppressWarnings("UnnecessaryQualifiedMemberReference") - @Redirect(method = "Lnet/minecraft/network/Connection;exceptionCaught(Lio/netty/channel/ChannelHandlerContext;Ljava/lang/Throwable;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;send(Lnet/minecraft/network/protocol/Packet;Lio/netty/util/concurrent/GenericFutureListener;)V")) - private void resendOnExceptionCaught(Connection self, Packet packet, GenericFutureListener> listener) { - PacketListener handler = this.packetListener; - - if (handler instanceof DisconnectPacketSource) { - this.send(((DisconnectPacketSource) handler).createDisconnectPacket(new TranslatableComponent("disconnect.genericReason")), listener); - } else { - this.disconnect(new TranslatableComponent("disconnect.genericReason")); // Don't send packet if we cannot send proper packets - } - } - - @Inject(method = "sendPacket", at = @At(value = "FIELD", target = "Lnet/minecraft/network/Connection;sentPackets:I")) - private void checkPacket(Packet packet, GenericFutureListener> callback, CallbackInfo ci) { - if (this.packetListener instanceof PacketCallbackListener) { - ((PacketCallbackListener) this.packetListener).sent(packet); - } - } - - @Inject(method = "channelInactive", at = @At("HEAD")) - private void handleDisconnect(ChannelHandlerContext channelHandlerContext, CallbackInfo ci) throws Exception { - if (packetListener instanceof NetworkHandlerExtensions) { // not the case for client/server query - ((NetworkHandlerExtensions) packetListener).getAddon().handleDisconnect(); - } - } - - @Override - public Collection getPendingChannelsNames() { - return this.playChannels; - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/EntityTrackerEntryMixin.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/EntityTrackerEntryMixin.java deleted file mode 100644 index 458bd9594..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/EntityTrackerEntryMixin.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.seibel.lod.forge.fabric.api.networking.v1.EntityTrackingEvents; -import net.minecraft.server.level.ServerEntity; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; - -@Mixin(ServerEntity.class) -abstract class EntityTrackerEntryMixin { - @Shadow - @Final - private Entity entity; - - @Inject(method = "addPairing", at = @At("HEAD")) - private void onStartTracking(ServerPlayer player, CallbackInfo ci) { - EntityTrackingEvents.START_TRACKING.invoker().onStartTracking(this.entity, player); - } - - @Inject(method = "removePairing", at = @At("TAIL")) - private void onStopTracking(ServerPlayer player, CallbackInfo ci) { - EntityTrackingEvents.STOP_TRACKING.invoker().onStopTracking(this.entity, player); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/PlayerManagerMixin.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/PlayerManagerMixin.java deleted file mode 100644 index 439001bf7..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/PlayerManagerMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.seibel.lod.forge.fabric.impl.networking.server.ServerNetworkingImpl; -import net.minecraft.network.Connection; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.players.PlayerList; - -@Mixin(PlayerList.class) -abstract class PlayerManagerMixin { - @Inject(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ClientboundCustomPayloadPacket;(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/network/FriendlyByteBuf;)V")) - private void handlePlayerConnection(Connection connection, ServerPlayer player, CallbackInfo ci) { - ServerNetworkingImpl.getAddon(player.connection).onClientReady(); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerLoginNetworkHandlerMixin.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerLoginNetworkHandlerMixin.java deleted file mode 100644 index 2af7f4c41..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerLoginNetworkHandlerMixin.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; -import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; -import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerLoginPacketListenerImpl; -import com.seibel.lod.forge.fabric.impl.networking.DisconnectPacketSource; -import com.seibel.lod.forge.fabric.impl.networking.NetworkHandlerExtensions; -import com.seibel.lod.forge.fabric.impl.networking.PacketCallbackListener; -import com.seibel.lod.forge.fabric.impl.networking.server.ServerLoginNetworkAddon; - -@Mixin(ServerLoginPacketListenerImpl.class) -abstract class ServerLoginNetworkHandlerMixin implements NetworkHandlerExtensions, DisconnectPacketSource, PacketCallbackListener { - @Shadow - @Final - private MinecraftServer server; - - @Shadow - public abstract void handleAcceptedLogin(); - - @Unique - private ServerLoginNetworkAddon addon; - - @Inject(method = "", at = @At("RETURN")) - private void initAddon(CallbackInfo ci) { - this.addon = new ServerLoginNetworkAddon((ServerLoginPacketListenerImpl) (Object) this); - } - - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerLoginPacketListenerImpl;handleAcceptedLogin()V")) - private void handlePlayerJoin(ServerLoginPacketListenerImpl handler) { - // Do not accept the player, thereby moving into play stage until all login futures being waited on are completed - if (this.addon.queryTick()) { - this.handleAcceptedLogin(); - } - } - - @Inject(method = "handleCustomQueryPacket", at = @At("HEAD"), cancellable = true) - private void handleCustomPayloadReceivedAsync(ServerboundCustomQueryPacket packet, CallbackInfo ci) { - // Handle queries - if (this.addon.handle(packet)) { - ci.cancel(); - } - } - - @Redirect(method = "handleAcceptedLogin", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getCompressionThreshold()I", ordinal = 0)) - private int removeLateCompressionPacketSending(MinecraftServer server) { - return -1; - } - - @Inject(method = "onDisconnect", at = @At("HEAD")) - private void handleDisconnection(Component reason, CallbackInfo ci) { - this.addon.handleDisconnect(); - } - - @Inject(method = "placeNewPlayer", at = @At("HEAD")) - private void handlePlayTransitionNormal(ServerPlayer player, CallbackInfo ci) { - this.addon.handlePlayTransition(); - } - - @Override - public void sent(Packet packet) { - if (packet instanceof ClientboundCustomQueryPacket) { - this.addon.registerOutgoingPacket((ClientboundCustomQueryPacket) packet); - } - } - - @Override - public ServerLoginNetworkAddon getAddon() { - return this.addon; - } - - @Override - public Packet createDisconnectPacket(Component message) { - return new ClientboundLoginDisconnectPacket(message); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerPlayNetworkHandlerMixin.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerPlayNetworkHandlerMixin.java deleted file mode 100644 index bfaa0507a..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/ServerPlayNetworkHandlerMixin.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import net.minecraft.network.Connection; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; -import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import com.seibel.lod.forge.fabric.impl.networking.DisconnectPacketSource; -import com.seibel.lod.forge.fabric.impl.networking.NetworkHandlerExtensions; -import com.seibel.lod.forge.fabric.impl.networking.server.ServerPlayNetworkAddon; - -// We want to apply a bit earlier than other mods which may not use us in order to prevent refCount issues -@Mixin(value = ServerGamePacketListenerImpl.class, priority = 999) -abstract class ServerPlayNetworkHandlerMixin implements NetworkHandlerExtensions, DisconnectPacketSource { - @Shadow - @Final - private MinecraftServer server; - @Shadow - @Final - public Connection connection; - - @Unique - private ServerPlayNetworkAddon addon; - - @Inject(method = "", at = @At("RETURN")) - private void initAddon(CallbackInfo ci) { - this.addon = new ServerPlayNetworkAddon((ServerGamePacketListenerImpl) (Object) this, this.server); - // 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 - this.addon.lateInit(); - } - - @Inject(method = "handleCustomPayload", at = @At("HEAD"), cancellable = true) - private void handleCustomPayloadReceivedAsync(ServerboundCustomPayloadPacket packet, CallbackInfo ci) { - if (this.addon.handle(packet)) { - ci.cancel(); - } - } - - @Inject(method = "onDisconnect", at = @At("HEAD")) - private void handleDisconnection(Component reason, CallbackInfo ci) { - this.addon.handleDisconnect(); - } - - @Override - public ServerPlayNetworkAddon getAddon() { - return this.addon; - } - - @Override - public Packet createDisconnectPacket(Component message) { - return new ClientboundDisconnectPacket(message); - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ConnectScreenAccessor.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ConnectScreenAccessor.java deleted file mode 100644 index 3df191246..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ConnectScreenAccessor.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.client.gui.screens.ConnectScreen; -import net.minecraft.network.Connection; - -@Mixin(ConnectScreen.class) -public interface ConnectScreenAccessor { - @Accessor - Connection getConnection(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/CustomPayloadC2SPacketAccessor.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/CustomPayloadC2SPacketAccessor.java deleted file mode 100644 index e5547daba..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/CustomPayloadC2SPacketAccessor.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket; -import net.minecraft.resources.ResourceLocation; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ServerboundCustomPayloadPacket.class) -public interface CustomPayloadC2SPacketAccessor { - @Accessor - ResourceLocation getIdentifier(); - - @Accessor - FriendlyByteBuf getData(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/EntityTrackerAccessor.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/EntityTrackerAccessor.java deleted file mode 100644 index 89be357bd..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/EntityTrackerAccessor.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor; - -import java.util.Set; -import net.minecraft.server.network.ServerPlayerConnection; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(targets = "net/minecraft/server/level/ChunkMap$TrackedEntity") -public interface EntityTrackerAccessor { - @Accessor("seenBy") - Set getPlayersTracking(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/LoginQueryResponseC2SPacketAccessor.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/LoginQueryResponseC2SPacketAccessor.java deleted file mode 100644 index 438abc5f9..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/LoginQueryResponseC2SPacketAccessor.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ServerboundCustomQueryPacket.class) -public interface LoginQueryResponseC2SPacketAccessor { - @Accessor - int getTransactionId(); - - @Nullable - @Accessor - FriendlyByteBuf getData(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/MinecraftClientAccessor.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/MinecraftClientAccessor.java deleted file mode 100644 index 3ee7920c2..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/MinecraftClientAccessor.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor; - -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.client.Minecraft; -import net.minecraft.network.Connection; - -@Mixin(Minecraft.class) -public interface MinecraftClientAccessor { - @Nullable - @Accessor("pendingConnection") - Connection getConnection(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ServerLoginNetworkHandlerAccessor.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ServerLoginNetworkHandlerAccessor.java deleted file mode 100644 index d6fe32d51..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ServerLoginNetworkHandlerAccessor.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginPacketListenerImpl; - -@Mixin(ServerLoginPacketListenerImpl.class) -public interface ServerLoginNetworkHandlerAccessor { - @Accessor - MinecraftServer getServer(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ThreadedAnvilChunkStorageAccessor.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ThreadedAnvilChunkStorageAccessor.java deleted file mode 100644 index 347f9894e..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/accessor/ThreadedAnvilChunkStorageAccessor.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.server.level.ChunkMap; - -@Mixin(ChunkMap.class) -public interface ThreadedAnvilChunkStorageAccessor { - @Accessor - Int2ObjectMap getEntityMap(); -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientLoginNetworkHandlerMixin.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientLoginNetworkHandlerMixin.java deleted file mode 100644 index 9fd4dc959..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientLoginNetworkHandlerMixin.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.client; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.seibel.lod.forge.fabric.impl.networking.NetworkHandlerExtensions; -import com.seibel.lod.forge.fabric.impl.networking.client.ClientLoginNetworkAddon; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; - -@Mixin(ClientHandshakePacketListenerImpl.class) -abstract class ClientLoginNetworkHandlerMixin implements NetworkHandlerExtensions { - @Shadow - @Final - private Minecraft minecraft; - - @Unique - private ClientLoginNetworkAddon addon; - - @Inject(method = "", at = @At("RETURN")) - private void initAddon(CallbackInfo ci) { - this.addon = new ClientLoginNetworkAddon((ClientHandshakePacketListenerImpl) (Object) this, this.minecraft); - } - - @Inject(method = "handleCustomQuery", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V", remap = false, shift = At.Shift.AFTER), cancellable = true) - private void handleQueryRequest(ClientboundCustomQueryPacket packet, CallbackInfo ci) { - if (this.addon.handlePacket(packet)) { - ci.cancel(); - } - } - - @Inject(method = "onDisconnect", at = @At("HEAD")) - private void invokeLoginDisconnectEvent(Component reason, CallbackInfo ci) { - this.addon.handleDisconnect(); - } - - @Inject(method = "handleGameProfile", at = @At("HEAD")) - private void handlePlayTransition(CallbackInfo ci) { - addon.handlePlayTransition(); - } - - @Override - public ClientLoginNetworkAddon getAddon() { - return this.addon; - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientPlayNetworkHandlerMixin.java b/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientPlayNetworkHandlerMixin.java deleted file mode 100644 index e399e6807..000000000 --- a/forge/src/main/java/com/seibel/lod/forge/mixins/fabric/mixin/networking/client/ClientPlayNetworkHandlerMixin.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 com.seibel.lod.forge.mixins.fabric.mixin.networking.client; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.seibel.lod.forge.fabric.impl.networking.NetworkHandlerExtensions; -import com.seibel.lod.forge.fabric.impl.networking.client.ClientNetworkingImpl; -import com.seibel.lod.forge.fabric.impl.networking.client.ClientPlayNetworkAddon; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; -import net.minecraft.network.protocol.game.ClientboundLoginPacket; - -// We want to apply a bit earlier than other mods which may not use us in order to prevent refCount issues - -@Mixin(value = ClientPacketListener.class, priority = 999) -abstract class ClientPlayNetworkHandlerMixin implements NetworkHandlerExtensions { - @Shadow - private Minecraft minecraft; - - @Unique - private ClientPlayNetworkAddon addon; - - @Inject(method = "", at = @At("RETURN")) - private void initAddon(CallbackInfo ci) { - this.addon = new ClientPlayNetworkAddon((ClientPacketListener) (Object) this, this.minecraft); - // 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(); - } - - @Inject(method = "handleLogin", at = @At("RETURN")) - private void handleServerPlayReady(ClientboundLoginPacket packet, CallbackInfo ci) { - this.addon.onServerReady(); - } - - @Inject(method = "handleCustomPayload", at = @At("HEAD"), cancellable = true) - private void handleCustomPayload(ClientboundCustomPayloadPacket packet, CallbackInfo ci) { - if (this.addon.handle(packet)) { - ci.cancel(); - } - } - - @Inject(method = "onDisconnect", at = @At("HEAD")) - private void handleDisconnection(Component reason, CallbackInfo ci) { - this.addon.handleDisconnect(); - } - - @Override - public ClientPlayNetworkAddon getAddon() { - return this.addon; - } -} diff --git a/forge/src/main/java/com/seibel/lod/forge/networking/NetworkHandler.java b/forge/src/main/java/com/seibel/lod/forge/networking/NetworkHandler.java index 2f8a1063d..6d7ce4043 100644 --- a/forge/src/main/java/com/seibel/lod/forge/networking/NetworkHandler.java +++ b/forge/src/main/java/com/seibel/lod/forge/networking/NetworkHandler.java @@ -21,8 +21,8 @@ package com.seibel.lod.forge.networking; import com.seibel.lod.common.networking.NetworkInterface; import com.seibel.lod.common.networking.Networking; -import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayNetworking; -import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking; +//import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayNetworking; +//import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking; /** * @author Ran @@ -30,15 +30,15 @@ import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking; public class NetworkHandler implements NetworkInterface { @Override public void register_Client() { - ClientPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (client, handler, buf, responseSender) -> { - com.seibel.lod.common.networking.NetworkHandler.receivePacketClient(client, handler, buf); - }); +// ClientPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (client, handler, buf, responseSender) -> { +// com.seibel.lod.common.networking.NetworkHandler.receivePacketClient(client, handler, buf); +// }); } @Override public void register_Server() { - ServerPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (server, player, handler, buf, responseSender) -> { - com.seibel.lod.common.networking.NetworkHandler.receivePacketServer(server, player, handler, buf); - }); +// ServerPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (server, player, handler, buf, responseSender) -> { +// com.seibel.lod.common.networking.NetworkHandler.receivePacketServer(server, player, handler, buf); +// }); } }