Skip to content

Commit

Permalink
Rewrite the FML Handshake packet formats to include actually syncing …
Browse files Browse the repository at this point in the history
…the registry data and introduce the concept of caching it locally.

Snapshots are not injected yet due top threading issues.
  • Loading branch information
LexManos committed Feb 28, 2019
1 parent cb70702 commit 58494f8
Show file tree
Hide file tree
Showing 11 changed files with 408 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
private String field_149598_b;
private int field_149599_c;
private EnumConnectionState field_149597_d;
+ private String fmlVersion = net.minecraftforge.fml.network.NetworkHooks.NETVERSION;
+ private String fmlVersion = net.minecraftforge.fml.network.FMLNetworkConstants.NETVERSION;

public CPacketHandshake() {
}
Expand All @@ -19,7 +19,7 @@
public void func_148840_b(PacketBuffer p_148840_1_) throws IOException {
p_148840_1_.func_150787_b(this.field_149600_a);
- p_148840_1_.func_180714_a(this.field_149598_b);
+ p_148840_1_.func_180714_a(this.field_149598_b + "\0"+net.minecraftforge.fml.network.NetworkHooks.NETVERSION+"\0");
+ p_148840_1_.func_180714_a(this.field_149598_b + "\0"+net.minecraftforge.fml.network.FMLNetworkConstants.NETVERSION+"\0");
p_148840_1_.writeShort(this.field_149599_c);
p_148840_1_.func_150787_b(this.field_149597_d.func_150759_c());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
@@ -322,11 +322,11 @@
}

