diff --git a/src/main/java/net/minecraftforge/fml/ModLoader.java b/src/main/java/net/minecraftforge/fml/ModLoader.java
index 473b61ca9d..3887c498db 100644
--- a/src/main/java/net/minecraftforge/fml/ModLoader.java
+++ b/src/main/java/net/minecraftforge/fml/ModLoader.java
@@ -31,6 +31,7 @@ import net.minecraftforge.fml.loading.FMLPaths;
import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
+import net.minecraftforge.fml.network.FMLNetworkConstants;
import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.forgespi.language.IModLanguageProvider;
import net.minecraftforge.registries.GameData;
@@ -99,6 +100,7 @@ public class ModLoader
this.loadingModList = FMLLoader.getLoadingModList();
this.loadingExceptions = FMLLoader.getLoadingModList().
getErrors().stream().flatMap(ModLoadingException::fromEarlyException).collect(Collectors.toList());
+ LOGGER.info(CORE, "Loading Network data for FML net version: {}", FMLNetworkConstants.NETVERSION);
}
public static ModLoader get()
diff --git a/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java b/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java
index 1e9a7fdc7d..7a8cb91c98 100644
--- a/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java
+++ b/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java
@@ -19,7 +19,6 @@
package net.minecraftforge.fml.network;
-import io.netty.util.AttributeKey;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.NetHandlerLoginServer;
@@ -27,9 +26,7 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.config.ConfigTracker;
import net.minecraftforge.fml.network.simple.SimpleChannel;
-import net.minecraftforge.fml.util.ThreeConsumer;
import net.minecraftforge.registries.ForgeRegistry;
-import net.minecraftforge.registries.RegistryManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
@@ -37,8 +34,12 @@ import org.apache.logging.log4j.MarkerManager;
import com.google.common.collect.Maps;
-import java.util.*;
-import java.util.function.BiConsumer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.function.Supplier;
import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
@@ -47,9 +48,9 @@ import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
* Instance responsible for handling the overall FML network handshake.
*
*
An instance is created during {@link net.minecraft.network.handshake.client.CPacketHandshake} handling, and attached
- * to the {@link NetworkManager#channel} via {@link #FML_HANDSHAKE_HANDLER_ATTRIBUTE_KEY}.
+ * to the {@link NetworkManager#channel} via {@link FMLNetworkConstants#FML_HANDSHAKE_HANDLER}.
*
- *
The {@link #channel} is a {@link SimpleChannel} with standard messages flowing in both directions.
+ *
The {@link FMLNetworkConstants#handshakeChannel} is a {@link SimpleChannel} with standard messages flowing in both directions.
*
*
The {@link #loginWrapper} transforms these messages into {@link net.minecraft.network.login.client.CPacketCustomPayloadLogin}
* and {@link net.minecraft.network.login.server.SPacketCustomPayloadLogin} compatible messages, by means of wrapping.
@@ -76,75 +77,10 @@ import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
public class FMLHandshakeHandler {
static final Marker FMLHSMARKER = MarkerManager.getMarker("FMLHANDSHAKE").setParents(FMLNetworkConstants.NETWORK);
private static final Logger LOGGER = LogManager.getLogger();
- static final ResourceLocation FML_HANDSHAKE_RESOURCE = new ResourceLocation("fml:handshake");
- private static final AttributeKey FML_HANDSHAKE_HANDLER_ATTRIBUTE_KEY = AttributeKey.newInstance("fml:handshake");
private static final FMLLoginWrapper loginWrapper = new FMLLoginWrapper();
- private static SimpleChannel channel;
+
static {
- channel = NetworkRegistry.ChannelBuilder.named(FML_HANDSHAKE_RESOURCE).
- clientAcceptedVersions(a -> true).
- serverAcceptedVersions(a -> true).
- networkProtocolVersion(() -> FMLNetworkConstants.NETVERSION).
- simpleChannel();
- channel.messageBuilder(FMLHandshakeMessages.C2SAcknowledge.class, 99).
- loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
- decoder(FMLHandshakeMessages.C2SAcknowledge::decode).
- encoder(FMLHandshakeMessages.C2SAcknowledge::encode).
- consumer(indexFirst(FMLHandshakeHandler::handleClientAck)).
- add();
- channel.messageBuilder(FMLHandshakeMessages.S2CModList.class, 1).
- loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
- decoder(FMLHandshakeMessages.S2CModList::decode).
- encoder(FMLHandshakeMessages.S2CModList::encode).
- markAsLoginPacket().
- consumer(biConsumerFor(FMLHandshakeHandler::handleServerModListOnClient)).
- add();
- channel.messageBuilder(FMLHandshakeMessages.C2SModListReply.class, 2).
- loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
- decoder(FMLHandshakeMessages.C2SModListReply::decode).
- encoder(FMLHandshakeMessages.C2SModListReply::encode).
- consumer(indexFirst(FMLHandshakeHandler::handleClientModListOnServer)).
- add();
- channel.messageBuilder(FMLHandshakeMessages.S2CRegistry.class, 3).
- loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
- decoder(FMLHandshakeMessages.S2CRegistry::decode).
- encoder(FMLHandshakeMessages.S2CRegistry::encode).
- buildLoginPacketList(RegistryManager::generateRegistryPackets). //TODO: Make this non-static, and store a cache on the client.
- consumer(biConsumerFor(FMLHandshakeHandler::handleRegistryMessage)).
- add();
- channel.messageBuilder(FMLHandshakeMessages.S2CConfigData.class, 4).
- loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
- decoder(FMLHandshakeMessages.S2CConfigData::decode).
- encoder(FMLHandshakeMessages.S2CConfigData::encode).
- buildLoginPacketList(ConfigTracker.INSTANCE::syncConfigs).
- consumer(biConsumerFor(FMLHandshakeHandler::handleConfigSync)).
- add();
- }
-
- /**
- * Transforms a two-argument instance method reference into a {@link BiConsumer} based on the {@link #getHandshake(Supplier)} function.
- *
- * @param consumer A two argument instance method reference
- * @param message type
- * @return A {@link BiConsumer} for use in message handling
- */
- private static BiConsumer> biConsumerFor(ThreeConsumer> consumer)
- {
- return (m, c) -> ThreeConsumer.bindArgs(consumer, m, c).accept(getHandshake(c));
- }
-
- /**
- * Transforms a two-argument instance method reference into a {@link BiConsumer} {@link #biConsumerFor(ThreeConsumer)}, first calling the {@link #handleIndexedMessage(FMLHandshakeMessages.LoginIndexedMessage, Supplier)}
- * method to handle index tracking. Used for client to server replies.
- * @param next The method reference to call after index handling
- * @param message type
- * @return A {@link BiConsumer} for use in message handling
- */
- private static BiConsumer> indexFirst(ThreeConsumer> next)
- {
- final BiConsumer> loginIndexedMessageSupplierBiConsumer = biConsumerFor(FMLHandshakeHandler::handleIndexedMessage);
- return loginIndexedMessageSupplierBiConsumer.andThen(biConsumerFor(next));
}
/**
@@ -155,22 +91,12 @@ public class FMLHandshakeHandler {
* @param direction The {@link NetworkDirection} for this connection: {@link NetworkDirection#LOGIN_TO_SERVER} or {@link NetworkDirection#LOGIN_TO_CLIENT}
*/
static void registerHandshake(NetworkManager manager, NetworkDirection direction) {
- manager.channel().attr(FML_HANDSHAKE_HANDLER_ATTRIBUTE_KEY).compareAndSet(null, new FMLHandshakeHandler(manager, direction));
- }
-
- /**
- * Retrieve the handshake from the {@link NetworkEvent.Context}
- *
- * @param contextSupplier the {@link NetworkEvent.Context}
- * @return The handshake handler for the connection
- */
- private static FMLHandshakeHandler getHandshake(Supplier contextSupplier) {
- return contextSupplier.get().attr(FML_HANDSHAKE_HANDLER_ATTRIBUTE_KEY).get();
+ manager.channel().attr(FMLNetworkConstants.FML_HANDSHAKE_HANDLER).compareAndSet(null, new FMLHandshakeHandler(manager, direction));
}
static boolean tickLogin(NetworkManager networkManager)
{
- return networkManager.channel().attr(FML_HANDSHAKE_HANDLER_ATTRIBUTE_KEY).get().tickServer();
+ return networkManager.channel().attr(FMLNetworkConstants.FML_HANDSHAKE_HANDLER).get().tickServer();
}
private List messageList;
@@ -197,7 +123,7 @@ public class FMLHandshakeHandler {
}
}
- private void handleServerModListOnClient(FMLHandshakeMessages.S2CModList serverModList, Supplier c)
+ void handleServerModListOnClient(FMLHandshakeMessages.S2CModList serverModList, Supplier c)
{
LOGGER.debug(FMLHSMARKER, "Logging into server with mod list [{}]", String.join(", ", serverModList.getModList()));
boolean accepted = NetworkRegistry.validateClientChannels(serverModList.getChannels());
@@ -207,18 +133,18 @@ public class FMLHandshakeHandler {
c.get().getNetworkManager().closeChannel(new TextComponentString("Connection closed - mismatched mod channel list"));
return;
}
- channel.reply(new FMLHandshakeMessages.C2SModListReply(), c.get());
+ FMLNetworkConstants.handshakeChannel.reply(new FMLHandshakeMessages.C2SModListReply(), c.get());
LOGGER.debug(FMLHSMARKER, "Accepted server connection");
// Set the modded marker on the channel so we know we got packets
- c.get().getNetworkManager().channel().attr(FMLNetworkConstants.FML_MARKER).set(FMLNetworkConstants.NETVERSION);
+ c.get().getNetworkManager().channel().attr(FMLNetworkConstants.FML_NETVERSION).set(FMLNetworkConstants.NETVERSION);
this.registriesToReceive = new HashSet<>(serverModList.getRegistries());
this.registrySnapshots = Maps.newHashMap();
LOGGER.debug(REGISTRIES, "Expecting {} registries: {}", ()->this.registriesToReceive.size(), ()->this.registriesToReceive);
}
- private void handleIndexedMessage(MSG message, Supplier c)
+ void handleIndexedMessage(MSG message, Supplier c)
{
LOGGER.debug(FMLHSMARKER, "Received client indexed reply {} of type {}", message.getLoginIndex(), message.getClass().getName());
boolean removed = this.sentMessages.removeIf(i->i==message.getLoginIndex());
@@ -227,7 +153,7 @@ public class FMLHandshakeHandler {
}
}
- private void handleClientModListOnServer(FMLHandshakeMessages.C2SModListReply clientModList, Supplier c)
+ void handleClientModListOnServer(FMLHandshakeMessages.C2SModListReply clientModList, Supplier c)
{
LOGGER.debug(FMLHSMARKER, "Received client connection with modlist [{}]", String.join(", ", clientModList.getModList()));
boolean accepted = NetworkRegistry.validateServerChannels(clientModList.getChannels());
@@ -240,12 +166,12 @@ public class FMLHandshakeHandler {
LOGGER.debug(FMLHSMARKER, "Accepted client connection mod list");
}
- private void handleRegistryMessage(final FMLHandshakeMessages.S2CRegistry registryPacket, final Supplier contextSupplier){
+ void handleRegistryMessage(final FMLHandshakeMessages.S2CRegistry registryPacket, final Supplier contextSupplier){
LOGGER.debug(FMLHSMARKER,"Received registry packet for {}", registryPacket.getRegistryName());
this.registriesToReceive.remove(registryPacket.getRegistryName());
this.registrySnapshots.put(registryPacket.getRegistryName(), registryPacket.getSnapshot());
contextSupplier.get().setPacketHandled(true);
- channel.reply(new FMLHandshakeMessages.C2SAcknowledge(), contextSupplier.get());
+ FMLNetworkConstants.handshakeChannel.reply(new FMLHandshakeMessages.C2SAcknowledge(), contextSupplier.get());
if (this.registriesToReceive.isEmpty()) {
//TODO: @cpw injectSnapshot Needs to be on the world thread. And maybe block the network/login so we don't get world data before we finish?
@@ -253,16 +179,16 @@ public class FMLHandshakeHandler {
}
}
- private void handleClientAck(final FMLHandshakeMessages.C2SAcknowledge msg, final Supplier contextSupplier) {
+ void handleClientAck(final FMLHandshakeMessages.C2SAcknowledge msg, final Supplier contextSupplier) {
LOGGER.debug(FMLHSMARKER, "Received acknowledgement from client");
contextSupplier.get().setPacketHandled(true);
}
- private void handleConfigSync(final FMLHandshakeMessages.S2CConfigData msg, final Supplier contextSupplier) {
+ void handleConfigSync(final FMLHandshakeMessages.S2CConfigData msg, final Supplier contextSupplier) {
LOGGER.debug(FMLHSMARKER, "Received config sync from server");
ConfigTracker.INSTANCE.receiveSyncedConfig(msg, contextSupplier);
contextSupplier.get().setPacketHandled(true);
- channel.reply(new FMLHandshakeMessages.C2SAcknowledge(), contextSupplier.get());
+ FMLNetworkConstants.handshakeChannel.reply(new FMLHandshakeMessages.C2SAcknowledge(), contextSupplier.get());
}
/**
* FML will send packets, from Server to Client, from the messages queue until the queue is drained. Each message
@@ -289,7 +215,7 @@ public class FMLHandshakeHandler {
// we're done when sentMessages is empty
if (sentMessages.isEmpty() && packetPosition >= messageList.size()-1) {
// clear ourselves - we're done!
- this.manager.channel().attr(FML_HANDSHAKE_HANDLER_ATTRIBUTE_KEY).set(null);
+ this.manager.channel().attr(FMLNetworkConstants.FML_HANDSHAKE_HANDLER).set(null);
LOGGER.debug(FMLHSMARKER, "Handshake complete!");
return true;
}
diff --git a/src/main/java/net/minecraftforge/fml/network/FMLHandshakeMessages.java b/src/main/java/net/minecraftforge/fml/network/FMLHandshakeMessages.java
index de4cc93fc0..373df14f61 100644
--- a/src/main/java/net/minecraftforge/fml/network/FMLHandshakeMessages.java
+++ b/src/main/java/net/minecraftforge/fml/network/FMLHandshakeMessages.java
@@ -21,7 +21,6 @@ package net.minecraftforge.fml.network;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.common.util.HexDumper;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import net.minecraftforge.registries.ForgeRegistry;
diff --git a/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java b/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java
index d282839d29..682c10e70c 100644
--- a/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java
+++ b/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java
@@ -49,7 +49,7 @@ public class FMLLoginWrapper {
private void wrapperReceived(final T packet) {
final NetworkEvent.Context wrappedContext = packet.getSource().get();
final PacketBuffer payload = packet.getPayload();
- ResourceLocation targetNetworkReceiver = FMLHandshakeHandler.FML_HANDSHAKE_RESOURCE;
+ ResourceLocation targetNetworkReceiver = FMLNetworkConstants.FML_HANDSHAKE_RESOURCE;
PacketBuffer data = null;
if (payload != null) {
targetNetworkReceiver = payload.readResourceLocation();
diff --git a/src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java b/src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java
index 9c02758d2d..0c2dbe298e 100644
--- a/src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java
+++ b/src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java
@@ -20,6 +20,8 @@
package net.minecraftforge.fml.network;
import io.netty.util.AttributeKey;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.fml.network.simple.SimpleChannel;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
@@ -32,6 +34,12 @@ public class FMLNetworkConstants
public static final int FMLNETVERSION = 2;
public static final String NETVERSION = FMLNETMARKER + FMLNETVERSION;
public static final String NOVERSION = "NONE";
+
static final Marker NETWORK = MarkerManager.getMarker("FMLNETWORK");
- static final AttributeKey FML_MARKER = AttributeKey.valueOf("fml:marker");
+ static final AttributeKey FML_NETVERSION = AttributeKey.valueOf("fml:netversion");
+ static final AttributeKey FML_HANDSHAKE_HANDLER = AttributeKey.valueOf("fml:handshake");
+ static final ResourceLocation FML_HANDSHAKE_RESOURCE = new ResourceLocation("fml:handshake");
+ static final ResourceLocation FML_PLAY_RESOURCE = new ResourceLocation("fml:play");
+ static final SimpleChannel handshakeChannel = NetworkInitialization.getHandshakeChannel();
+ static final SimpleChannel playChannel = NetworkInitialization.getPlayChannel();
}
diff --git a/src/main/java/net/minecraftforge/fml/network/FMLPlayHandler.java b/src/main/java/net/minecraftforge/fml/network/FMLPlayHandler.java
deleted file mode 100644
index 052f03e1ff..0000000000
--- a/src/main/java/net/minecraftforge/fml/network/FMLPlayHandler.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Minecraft Forge
- * Copyright (c) 2016-2019.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package net.minecraftforge.fml.network;
-
-import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.fml.network.simple.SimpleChannel;
-
-public class FMLPlayHandler
-{
- public static final SimpleChannel channel = NetworkRegistry.ChannelBuilder
- .named(new ResourceLocation("fml", "play"))
- .clientAcceptedVersions(a -> true)
- .serverAcceptedVersions(a -> true)
- .networkProtocolVersion(() -> FMLNetworkConstants.NETVERSION)
- .simpleChannel();
- static
- {
- channel.registerMessage(0, FMLPlayMessages.SpawnEntity.class, FMLPlayMessages.SpawnEntity::encode, FMLPlayMessages.SpawnEntity::decode, FMLPlayMessages.SpawnEntity::handle);
- channel.registerMessage(1, FMLPlayMessages.OpenContainer.class, FMLPlayMessages.OpenContainer::encode, FMLPlayMessages.OpenContainer::decode, FMLPlayMessages.OpenContainer::handle);
- }
-}
diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java b/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java
index f76e9e812d..4d9f27aaf6 100644
--- a/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java
+++ b/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java
@@ -52,14 +52,14 @@ public class NetworkHooks
public static ConnectionType getConnectionType(final Supplier connection)
{
- return ConnectionType.forVersionFlag(connection.get().channel().attr(FMLNetworkConstants.FML_MARKER).get());
+ return ConnectionType.forVersionFlag(connection.get().channel().attr(FMLNetworkConstants.FML_NETVERSION).get());
}
public static Packet> getEntitySpawningPacket(Entity entity)
{
if (!entity.getType().usesVanillaSpawning())
{
- return FMLPlayHandler.channel.toVanillaPacket(new FMLPlayMessages.SpawnEntity(entity), NetworkDirection.PLAY_TO_CLIENT);
+ return FMLNetworkConstants.playChannel.toVanillaPacket(new FMLPlayMessages.SpawnEntity(entity), NetworkDirection.PLAY_TO_CLIENT);
}
return null;
}
@@ -71,14 +71,14 @@ public class NetworkHooks
public static void registerServerLoginChannel(NetworkManager manager, CPacketHandshake packet)
{
- manager.channel().attr(FMLNetworkConstants.FML_MARKER).set(packet.getFMLVersion());
+ manager.channel().attr(FMLNetworkConstants.FML_NETVERSION).set(packet.getFMLVersion());
FMLHandshakeHandler.registerHandshake(manager, NetworkDirection.LOGIN_TO_CLIENT);
}
public static void registerClientLoginChannel(NetworkManager manager)
{
if (manager == null || manager.channel() == null) return;
- manager.channel().attr(FMLNetworkConstants.FML_MARKER).set(FMLNetworkConstants.NOVERSION);
+ manager.channel().attr(FMLNetworkConstants.FML_NETVERSION).set(FMLNetworkConstants.NOVERSION);
FMLHandshakeHandler.registerHandshake(manager, NetworkDirection.LOGIN_TO_SERVER);
}
@@ -167,7 +167,7 @@ public class NetworkHooks
throw new IllegalArgumentException("Invalid PacketBuffer for openGui, found "+ output.readableBytes()+ " bytes");
}
FMLPlayMessages.OpenContainer msg = new FMLPlayMessages.OpenContainer(id, openContainerId, output);
- FMLPlayHandler.channel.sendTo(msg, player.connection.getNetworkManager(), NetworkDirection.PLAY_TO_CLIENT);
+ FMLNetworkConstants.playChannel.sendTo(msg, player.connection.getNetworkManager(), NetworkDirection.PLAY_TO_CLIENT);
Container c = containerSupplier.createContainer(player.inventory, player);
player.openContainer = c;
diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkInitialization.java b/src/main/java/net/minecraftforge/fml/network/NetworkInitialization.java
new file mode 100644
index 0000000000..b9d7c9000c
--- /dev/null
+++ b/src/main/java/net/minecraftforge/fml/network/NetworkInitialization.java
@@ -0,0 +1,139 @@
+/*
+ * Minecraft Forge
+ * Copyright (c) 2016-2019.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package net.minecraftforge.fml.network;
+
+import net.minecraftforge.fml.config.ConfigTracker;
+import net.minecraftforge.fml.network.simple.SimpleChannel;
+import net.minecraftforge.fml.util.ThreeConsumer;
+import net.minecraftforge.registries.RegistryManager;
+
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+
+class NetworkInitialization {
+
+ public static SimpleChannel getHandshakeChannel() {
+ SimpleChannel handshakeChannel = NetworkRegistry.ChannelBuilder.
+ named(FMLNetworkConstants.FML_HANDSHAKE_RESOURCE).
+ clientAcceptedVersions(a -> true).
+ serverAcceptedVersions(a -> true).
+ networkProtocolVersion(() -> FMLNetworkConstants.NETVERSION).
+ simpleChannel();
+
+ handshakeChannel.messageBuilder(FMLHandshakeMessages.C2SAcknowledge.class, 99).
+ loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
+ decoder(FMLHandshakeMessages.C2SAcknowledge::decode).
+ encoder(FMLHandshakeMessages.C2SAcknowledge::encode).
+ consumer(indexFirst(FMLHandshakeHandler::handleClientAck)).
+ add();
+
+ handshakeChannel.messageBuilder(FMLHandshakeMessages.S2CModList.class, 1).
+ loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
+ decoder(FMLHandshakeMessages.S2CModList::decode).
+ encoder(FMLHandshakeMessages.S2CModList::encode).
+ markAsLoginPacket().
+ consumer(biConsumerFor(FMLHandshakeHandler::handleServerModListOnClient)).
+ add();
+
+ handshakeChannel.messageBuilder(FMLHandshakeMessages.C2SModListReply.class, 2).
+ loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
+ decoder(FMLHandshakeMessages.C2SModListReply::decode).
+ encoder(FMLHandshakeMessages.C2SModListReply::encode).
+ consumer(indexFirst(FMLHandshakeHandler::handleClientModListOnServer)).
+ add();
+
+ handshakeChannel.messageBuilder(FMLHandshakeMessages.S2CRegistry.class, 3).
+ loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
+ decoder(FMLHandshakeMessages.S2CRegistry::decode).
+ encoder(FMLHandshakeMessages.S2CRegistry::encode).
+ buildLoginPacketList(RegistryManager::generateRegistryPackets). //TODO: Make this non-static, and store a cache on the client.
+ consumer(biConsumerFor(FMLHandshakeHandler::handleRegistryMessage)).
+ add();
+
+ handshakeChannel.messageBuilder(FMLHandshakeMessages.S2CConfigData.class, 4).
+ loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
+ decoder(FMLHandshakeMessages.S2CConfigData::decode).
+ encoder(FMLHandshakeMessages.S2CConfigData::encode).
+ buildLoginPacketList(ConfigTracker.INSTANCE::syncConfigs).
+ consumer(biConsumerFor(FMLHandshakeHandler::handleConfigSync)).
+ add();
+
+ return handshakeChannel;
+ }
+
+ public static SimpleChannel getPlayChannel() {
+ SimpleChannel playChannel = NetworkRegistry.ChannelBuilder
+ .named(FMLNetworkConstants.FML_PLAY_RESOURCE)
+ .clientAcceptedVersions(a -> true)
+ .serverAcceptedVersions(a -> true)
+ .networkProtocolVersion(() -> FMLNetworkConstants.NETVERSION)
+ .simpleChannel();
+
+ playChannel.messageBuilder(FMLPlayMessages.SpawnEntity.class, 0).
+ decoder(FMLPlayMessages.SpawnEntity::decode).
+ encoder(FMLPlayMessages.SpawnEntity::encode).
+ consumer(FMLPlayMessages.SpawnEntity::handle).
+ add();
+
+ playChannel.messageBuilder(FMLPlayMessages.OpenContainer.class,1).
+ decoder(FMLPlayMessages.OpenContainer::decode).
+ encoder(FMLPlayMessages.OpenContainer::encode).
+ consumer(FMLPlayMessages.OpenContainer::handle).
+ add();
+
+ return playChannel;
+ }
+
+
+ /**
+ * Transforms a two-argument instance method reference into a {@link BiConsumer} based on the {@link #getHandshake(Supplier)} function.
+ *
+ * @param consumer A two argument instance method reference
+ * @param message type
+ * @return A {@link BiConsumer} for use in message handling
+ */
+ private static BiConsumer> biConsumerFor(ThreeConsumer> consumer)
+ {
+ return (m, c) -> ThreeConsumer.bindArgs(consumer, m, c).accept(getHandshake(c));
+ }
+
+ /**
+ * Transforms a two-argument instance method reference into a {@link BiConsumer} {@link #biConsumerFor(ThreeConsumer)}, first calling the {@link #handleIndexedMessage(FMLHandshakeMessages.LoginIndexedMessage, Supplier)}
+ * method to handle index tracking. Used for client to server replies.
+ * @param next The method reference to call after index handling
+ * @param message type
+ * @return A {@link BiConsumer} for use in message handling
+ */
+ private static BiConsumer> indexFirst(ThreeConsumer> next)
+ {
+ final BiConsumer> loginIndexedMessageSupplierBiConsumer = biConsumerFor(FMLHandshakeHandler::handleIndexedMessage);
+ return loginIndexedMessageSupplierBiConsumer.andThen(biConsumerFor(next));
+ }
+
+ /**
+ * Retrieve the handshake from the {@link NetworkEvent.Context}
+ *
+ * @param contextSupplier the {@link NetworkEvent.Context}
+ * @return The handshake handler for the connection
+ */
+ private static FMLHandshakeHandler getHandshake(Supplier contextSupplier) {
+ return contextSupplier.get().attr(FMLNetworkConstants.FML_HANDSHAKE_HANDLER).get();
+ }
+}