mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-13 16:54:22 +00:00
Introduce a new feature that lets mods know if optional mods and optional network channels are present in the remote.
Allow connections from forge versions that don't have the vanilla splitter.
This commit is contained in:
1 parent
a95b968c13
commit
a4f7087b92
10 files changed
+172
-6
No files matched your search
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2021.
|
||||
*
|
||||
* 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 com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FMLConnectionData
|
||||
{
|
||||
private ImmutableList<String> modList;
|
||||
private ImmutableMap<ResourceLocation, String> channels;
|
||||
|
||||
/* package private */ FMLConnectionData(List<String> modList, Map<ResourceLocation, String> channels)
|
||||
{
|
||||
this.modList = ImmutableList.copyOf(modList);
|
||||
this.channels = ImmutableMap.copyOf(channels);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of mods present in the remote.
|
||||
* <b>WARNING: This list is not authoritative.
|
||||
* A mod missing from the list does not mean the mod isn't there,
|
||||
* and similarly a mod present in the list does not mean it is there.
|
||||
* People using hacked clients WILL hack the mod lists to make them look correct.
|
||||
* Do not use this as an anti-cheat feature!
|
||||
* </b>
|
||||
* @return An immutable list of MODIDs
|
||||
*/
|
||||
public ImmutableList<String> getModList()
|
||||
{
|
||||
return modList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of network channels present in the remote.
|
||||
* <b>WARNING: This list is not authoritative.
|
||||
* A channel missing from the list does not mean the remote won't accept packets with that channel ID,
|
||||
* and similarly a channel present in the list does not mean the remote won't ignore it.
|
||||
* People using hacked clients WILL hack the channel list to make it look correct.
|
||||
* Do not use this as an anti-cheat feature!
|
||||
* </b>
|
||||
* @return An immutable map of channel IDs and their respective protocol versions.
|
||||
*/
|
||||
public ImmutableMap<ResourceLocation, String> getChannels()
|
||||
{
|
||||
return channels;
|
||||
}
|
||||
}
|
||||
@@ -184,6 +184,8 @@ public class FMLHandshakeHandler {
|
||||
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_NETVERSION).set(FMLNetworkConstants.NETVERSION);
|
||||
c.get().getNetworkManager().channel().attr(FMLNetworkConstants.FML_CONNECTION_DATA)
|
||||
.set(new FMLConnectionData(serverModList.getModList(), serverModList.getChannels()));
|
||||
|
||||
this.registriesToReceive = new HashSet<>(serverModList.getRegistries());
|
||||
this.registrySnapshots = Maps.newHashMap();
|
||||
@@ -203,6 +205,8 @@ public class FMLHandshakeHandler {
|
||||
{
|
||||
LOGGER.debug(FMLHSMARKER, "Received client connection with modlist [{}]", String.join(", ", clientModList.getModList()));
|
||||
boolean accepted = NetworkRegistry.validateServerChannels(clientModList.getChannels());
|
||||
c.get().getNetworkManager().channel().attr(FMLNetworkConstants.FML_CONNECTION_DATA)
|
||||
.set(new FMLConnectionData(clientModList.getModList(), clientModList.getChannels()));
|
||||
c.get().setPacketHandled(true);
|
||||
if (!accepted) {
|
||||
LOGGER.error(FMLHSMARKER, "Terminating connection with client, mismatched mod list");
|
||||
|
||||
@@ -41,6 +41,7 @@ public class FMLNetworkConstants
|
||||
static final AttributeKey<String> FML_NETVERSION = AttributeKey.valueOf("fml:netversion");
|
||||
static final AttributeKey<FMLHandshakeHandler> FML_HANDSHAKE_HANDLER = AttributeKey.valueOf("fml:handshake");
|
||||
static final AttributeKey<FMLMCRegisterPacketHandler.ChannelList> FML_MC_REGISTRY = AttributeKey.valueOf("minecraft:netregistry");
|
||||
static final AttributeKey<FMLConnectionData> FML_CONNECTION_DATA = AttributeKey.valueOf("fml:conndata");
|
||||
static final ResourceLocation FML_HANDSHAKE_RESOURCE = new ResourceLocation("fml:handshake");
|
||||
static final ResourceLocation FML_PLAY_RESOURCE = new ResourceLocation("fml:play");
|
||||
static final ResourceLocation MC_REGISTER_RESOURCE = new ResourceLocation("minecraft:register");
|
||||
|
||||
@@ -53,6 +53,8 @@ import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
|
||||
import net.minecraftforge.fml.config.ConfigTracker;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class NetworkHooks
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -255,4 +257,10 @@ public class NetworkHooks
|
||||
FMLNetworkConstants.playChannel.sendTo(new FMLPlayMessages.SyncCustomTagTypes(customTagTypes), player.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FMLConnectionData getConnectionData(NetworkManager mgr)
|
||||
{
|
||||
return mgr.channel().attr(FMLNetworkConstants.FML_CONNECTION_DATA).get();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package net.minecraftforge.fml.network;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.eventbus.api.BusBuilder;
|
||||
@@ -108,4 +110,9 @@ public class NetworkInstance
|
||||
void dispatchEvent(final NetworkEvent networkEvent) {
|
||||
this.networkEventBus.post(networkEvent);
|
||||
}
|
||||
|
||||
public boolean isRemotePresent(NetworkManager manager) {
|
||||
FMLConnectionData connectionData = NetworkHooks.getConnectionData(manager);
|
||||
return connectionData != null && connectionData.getChannels().containsKey(channelName);
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,26 @@ public class NetworkRegistry
|
||||
@SuppressWarnings("RedundantStringConstructorCall")
|
||||
public static String ACCEPTVANILLA = new String("ALLOWVANILLA \uD83D\uDC93\uD83D\uDC93\uD83D\uDC93");
|
||||
|
||||
/**
|
||||
* Makes a version predicate that accepts connections to vanilla or without the channel.
|
||||
* @param protocolVersion The protocol version, which will be matched exactly.
|
||||
* @return A new predicate with the new conditions.
|
||||
*/
|
||||
public static Predicate<String> acceptMissingOr(final String protocolVersion)
|
||||
{
|
||||
return acceptMissingOr(protocolVersion::equals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a version predicate that accepts connections to vanilla or without the channel.
|
||||
* @param versionCheck The main version predicate, which should check the version number of the protocol.
|
||||
* @return A new predicate with the new conditions.
|
||||
*/
|
||||
public static Predicate<String> acceptMissingOr(Predicate<String> versionCheck)
|
||||
{
|
||||
return versionCheck.or(ABSENT::equals).or(ACCEPTVANILLA::equals);
|
||||
}
|
||||
|
||||
public static List<String> getServerNonVanillaNetworkMods()
|
||||
{
|
||||
return listRejectedVanillaMods(NetworkInstance::tryClientVersionOnServer);
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
|
||||
package net.minecraftforge.fml.network.event;
|
||||
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraftforge.fml.network.NetworkEvent;
|
||||
import net.minecraftforge.fml.network.NetworkHooks;
|
||||
import net.minecraftforge.fml.network.NetworkInstance;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@@ -47,4 +49,8 @@ public class EventNetworkChannel
|
||||
{
|
||||
instance.unregisterObject(object);
|
||||
}
|
||||
|
||||
public boolean isRemotePresent(NetworkManager manager) {
|
||||
return instance.isRemotePresent(manager);
|
||||
}
|
||||
}
|
||||
@@ -134,6 +134,13 @@ public class SimpleChannel
|
||||
context.getPacketDispatcher().sendPacket(instance.getChannelName(), toBuffer(msgToReply).getLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the channel is present in the given connection.
|
||||
*/
|
||||
public boolean isRemotePresent(NetworkManager manager) {
|
||||
return instance.isRemotePresent(manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new MessageBuilder. The type should implement {@link java.util.function.IntSupplier} if it is a login
|
||||
* packet.
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2021.
|
||||
*
|
||||
* 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.network;
|
||||
|
||||
import java.util.List;
|
||||
@@ -34,7 +53,7 @@ public class ForgeConnectionNetworkFilter extends VanillaPacketFilter
|
||||
protected boolean isNecessary(NetworkManager manager)
|
||||
{
|
||||
// not needed on local connections, because packets are not encoded to bytes there
|
||||
return !manager.isMemoryConnection() && !NetworkHooks.isVanillaConnection(manager);
|
||||
return !manager.isMemoryConnection() && !VanillaPacketSplitter.isRemoteCompatible(manager);
|
||||
}
|
||||
|
||||
private static void splitPacket(IPacket<?> packet, List<? super IPacket<?>> out)
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2021.
|
||||
*
|
||||
* 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.network;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -5,21 +24,20 @@ import java.io.UncheckedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.network.play.ClientPlayNetHandler;
|
||||
import net.minecraft.network.IPacket;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.PacketDirection;
|
||||
import net.minecraft.network.ProtocolType;
|
||||
import net.minecraft.network.*;
|
||||
import net.minecraft.network.play.server.SCustomPayloadPlayPacket;
|
||||
import net.minecraft.network.play.server.STagsListPacket;
|
||||
import net.minecraft.network.play.server.SUpdateRecipesPacket;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.network.NetworkDirection;
|
||||
import net.minecraftforge.fml.network.NetworkEvent;
|
||||
import net.minecraftforge.fml.network.NetworkHooks;
|
||||
import net.minecraftforge.fml.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.network.event.EventNetworkChannel;
|
||||
|
||||
@@ -54,9 +72,12 @@ public class VanillaPacketSplitter
|
||||
private static final byte STATE_FIRST = 1;
|
||||
private static final byte STATE_LAST = 2;
|
||||
|
||||
private static EventNetworkChannel channel;
|
||||
|
||||
public static void register()
|
||||
{
|
||||
EventNetworkChannel channel = NetworkRegistry.newEventChannel(CHANNEL, () -> VERSION, VERSION::equals, VERSION::equals);
|
||||
Predicate<String> versionCheck = NetworkRegistry.acceptMissingOr(VERSION);
|
||||
channel = NetworkRegistry.newEventChannel(CHANNEL, () -> VERSION, versionCheck, versionCheck);
|
||||
channel.addListener(VanillaPacketSplitter::onClientPacket);
|
||||
}
|
||||
|
||||
@@ -185,4 +206,8 @@ public class VanillaPacketSplitter
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRemoteCompatible(NetworkManager manager)
|
||||
{
|
||||
return !NetworkHooks.isVanillaConnection(manager) && channel.isRemotePresent(manager);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user