public void func_201866_a(EnumCreatureType p_201866_1_, Biome.SpawnListEntry p_201866_2_) {
protected void func_201866_a(EnumCreatureType p_201866_1_, Biome.SpawnListEntry p_201866_2_) {
- this.field_201880_ax.get(p_201866_1_).add(p_201866_2_);
+ this.field_201880_ax.computeIfAbsent(p_201866_1_, k -> Lists.newArrayList()).add(p_201866_2_);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
/*
* 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.common.util;

import net.minecraft.nbt.NBTTagCompound;
Expand Down
129 changes: 129 additions & 0 deletions src/main/java/net/minecraftforge/common/util/HexDumper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* 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.common.util;

import io.netty.buffer.ByteBuf;

/**
* Utility class for creating a nice human readable dump of binary data.
*
* It might look something like this:<BR>
*<PRE>
* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ................
* 69 68 67 66 65 64 63 62 61 61 6A 6B 6C 6D 6E 00 ihgfedcbaajklmn.
* 41 00 A.
* Length: 34
*</PRE>
*/
public class HexDumper
{

public static String dump(ByteBuf data)
{
int current = data.readerIndex();
data.readerIndex(0);
Instance inst = new Instance(current, data.readableBytes());
data.forEachByte(b -> {
inst.add(b);
return true;
});
data.readerIndex(current);
return inst.finish();
}

public static String dump(byte[] data)
{
return dump(data, -1);
}

public static String dump(byte[] data, int marker)
{
Instance inst = new Instance(marker, data.length);
for (int x = 0; x < data.length; x++)
inst.add(data[x]);
return inst.finish();
}

private static class Instance
{
private static final String HEX = "0123456789ABCDEF";
private final int marked;
private final StringBuilder buf;
private char[] ascii = new char[16];
private int index = 0;

private Instance(int marked, int size)
{
this.marked = marked;
int lines = ((size + 15) / 16);
this.buf = new StringBuilder((size * 3) //Hex
+ size // ASCII
+ (lines * 2) // \t and \n per line
+ (marked == -1 ? 0 : lines)); // ' ' or < at the start of each line

for (int x = 0; x < ascii.length; x++)
ascii[x] = ' ';
}

public void add(byte data)
{
if (index == 0 && marked != -1)
buf.append(index == marked ? '<' : ' ');

if (index != 0 && index % 16 == 0)
{
buf.append('\t');
for (int x = 0; x < 16; x++)
{
buf.append(ascii[x]);
ascii[x] = ' ';
}
buf.append('\n');
if (marked != -1)
buf.append(index == marked ? '<' : ' ');
}
ascii[index % 16] = data < ' ' || data > '~' ? '.' : (char)data;
buf.append(HEX.charAt((data & 0xF0) >> 4));
buf.append(HEX.charAt((data & 0x0F) ));
if (index + 1 == marked)
buf.append(marked % 16 == 0 ? ' ' : '<');
else
buf.append(marked == index ? '>' : ' ');

index++;
}

public String finish()
{
int padding = 16 - (index % 16);
if (padding > 0)
{
for (int x = 0; x < padding * 3; x++)
buf.append(' ');
buf.append('\t');
buf.append(ascii);
}
buf.append('\n');
buf.append("Length: ").append(index);
if (marked != -1)
buf.append(" Mark: ").append(marked);
return buf.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;

import com.google.common.collect.Maps;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
Expand Down Expand Up @@ -108,7 +110,7 @@ public class FMLHandshakeHandler {
loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
decoder(FMLHandshakeMessages.S2CRegistry::decode).
encoder(FMLHandshakeMessages.S2CRegistry::encode).
buildLoginPacketList(RegistryManager::generateRegistryPackets).
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).
Expand Down Expand Up @@ -178,8 +180,9 @@ static boolean tickLogin(NetworkManager networkManager)
private final NetworkDirection direction;
private final NetworkManager manager;
private int packetPosition;
private ForgeRegistry.Snapshot registrySnapshot;
private Set<String> registriesToReceive;
private Map<ResourceLocation, ForgeRegistry.Snapshot> registrySnapshots;
private Set<ResourceLocation> registriesToReceive;
private Map<ResourceLocation, String> registryHashes;

private FMLHandshakeHandler(NetworkManager networkManager, NetworkDirection side)
{
Expand All @@ -196,20 +199,22 @@ private FMLHandshakeHandler(NetworkManager networkManager, NetworkDirection side

private void handleServerModListOnClient(FMLHandshakeMessages.S2CModList serverModList, Supplier<NetworkEvent.Context> c)
{
LOGGER.debug(FMLHSMARKER, "Logging into server with mod list [{}]", serverModList.getModList());
LOGGER.debug(FMLHSMARKER, "Logging into server with mod list [{}]", String.join(", ", serverModList.getModList()));
boolean accepted = NetworkRegistry.validateClientChannels(serverModList.getChannels());
c.get().setPacketHandled(true);
if (!accepted) {
LOGGER.error(FMLHSMARKER, "Terminating connection with server, mismatched mod list");
c.get().getNetworkManager().closeChannel(new TextComponentString("Connection closed - mismatched mod channel list"));
return;
}
final FMLHandshakeMessages.C2SModListReply reply = new FMLHandshakeMessages.C2SModListReply();
channel.reply(reply, c.get());
channel.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);

this.registriesToReceive = new HashSet<>(serverModList.getRegistries());
this.registrySnapshots = Maps.newHashMap();
LOGGER.debug(REGISTRIES, "Expecting {} registries: {}", ()->this.registriesToReceive.size(), ()->this.registriesToReceive);
}

Expand All @@ -224,7 +229,7 @@ private <MSG extends FMLHandshakeMessages.LoginIndexedMessage> void handleIndexe

private void handleClientModListOnServer(FMLHandshakeMessages.C2SModListReply clientModList, Supplier<NetworkEvent.Context> c)
{
LOGGER.debug(FMLHSMARKER, "Received client connection with modlist [{}]", clientModList.getModList());
LOGGER.debug(FMLHSMARKER, "Received client connection with modlist [{}]", String.join(", ", clientModList.getModList()));
boolean accepted = NetworkRegistry.validateServerChannels(clientModList.getChannels());
c.get().setPacketHandled(true);
if (!accepted) {
Expand All @@ -234,13 +239,18 @@ private void handleClientModListOnServer(FMLHandshakeMessages.C2SModListReply cl
}
LOGGER.debug(FMLHSMARKER, "Accepted client connection mod list");
}
private void handleRegistryMessage(final FMLHandshakeMessages.S2CRegistry registryPacket, final Supplier<NetworkEvent.Context> contextSupplier) {

private void handleRegistryMessage(final FMLHandshakeMessages.S2CRegistry registryPacket, final Supplier<NetworkEvent.Context> contextSupplier){
LOGGER.debug(FMLHSMARKER,"Received registry packet for {}", registryPacket.getRegistryName());
this.registriesToReceive.remove(registryPacket.getRegistryName());
RegistryManager.acceptRegistry(registryPacket, contextSupplier);
this.registrySnapshots.put(registryPacket.getRegistryName(), registryPacket.getSnapshot());
contextSupplier.get().setPacketHandled(true);
final FMLHandshakeMessages.C2SAcknowledge reply = new FMLHandshakeMessages.C2SAcknowledge();
channel.reply(reply, contextSupplier.get());
if (this.registriesToReceive.isEmpty()) {}//injectSnapshot
channel.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?
registrySnapshots = null;
}
}

private void handleClientAck(final FMLHandshakeMessages.C2SAcknowledge msg, final Supplier<NetworkEvent.Context> contextSupplier) {
Expand All @@ -252,8 +262,7 @@ private void handleConfigSync(final FMLHandshakeMessages.S2CConfigData msg, fina
LOGGER.debug(FMLHSMARKER, "Received config sync from server");
ConfigTracker.INSTANCE.receiveSyncedConfig(msg, contextSupplier);
contextSupplier.get().setPacketHandled(true);
final FMLHandshakeMessages.C2SAcknowledge reply = new FMLHandshakeMessages.C2SAcknowledge();
channel.reply(reply, contextSupplier.get());
channel.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
Expand Down
Loading

0 comments on commit 58494f8

Please sign in to comment.