mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 16:27:47 +00:00
Allow login packets to only generate on server based connections
Run injectSnapshot on the client thread, wait for result and disconnect when injectSnapshot fails. Fix DevServer to load MOD_CLASSES Fix LaunchTesting to properly load log4j2 markers (don't use a static variable in that class!) Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
14 files changed
+127
-27
No files matched your search
@@ -79,7 +79,7 @@ public class ConfigTracker {
|
||||
this.configSets.get(type).forEach(config -> openConfig(config, configBasePath));
|
||||
}
|
||||
|
||||
public List<Pair<String, FMLHandshakeMessages.S2CConfigData>> syncConfigs() {
|
||||
public List<Pair<String, FMLHandshakeMessages.S2CConfigData>> syncConfigs(boolean isLocal) {
|
||||
final Map<String, byte[]> configData = configSets.get(ModConfig.Type.SERVER).stream().collect(Collectors.toMap(ModConfig::getFileName, mc -> { //TODO: Test cpw's LambdaExceptionUtils on Oracle javac.
|
||||
try {
|
||||
return Files.readAllBytes(mc.getFullPath());
|
||||
|
||||
@@ -30,6 +30,7 @@ public enum ConnectionType
|
||||
ConnectionType(Function<String, Integer> versionExtractor) {
|
||||
this.versionExtractor = versionExtractor;
|
||||
}
|
||||
|
||||
public static ConnectionType forVersionFlag(String vers)
|
||||
{
|
||||
return vers.startsWith(FMLNetworkConstants.FMLNETMARKER) ? MODDED : VANILLA;
|
||||
|
||||
@@ -19,14 +19,17 @@
|
||||
|
||||
package net.minecraftforge.fml.network;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.NetHandlerLoginServer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraftforge.fml.config.ConfigTracker;
|
||||
import net.minecraftforge.fml.loading.AdvancedLogMessageAdapter;
|
||||
import net.minecraftforge.fml.network.simple.SimpleChannel;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
@@ -40,6 +43,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
|
||||
@@ -114,11 +119,14 @@ public class FMLHandshakeHandler {
|
||||
{
|
||||
this.direction = side;
|
||||
this.manager = networkManager;
|
||||
if (NetworkHooks.getConnectionType(()->this.manager)==ConnectionType.VANILLA) {
|
||||
if (networkManager.isLocalChannel()) {
|
||||
this.messageList = NetworkRegistry.gatherLoginPayloads(this.direction, true);
|
||||
LOGGER.debug(FMLHSMARKER, "Starting local connection.");
|
||||
} else if (NetworkHooks.getConnectionType(()->this.manager)==ConnectionType.VANILLA) {
|
||||
this.messageList = Collections.emptyList();
|
||||
LOGGER.debug(FMLHSMARKER, "Starting new vanilla network connection.");
|
||||
} else {
|
||||
this.messageList = NetworkRegistry.gatherLoginPayloads(this.direction);
|
||||
this.messageList = NetworkRegistry.gatherLoginPayloads(this.direction, false);
|
||||
LOGGER.debug(FMLHSMARKER, "Starting new modded network connection. Found {} messages to dispatch.", this.messageList.size());
|
||||
}
|
||||
}
|
||||
@@ -170,13 +178,48 @@ public class FMLHandshakeHandler {
|
||||
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);
|
||||
FMLNetworkConstants.handshakeChannel.reply(new FMLHandshakeMessages.C2SAcknowledge(), contextSupplier.get());
|
||||
|
||||
boolean continueHandshake = true;
|
||||
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?
|
||||
registrySnapshots = null;
|
||||
continueHandshake = handleRegistryLoading(contextSupplier);
|
||||
}
|
||||
// The handshake reply isn't sent until we have processed the message
|
||||
contextSupplier.get().setPacketHandled(true);
|
||||
if (!continueHandshake) {
|
||||
LOGGER.error(FMLHSMARKER, "Connection closed, not continuing handshake");
|
||||
} else {
|
||||
FMLNetworkConstants.handshakeChannel.reply(new FMLHandshakeMessages.C2SAcknowledge(), contextSupplier.get());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleRegistryLoading(final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
// We use a countdown latch to suspend the network thread pending the client thread processing the registry data
|
||||
AtomicBoolean successfulConnection = new AtomicBoolean(false);
|
||||
CountDownLatch block = new CountDownLatch(1);
|
||||
contextSupplier.get().enqueueWork(() -> {
|
||||
LOGGER.debug(FMLHSMARKER, "Injecting registry snapshot from server.");
|
||||
final Multimap<ResourceLocation, ResourceLocation> missingData = GameData.injectSnapshot(registrySnapshots, false, false);
|
||||
LOGGER.debug(FMLHSMARKER, "Snapshot injected.");
|
||||
if (!missingData.isEmpty()) {
|
||||
LOGGER.error(FMLHSMARKER, "Missing registry data for network connection:\n{}", new AdvancedLogMessageAdapter(sb->
|
||||
missingData.forEach((reg, entry)-> sb.append("\t").append(reg).append(": ").append(entry).append('\n'))));
|
||||
}
|
||||
successfulConnection.set(missingData.isEmpty());
|
||||
block.countDown();
|
||||
});
|
||||
LOGGER.debug(FMLHSMARKER, "Waiting for registries to load.");
|
||||
try {
|
||||
block.await();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.interrupted();
|
||||
}
|
||||
if (successfulConnection.get()) {
|
||||
LOGGER.debug(FMLHSMARKER, "Registry load complete, continuing handshake.");
|
||||
} else {
|
||||
LOGGER.error(FMLHSMARKER, "Failed to load registry, closing connection.");
|
||||
this.manager.closeChannel(new TextComponentString("Failed to synchronize registry data from server, closing connection"));
|
||||
}
|
||||
return successfulConnection.get();
|
||||
}
|
||||
|
||||
void handleClientAck(final FMLHandshakeMessages.C2SAcknowledge msg, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
|
||||
@@ -101,14 +101,20 @@ public class NetworkEvent extends Event
|
||||
|
||||
public static class GatherLoginPayloadsEvent extends Event {
|
||||
private final List<NetworkRegistry.LoginPayload> collected;
|
||||
private final boolean isLocal;
|
||||
|
||||
public GatherLoginPayloadsEvent(final List<NetworkRegistry.LoginPayload> loginPayloadList) {
|
||||
public GatherLoginPayloadsEvent(final List<NetworkRegistry.LoginPayload> loginPayloadList, boolean isLocal) {
|
||||
this.collected = loginPayloadList;
|
||||
this.isLocal = isLocal;
|
||||
}
|
||||
|
||||
public void add(PacketBuffer buffer, ResourceLocation channelName, String context) {
|
||||
collected.add(new NetworkRegistry.LoginPayload(buffer, channelName, context));
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return isLocal;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoginPayloadEvent extends NetworkEvent {
|
||||
|
||||
@@ -96,8 +96,8 @@ public class NetworkInstance
|
||||
return this.serverAcceptedVersions.test(clientVersion);
|
||||
}
|
||||
|
||||
void dispatchGatherLogin(final List<NetworkRegistry.LoginPayload> loginPayloadList) {
|
||||
this.networkEventBus.post(new NetworkEvent.GatherLoginPayloadsEvent(loginPayloadList));
|
||||
void dispatchGatherLogin(final List<NetworkRegistry.LoginPayload> loginPayloadList, boolean isLocal) {
|
||||
this.networkEventBus.post(new NetworkEvent.GatherLoginPayloadsEvent(loginPayloadList, isLocal));
|
||||
}
|
||||
|
||||
void dispatchLoginPacket(final NetworkEvent.LoginPayloadEvent loginPayloadEvent) {
|
||||
|
||||
@@ -218,10 +218,10 @@ public class NetworkRegistry
|
||||
* @return The {@link LoginPayload} list
|
||||
* @param direction the network direction for the request - only gathers for LOGIN_TO_CLIENT
|
||||
*/
|
||||
static List<LoginPayload> gatherLoginPayloads(final NetworkDirection direction) {
|
||||
static List<LoginPayload> gatherLoginPayloads(final NetworkDirection direction, boolean isLocal) {
|
||||
if (direction!=NetworkDirection.LOGIN_TO_CLIENT) return Collections.emptyList();
|
||||
List<LoginPayload> gatheredPayloads = new ArrayList<>();
|
||||
instances.values().forEach(ni->ni.dispatchGatherLogin(gatheredPayloads));
|
||||
instances.values().forEach(ni->ni.dispatchGatherLogin(gatheredPayloads, isLocal));
|
||||
return gatheredPayloads;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class SimpleChannel
|
||||
{
|
||||
private final NetworkInstance instance;
|
||||
private final IndexedMessageCodec indexedCodec;
|
||||
private List<Supplier<? extends List<? extends Pair<String,?>>>> loginPackets;
|
||||
private List<Function<Boolean, ? extends List<? extends Pair<String,?>>>> loginPackets;
|
||||
|
||||
public SimpleChannel(NetworkInstance instance)
|
||||
{
|
||||
@@ -52,7 +52,7 @@ public class SimpleChannel
|
||||
|
||||
private void networkLoginGather(final NetworkEvent.GatherLoginPayloadsEvent gatherEvent) {
|
||||
loginPackets.forEach(packetGenerator->{
|
||||
packetGenerator.get().forEach(p->{
|
||||
packetGenerator.apply(gatherEvent.isLocal()).forEach(p->{
|
||||
PacketBuffer pb = new PacketBuffer(Unpooled.buffer());
|
||||
this.indexedCodec.build(p.getRight(), pb);
|
||||
gatherEvent.add(pb, this.instance.getChannelName(), p.getLeft());
|
||||
@@ -125,7 +125,7 @@ public class SimpleChannel
|
||||
private BiConsumer<MSG, Supplier<NetworkEvent.Context>> consumer;
|
||||
private Function<MSG, Integer> loginIndexGetter;
|
||||
private BiConsumer<MSG, Integer> loginIndexSetter;
|
||||
private Supplier<List<Pair<String,MSG>>> loginPacketGenerators;
|
||||
private Function<Boolean, List<Pair<String, MSG>>> loginPacketGenerators;
|
||||
|
||||
private static <MSG> MessageBuilder<MSG> forType(final SimpleChannel channel, final Class<MSG> type, int id) {
|
||||
MessageBuilder<MSG> builder = new MessageBuilder<>();
|
||||
@@ -151,18 +151,18 @@ public class SimpleChannel
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder<MSG> buildLoginPacketList(Supplier<List<Pair<String,MSG>>> loginPacketGenerators) {
|
||||
public MessageBuilder<MSG> buildLoginPacketList(Function<Boolean, List<Pair<String,MSG>>> loginPacketGenerators) {
|
||||
this.loginPacketGenerators = loginPacketGenerators;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder<MSG> markAsLoginPacket()
|
||||
{
|
||||
this.loginPacketGenerators = () -> {
|
||||
this.loginPacketGenerators = (isLocal) -> {
|
||||
try {
|
||||
return Collections.singletonList(Pair.of(type.getName(), type.newInstance()));
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException("Inaccessible no-arg constructor for message "+type.getName(),e);
|
||||
throw new RuntimeException("Inaccessible no-arg constructor for message "+type.getName(), e);
|
||||
}
|
||||
};
|
||||
return this;
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package net.minecraftforge.registries;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -146,15 +148,15 @@ public class RegistryManager
|
||||
this.superTypes.clear();
|
||||
}
|
||||
|
||||
public static List<Pair<String, FMLHandshakeMessages.S2CRegistry>> generateRegistryPackets()
|
||||
public static List<Pair<String, FMLHandshakeMessages.S2CRegistry>> generateRegistryPackets(boolean isLocal)
|
||||
{
|
||||
return ACTIVE.takeSnapshot(false).entrySet().stream().
|
||||
return !isLocal ? ACTIVE.takeSnapshot(false).entrySet().stream().
|
||||
map(e->Pair.of("Registry " + e.getKey(), new FMLHandshakeMessages.S2CRegistry(e.getKey(), e.getValue()))).
|
||||
collect(Collectors.toList());
|
||||
collect(Collectors.toList()) : Collections.emptyList();
|
||||
}
|
||||
|
||||
public static List<ResourceLocation> registryNames()
|
||||
{
|
||||
return ACTIVE.registries.entrySet().stream().map(Map.Entry::getKey).collect(Collectors.toList());
|
||||
return new ArrayList<>(ACTIVE.registries.keySet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.server.command;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.command.Commands;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommandModList {
|
||||
static ArgumentBuilder<CommandSource, ?> register()
|
||||
{
|
||||
return Commands.literal("mods")
|
||||
.requires(cs->cs.hasPermissionLevel(0)) //permission
|
||||
.executes(ctx -> {
|
||||
ctx.getSource().sendFeedback(new TextComponentTranslation("commands.forge.mods.list",
|
||||
ModList.get().getMods().stream().map(ModInfo::getModId).collect(Collectors.joining(","))),
|
||||
true);
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,7 @@ public class ForgeCommand
|
||||
.then(CommandGenerate.register())
|
||||
.then(CommandDimensions.register())
|
||||
.then(CommandSetDimension.register())
|
||||
.then(CommandModList.register())
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user