Preliminary network protocol re-work. vanilla clients can now connect. Further cleanup needed.
This commit is contained in:
parent
1ac0c5d87f
commit
511c370193
15 changed files with 403 additions and 67 deletions
|
@ -0,0 +1,11 @@
|
||||||
|
--- ../src-base/minecraft/net/minecraft/client/multiplayer/GuiConnecting.java
|
||||||
|
+++ ../src-work/minecraft/net/minecraft/client/multiplayer/GuiConnecting.java
|
||||||
|
@@ -69,7 +69,7 @@
|
||||||
|
inetaddress = InetAddress.getByName(p_146367_1_);
|
||||||
|
GuiConnecting.this.field_146371_g = NetworkManager.func_150726_a(inetaddress, p_146367_2_);
|
||||||
|
GuiConnecting.this.field_146371_g.func_150719_a(new NetHandlerLoginClient(GuiConnecting.this.field_146371_g, GuiConnecting.this.field_146297_k, GuiConnecting.this.field_146374_i));
|
||||||
|
- GuiConnecting.this.field_146371_g.func_179290_a(new C00Handshake(47, p_146367_1_, p_146367_2_, EnumConnectionState.LOGIN));
|
||||||
|
+ GuiConnecting.this.field_146371_g.func_179290_a(new C00Handshake(47, p_146367_1_, p_146367_2_, EnumConnectionState.LOGIN, true));
|
||||||
|
GuiConnecting.this.field_146371_g.func_179290_a(new C00PacketLoginStart(GuiConnecting.this.field_146297_k.func_110432_I().func_148256_e()));
|
||||||
|
}
|
||||||
|
catch (UnknownHostException unknownhostexception)
|
|
@ -0,0 +1,10 @@
|
||||||
|
--- ../src-base/minecraft/net/minecraft/client/network/NetHandlerHandshakeMemory.java
|
||||||
|
+++ ../src-work/minecraft/net/minecraft/client/network/NetHandlerHandshakeMemory.java
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
|
||||||
|
public void func_147383_a(C00Handshake p_147383_1_)
|
||||||
|
{
|
||||||
|
+ if (!cpw.mods.fml.common.FMLCommonHandler.instance().handleServerHandshake(p_147383_1_, this.field_147384_b)) return;
|
||||||
|
this.field_147384_b.func_150723_a(p_147383_1_.func_149594_c());
|
||||||
|
this.field_147384_b.func_150719_a(new NetHandlerLoginServer(this.field_147385_a, this.field_147384_b));
|
||||||
|
}
|
|
@ -1,6 +1,18 @@
|
||||||
--- ../src-base/minecraft/net/minecraft/network/NetworkManager.java
|
--- ../src-base/minecraft/net/minecraft/network/NetworkManager.java
|
||||||
+++ ../src-work/minecraft/net/minecraft/network/NetworkManager.java
|
+++ ../src-work/minecraft/net/minecraft/network/NetworkManager.java
|
||||||
@@ -175,7 +175,7 @@
|
@@ -88,6 +88,11 @@
|
||||||
|
this.field_179294_g = p_i46004_1_;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ public EnumPacketDirection getDirection()
|
||||||
|
+ {
|
||||||
|
+ return this.field_179294_g;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
public void channelActive(ChannelHandlerContext p_channelActive_1_) throws Exception
|
||||||
|
{
|
||||||
|
super.channelActive(p_channelActive_1_);
|
||||||
|
@@ -175,7 +180,7 @@
|
||||||
final EnumConnectionState enumconnectionstate = EnumConnectionState.func_150752_a(p_150732_1_);
|
final EnumConnectionState enumconnectionstate = EnumConnectionState.func_150752_a(p_150732_1_);
|
||||||
final EnumConnectionState enumconnectionstate1 = (EnumConnectionState)this.field_150746_k.attr(field_150739_c).get();
|
final EnumConnectionState enumconnectionstate1 = (EnumConnectionState)this.field_150746_k.attr(field_150739_c).get();
|
||||||
|
|
||||||
|
@ -9,7 +21,7 @@
|
||||||
{
|
{
|
||||||
field_150735_g.debug("Disabled auto read");
|
field_150735_g.debug("Disabled auto read");
|
||||||
this.field_150746_k.config().setAutoRead(false);
|
this.field_150746_k.config().setAutoRead(false);
|
||||||
@@ -183,7 +183,7 @@
|
@@ -183,7 +188,7 @@
|
||||||
|
|
||||||
if (this.field_150746_k.eventLoop().inEventLoop())
|
if (this.field_150746_k.eventLoop().inEventLoop())
|
||||||
{
|
{
|
||||||
|
@ -18,7 +30,7 @@
|
||||||
{
|
{
|
||||||
this.func_150723_a(enumconnectionstate);
|
this.func_150723_a(enumconnectionstate);
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@
|
@@ -204,7 +209,7 @@
|
||||||
private static final String __OBFID = "CL_00001243";
|
private static final String __OBFID = "CL_00001243";
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
|
@ -27,7 +39,7 @@
|
||||||
{
|
{
|
||||||
NetworkManager.this.func_150723_a(enumconnectionstate);
|
NetworkManager.this.func_150723_a(enumconnectionstate);
|
||||||
}
|
}
|
||||||
@@ -409,6 +409,11 @@
|
@@ -409,6 +414,11 @@
|
||||||
this.channelRead0(p_channelRead0_1_, (Packet)p_channelRead0_2_);
|
this.channelRead0(p_channelRead0_1_, (Packet)p_channelRead0_2_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
--- ../src-base/minecraft/net/minecraft/network/handshake/client/C00Handshake.java
|
||||||
|
+++ ../src-work/minecraft/net/minecraft/network/handshake/client/C00Handshake.java
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
private int field_149599_c;
|
||||||
|
private EnumConnectionState field_149597_d;
|
||||||
|
private static final String __OBFID = "CL_00001372";
|
||||||
|
+ private boolean hasFMLMarker = false;
|
||||||
|
|
||||||
|
public C00Handshake() {}
|
||||||
|
|
||||||
|
@@ -28,18 +29,26 @@
|
||||||
|
this.field_149597_d = p_i45266_4_;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ public C00Handshake(int protocol, String address, int port, EnumConnectionState state, boolean addFMLMarker)
|
||||||
|
+ {
|
||||||
|
+ this(protocol, address, port, state);
|
||||||
|
+ this.hasFMLMarker = addFMLMarker;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
public void func_148837_a(PacketBuffer p_148837_1_) throws IOException
|
||||||
|
{
|
||||||
|
this.field_149600_a = p_148837_1_.func_150792_a();
|
||||||
|
this.field_149598_b = p_148837_1_.func_150789_c(255);
|
||||||
|
this.field_149599_c = p_148837_1_.readUnsignedShort();
|
||||||
|
this.field_149597_d = EnumConnectionState.func_150760_a(p_148837_1_.func_150792_a());
|
||||||
|
+ this.hasFMLMarker = this.field_149598_b.contains("\0FML\0");
|
||||||
|
+ this.field_149598_b = this.field_149598_b.split("\0")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
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 + "\0FML\0");
|
||||||
|
p_148840_1_.writeShort(this.field_149599_c);
|
||||||
|
p_148840_1_.func_150787_b(this.field_149597_d.func_150759_c());
|
||||||
|
}
|
||||||
|
@@ -63,4 +72,9 @@
|
||||||
|
{
|
||||||
|
this.func_180770_a((INetHandlerHandshakeServer)p_148833_1_);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public boolean hasFMLMarker()
|
||||||
|
+ {
|
||||||
|
+ return this.hasFMLMarker;
|
||||||
|
+ }
|
||||||
|
}
|
|
@ -1,16 +1,10 @@
|
||||||
--- ../src-base/minecraft/net/minecraft/server/network/NetHandlerHandshakeTCP.java
|
--- ../src-base/minecraft/net/minecraft/server/network/NetHandlerHandshakeTCP.java
|
||||||
+++ ../src-work/minecraft/net/minecraft/server/network/NetHandlerHandshakeTCP.java
|
+++ ../src-work/minecraft/net/minecraft/server/network/NetHandlerHandshakeTCP.java
|
||||||
@@ -23,6 +23,14 @@
|
@@ -23,6 +23,8 @@
|
||||||
|
|
||||||
public void func_147383_a(C00Handshake p_147383_1_)
|
public void func_147383_a(C00Handshake p_147383_1_)
|
||||||
{
|
{
|
||||||
+ if (!cpw.mods.fml.common.FMLCommonHandler.instance().shouldAllowPlayerLogins())
|
+ if (!cpw.mods.fml.common.FMLCommonHandler.instance().handleServerHandshake(p_147383_1_, this.field_147386_b)) return;
|
||||||
+ {
|
|
||||||
+ ChatComponentText chatcomponenttext = new ChatComponentText("Server is still starting! Please wait before reconnecting.");
|
|
||||||
+ this.field_147386_b.func_179290_a(new S00PacketDisconnect(chatcomponenttext));
|
|
||||||
+ this.field_147386_b.func_150718_a(chatcomponenttext);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
+
|
||||||
switch (NetHandlerHandshakeTCP.SwitchEnumConnectionState.field_151291_a[p_147383_1_.func_149594_c().ordinal()])
|
switch (NetHandlerHandshakeTCP.SwitchEnumConnectionState.field_151291_a[p_147383_1_.func_149594_c().ordinal()])
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,9 +28,13 @@ import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.NBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.network.EnumConnectionState;
|
||||||
import net.minecraft.network.INetHandler;
|
import net.minecraft.network.INetHandler;
|
||||||
import net.minecraft.network.NetworkManager;
|
import net.minecraft.network.NetworkManager;
|
||||||
|
import net.minecraft.network.handshake.client.C00Handshake;
|
||||||
|
import net.minecraft.network.login.server.S00PacketDisconnect;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.util.ChatComponentText;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.storage.SaveHandler;
|
import net.minecraft.world.storage.SaveHandler;
|
||||||
import net.minecraft.world.storage.WorldInfo;
|
import net.minecraft.world.storage.WorldInfo;
|
||||||
|
@ -40,6 +44,7 @@ import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableList.Builder;
|
import com.google.common.collect.ImmutableList.Builder;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
@ -52,6 +57,7 @@ import cpw.mods.fml.common.gameevent.InputEvent;
|
||||||
import cpw.mods.fml.common.gameevent.PlayerEvent;
|
import cpw.mods.fml.common.gameevent.PlayerEvent;
|
||||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||||
|
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||||
import cpw.mods.fml.relauncher.Side;
|
import cpw.mods.fml.relauncher.Side;
|
||||||
import cpw.mods.fml.server.FMLServerHandler;
|
import cpw.mods.fml.server.FMLServerHandler;
|
||||||
|
|
||||||
|
@ -590,6 +596,39 @@ public class FMLCommonHandler
|
||||||
return sidedDelegate.shouldAllowPlayerLogins();
|
return sidedDelegate.shouldAllowPlayerLogins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process initial Handshake packet, kicks players from the server if they are connecting while we are starting up.
|
||||||
|
* Also verifies the client has the FML marker.
|
||||||
|
*
|
||||||
|
* @param packet Handshake Packet
|
||||||
|
* @param manager Network connection
|
||||||
|
* @return True to allow connection, otherwise False.
|
||||||
|
*/
|
||||||
|
public boolean handleServerHandshake(C00Handshake packet, NetworkManager manager)
|
||||||
|
{
|
||||||
|
if (!shouldAllowPlayerLogins())
|
||||||
|
{
|
||||||
|
ChatComponentText text = new ChatComponentText("Server is still starting! Please wait before reconnecting.");
|
||||||
|
FMLLog.info("Disconnecting Player: " + text.getUnformattedText());
|
||||||
|
manager.func_179290_a(new S00PacketDisconnect(text));
|
||||||
|
manager.closeChannel(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet.func_149594_c() == EnumConnectionState.LOGIN && (!NetworkRegistry.INSTANCE.isVanillaAccepted(Side.CLIENT) && !packet.hasFMLMarker()))
|
||||||
|
{
|
||||||
|
manager.setConnectionState(EnumConnectionState.LOGIN);
|
||||||
|
ChatComponentText text = new ChatComponentText("This server requires FML/Forge to be installed. Contact your server admin for more details.");
|
||||||
|
FMLLog.info("Disconnecting Player: " + text.getUnformattedText());
|
||||||
|
manager.func_179290_a(new S00PacketDisconnect(text));
|
||||||
|
manager.closeChannel(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.channel().attr(NetworkRegistry.FML_MARKER).set(packet.hasFMLMarker());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to exit from java, with system exit preventions in place. Will be tidy about it and just log a message,
|
* Used to exit from java, with system exit preventions in place. Will be tidy about it and just log a message,
|
||||||
|
|
|
@ -857,7 +857,8 @@ public class Loader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FMLLog.info("Attempting connection with missing mods %s at %s", difference, side);
|
if (difference.size() > 0)
|
||||||
|
FMLLog.info("Attempting connection with missing mods %s at %s", difference, side);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,12 @@ public class TerminalTransformer implements IClassTransformer
|
||||||
{
|
{
|
||||||
final boolean warn = !(clsName.equals("net/minecraft/client/Minecraft") ||
|
final boolean warn = !(clsName.equals("net/minecraft/client/Minecraft") ||
|
||||||
clsName.equals("net/minecraft/server/dedicated/DedicatedServer") ||
|
clsName.equals("net/minecraft/server/dedicated/DedicatedServer") ||
|
||||||
|
clsName.equals("net/minecraft/server/dedicated/ServerHangWatchdog") ||
|
||||||
|
clsName.equals("net/minecraft/server/dedicated/ServerHangWatchdog$1") ||
|
||||||
clsName.equals("cpw/mods/fml/common/FMLCommonHandler") ||
|
clsName.equals("cpw/mods/fml/common/FMLCommonHandler") ||
|
||||||
clsName.startsWith("com/jcraft/jogg/") ||
|
clsName.startsWith("com/jcraft/jogg/") ||
|
||||||
clsName.startsWith("scala/sys/")
|
clsName.startsWith("scala/sys/") ||
|
||||||
|
clsName.startsWith("net/minecraft/server/gui/MinecraftServerGui")
|
||||||
);
|
);
|
||||||
|
|
||||||
return new MethodVisitor(Opcodes.ASM4, super.visitMethod(mAccess, mName, mDesc, mSignature, mExceptions))
|
return new MethodVisitor(Opcodes.ASM4, super.visitMethod(mAccess, mName, mDesc, mSignature, mExceptions))
|
||||||
|
@ -132,6 +135,7 @@ public class TerminalTransformer implements IClassTransformer
|
||||||
// FML is allowed to call system exit and the Minecraft applet (from the quit button), and the dedicated server (from itself)
|
// FML is allowed to call system exit and the Minecraft applet (from the quit button), and the dedicated server (from itself)
|
||||||
if (!(callingClass.startsWith("cpw.mods.fml.") ||
|
if (!(callingClass.startsWith("cpw.mods.fml.") ||
|
||||||
("net.minecraft.client.Minecraft".equals(callingClass) && "net.minecraft.client.Minecraft".equals(callingParent)) ||
|
("net.minecraft.client.Minecraft".equals(callingClass) && "net.minecraft.client.Minecraft".equals(callingParent)) ||
|
||||||
|
("net.minecraft.server.gui.MinecraftServerGui$1".equals(callingClass) && "java.awt.AWTEventMulticaster".equals(callingParent)) ||
|
||||||
("net.minecraft.server.dedicated.DedicatedServer".equals(callingClass) && "net.minecraft.server.MinecraftServer".equals(callingParent)))
|
("net.minecraft.server.dedicated.DedicatedServer".equals(callingClass) && "net.minecraft.server.MinecraftServer".equals(callingParent)))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,10 +58,11 @@ public enum NetworkRegistry
|
||||||
/**
|
/**
|
||||||
* Set in the {@link ChannelHandlerContext}
|
* Set in the {@link ChannelHandlerContext}
|
||||||
*/
|
*/
|
||||||
public static final AttributeKey<String> FML_CHANNEL = new AttributeKey<String>("fml:channelName");
|
public static final AttributeKey<String> FML_CHANNEL = AttributeKey.valueOf("fml:channelName");
|
||||||
public static final AttributeKey<Side> CHANNEL_SOURCE = new AttributeKey<Side>("fml:channelSource");
|
public static final AttributeKey<Side> CHANNEL_SOURCE = AttributeKey.valueOf("fml:channelSource");
|
||||||
public static final AttributeKey<ModContainer> MOD_CONTAINER = new AttributeKey<ModContainer>("fml:modContainer");
|
public static final AttributeKey<ModContainer> MOD_CONTAINER = AttributeKey.valueOf("fml:modContainer");
|
||||||
public static final AttributeKey<INetHandler> NET_HANDLER = new AttributeKey<INetHandler>("fml:netHandler");
|
public static final AttributeKey<INetHandler> NET_HANDLER = AttributeKey.valueOf("fml:netHandler");
|
||||||
|
public static final AttributeKey<Boolean> FML_MARKER = AttributeKey.valueOf("fml:hasMarker");
|
||||||
|
|
||||||
public static final byte FML_PROTOCOL = 1;
|
public static final byte FML_PROTOCOL = 1;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.ChannelPromise;
|
||||||
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLLog;
|
||||||
|
import net.minecraft.network.EnumPacketDirection;
|
||||||
|
import net.minecraft.network.NetworkManager;
|
||||||
|
import net.minecraft.network.Packet;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.util.MessageDeserializer2;
|
||||||
|
import net.minecraft.util.MessageSerializer2;
|
||||||
|
|
||||||
|
public class PacketLoggingHandler
|
||||||
|
{
|
||||||
|
public static void register(NetworkManager manager)
|
||||||
|
{
|
||||||
|
ChannelPipeline pipeline = manager.channel().pipeline();
|
||||||
|
final EnumPacketDirection direction = manager.getDirection();
|
||||||
|
if (manager.isLocalChannel())
|
||||||
|
{
|
||||||
|
pipeline.addBefore("packet_handler", "splitter", new SimpleChannelInboundHandler<Packet>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void channelRead0(ChannelHandlerContext ctx, Packet msg) throws Exception
|
||||||
|
{
|
||||||
|
PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
|
||||||
|
msg.writePacketData(buf);
|
||||||
|
FMLLog.log(Level.DEBUG, "$s $s:\n%s", msg.getClass().getSimpleName(), ByteBufUtils.getContentDump(buf));
|
||||||
|
ctx.fireChannelRead(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pipeline.addBefore("splitter", "prepender", new ChannelOutboundHandlerAdapter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception
|
||||||
|
{
|
||||||
|
if (msg instanceof Packet)
|
||||||
|
{
|
||||||
|
PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
|
||||||
|
((Packet)msg).writePacketData(buf);
|
||||||
|
FMLLog.log(Level.DEBUG, "$s $s:\n%s", msg.getClass().getSimpleName(), ByteBufUtils.getContentDump(buf));
|
||||||
|
}
|
||||||
|
ctx.write(msg, promise);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pipeline.replace("splitter", "splitter", new MessageDeserializer2()
|
||||||
|
{
|
||||||
|
String prefix = (direction == EnumPacketDirection.SERVERBOUND ? "SERVER: C->S" : "CLIENT: S->C");
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext context, ByteBuf input, List output)
|
||||||
|
{
|
||||||
|
super.decode(context, input, output);
|
||||||
|
for (ByteBuf pkt : (List<ByteBuf>)output)
|
||||||
|
{
|
||||||
|
pkt.markReaderIndex();
|
||||||
|
FMLLog.log(Level.DEBUG, "%s:\n%s", prefix, ByteBufUtils.getContentDump(pkt));
|
||||||
|
pkt.resetReaderIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pipeline.replace("prepender", "prepender", new MessageSerializer2()
|
||||||
|
{
|
||||||
|
String prefix = (direction == EnumPacketDirection.SERVERBOUND ? "SERVER: S->C" : "CLIENT: C->S");
|
||||||
|
@Override
|
||||||
|
protected void encode(ChannelHandlerContext context, ByteBuf input, ByteBuf output)
|
||||||
|
{
|
||||||
|
input.markReaderIndex();
|
||||||
|
FMLLog.log(Level.DEBUG, "%s:\n%s", prefix, ByteBufUtils.getContentDump(input));
|
||||||
|
input.resetReaderIndex();
|
||||||
|
super.encode(context, input, output);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ import cpw.mods.fml.common.registry.GameData;
|
||||||
public abstract class FMLHandshakeMessage {
|
public abstract class FMLHandshakeMessage {
|
||||||
public static FMLProxyPacket makeCustomChannelRegistration(Set<String> channels)
|
public static FMLProxyPacket makeCustomChannelRegistration(Set<String> channels)
|
||||||
{
|
{
|
||||||
String salutation = Joiner.on('\0').join(Iterables.concat(Arrays.asList("FML|HS","FML"),channels));
|
String salutation = Joiner.on('\0').join(Iterables.concat(Arrays.asList("FML|HS","FML", "FML|MP"),channels));
|
||||||
FMLProxyPacket proxy = new FMLProxyPacket(new PacketBuffer(Unpooled.wrappedBuffer(salutation.getBytes(Charsets.UTF_8))), "REGISTER");
|
FMLProxyPacket proxy = new FMLProxyPacket(new PacketBuffer(Unpooled.wrappedBuffer(salutation.getBytes(Charsets.UTF_8))), "REGISTER");
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.util.AttributeKey;
|
import io.netty.util.AttributeKey;
|
||||||
|
|
||||||
public class HandshakeMessageHandler<S extends Enum<S> & IHandshakeState<S>> extends SimpleChannelInboundHandler<FMLHandshakeMessage> {
|
public class HandshakeMessageHandler<S extends Enum<S> & IHandshakeState<S>> extends SimpleChannelInboundHandler<FMLHandshakeMessage> {
|
||||||
private static final AttributeKey<IHandshakeState<?>> STATE = new AttributeKey<IHandshakeState<?>>("fml:handshake-state");
|
private static final AttributeKey<IHandshakeState<?>> STATE = AttributeKey.valueOf("fml:handshake-state");
|
||||||
private final AttributeKey<S> fmlHandshakeState;
|
private final AttributeKey<S> fmlHandshakeState;
|
||||||
private S initialState;
|
private S initialState;
|
||||||
private Class<S> stateType;
|
private Class<S> stateType;
|
||||||
|
@ -23,8 +23,9 @@ public class HandshakeMessageHandler<S extends Enum<S> & IHandshakeState<S>> ext
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, FMLHandshakeMessage msg) throws Exception
|
protected void channelRead0(ChannelHandlerContext ctx, FMLHandshakeMessage msg) throws Exception
|
||||||
{
|
{
|
||||||
S state = ctx.attr(fmlHandshakeState).get();
|
S state = ctx.attr(fmlHandshakeState).get();
|
||||||
FMLLog.finer(msg.toString(stateType) + "->" + state.getClass().getName().substring(state.getClass().getName().lastIndexOf('.')+1)+":"+state);
|
FMLLog.fine(stateType.getSimpleName() + ": " + msg.toString(stateType) + "->" + state.getClass().getName().substring(state.getClass().getName().lastIndexOf('.')+1)+":"+state);
|
||||||
S newState = state.accept(ctx, msg);
|
S newState = state.accept(ctx, msg);
|
||||||
|
FMLLog.fine(" Next: " + newState.name());
|
||||||
ctx.attr(fmlHandshakeState).set(newState);
|
ctx.attr(fmlHandshakeState).set(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +38,9 @@ public class HandshakeMessageHandler<S extends Enum<S> & IHandshakeState<S>> ext
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
|
||||||
{
|
{
|
||||||
S state = ctx.attr(fmlHandshakeState).get();
|
S state = ctx.attr(fmlHandshakeState).get();
|
||||||
|
FMLLog.fine(stateType.getSimpleName() + ": null->" + state.getClass().getName().substring(state.getClass().getName().lastIndexOf('.')+1)+":"+state);
|
||||||
S newState = state.accept(ctx, null);
|
S newState = state.accept(ctx, null);
|
||||||
|
FMLLog.fine(" Next: " + newState.name());
|
||||||
ctx.attr(fmlHandshakeState).set(newState);
|
ctx.attr(fmlHandshakeState).set(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package cpw.mods.fml.common.network.handshake;
|
package cpw.mods.fml.common.network.handshake;
|
||||||
|
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelOutboundHandler;
|
import io.netty.channel.ChannelOutboundHandler;
|
||||||
|
@ -10,19 +11,24 @@ import io.netty.util.AttributeKey;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.GenericFutureListener;
|
import io.netty.util.concurrent.GenericFutureListener;
|
||||||
import io.netty.util.concurrent.ScheduledFuture;
|
import io.netty.util.concurrent.ScheduledFuture;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.channels.ClosedChannelException;
|
import java.nio.channels.ClosedChannelException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.network.EnumConnectionState;
|
import net.minecraft.network.EnumConnectionState;
|
||||||
import net.minecraft.network.INetHandler;
|
import net.minecraft.network.INetHandler;
|
||||||
import net.minecraft.network.NetHandlerPlayServer;
|
import net.minecraft.network.NetHandlerPlayServer;
|
||||||
import net.minecraft.network.NetworkManager;
|
import net.minecraft.network.NetworkManager;
|
||||||
import net.minecraft.network.Packet;
|
import net.minecraft.network.Packet;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.network.play.client.C17PacketCustomPayload;
|
import net.minecraft.network.play.client.C17PacketCustomPayload;
|
||||||
import net.minecraft.network.play.server.S01PacketJoinGame;
|
import net.minecraft.network.play.server.S01PacketJoinGame;
|
||||||
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
||||||
|
@ -35,12 +41,14 @@ import cpw.mods.fml.common.network.FMLNetworkEvent;
|
||||||
import cpw.mods.fml.common.network.FMLNetworkException;
|
import cpw.mods.fml.common.network.FMLNetworkException;
|
||||||
import cpw.mods.fml.common.network.FMLOutboundHandler;
|
import cpw.mods.fml.common.network.FMLOutboundHandler;
|
||||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||||
|
import cpw.mods.fml.common.network.PacketLoggingHandler;
|
||||||
import cpw.mods.fml.common.network.internal.FMLMessage;
|
import cpw.mods.fml.common.network.internal.FMLMessage;
|
||||||
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
|
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
|
||||||
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
|
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
|
||||||
import cpw.mods.fml.relauncher.Side;
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
|
||||||
public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> implements ChannelOutboundHandler {
|
public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> implements ChannelOutboundHandler {
|
||||||
|
private static boolean DEBUG_HANDSHAKE = Boolean.parseBoolean(System.getProperty("fml.debugNetworkHandshake", "false"));
|
||||||
private static enum ConnectionState {
|
private static enum ConnectionState {
|
||||||
OPENING, AWAITING_HANDSHAKE, HANDSHAKING, HANDSHAKECOMPLETE, CONNECTED;
|
OPENING, AWAITING_HANDSHAKE, HANDSHAKING, HANDSHAKECOMPLETE, CONNECTED;
|
||||||
}
|
}
|
||||||
|
@ -68,8 +76,8 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
return net;
|
return net;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = new AttributeKey<NetworkDispatcher>("fml:dispatcher");
|
public static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = AttributeKey.valueOf("fml:dispatcher");
|
||||||
public static final AttributeKey<Boolean> IS_LOCAL = new AttributeKey<Boolean>("fml:isLocal");
|
public static final AttributeKey<Boolean> IS_LOCAL = AttributeKey.valueOf("fml:isLocal");
|
||||||
public final NetworkManager manager;
|
public final NetworkManager manager;
|
||||||
private final ServerConfigurationManager scm;
|
private final ServerConfigurationManager scm;
|
||||||
private EntityPlayerMP player;
|
private EntityPlayerMP player;
|
||||||
|
@ -91,6 +99,8 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.SERVER);
|
this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.SERVER);
|
||||||
this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS");
|
this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS");
|
||||||
this.handshakeChannel.attr(IS_LOCAL).set(manager.isLocalChannel());
|
this.handshakeChannel.attr(IS_LOCAL).set(manager.isLocalChannel());
|
||||||
|
if (DEBUG_HANDSHAKE)
|
||||||
|
PacketLoggingHandler.register(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkDispatcher(NetworkManager manager, ServerConfigurationManager scm)
|
public NetworkDispatcher(NetworkManager manager, ServerConfigurationManager scm)
|
||||||
|
@ -104,12 +114,26 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.CLIENT);
|
this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.CLIENT);
|
||||||
this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS");
|
this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS");
|
||||||
this.handshakeChannel.attr(IS_LOCAL).set(manager.isLocalChannel());
|
this.handshakeChannel.attr(IS_LOCAL).set(manager.isLocalChannel());
|
||||||
|
if (DEBUG_HANDSHAKE)
|
||||||
|
PacketLoggingHandler.register(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void serverToClientHandshake(EntityPlayerMP player)
|
public void serverToClientHandshake(EntityPlayerMP player)
|
||||||
{
|
{
|
||||||
this.player = player;
|
this.player = player;
|
||||||
insertIntoChannel();
|
insertIntoChannel();
|
||||||
|
Boolean fml = this.manager.channel().attr(NetworkRegistry.FML_MARKER).get();
|
||||||
|
if (fml != null && fml.booleanValue())
|
||||||
|
{
|
||||||
|
//FML on client, send server hello
|
||||||
|
//TODO: Make this cleaner as it uses netty magic 0.o
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serverInitiateHandshake();
|
||||||
|
FMLLog.info("Connection received without FML marker, assuming vanilla.");
|
||||||
|
this.completeServerSideConnection(ConnectionType.VANILLA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertIntoChannel()
|
private void insertIntoChannel()
|
||||||
|
@ -138,7 +162,6 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
// Send mod salutation to the client
|
// Send mod salutation to the client
|
||||||
// This will be ignored by vanilla clients
|
// This will be ignored by vanilla clients
|
||||||
this.state = ConnectionState.AWAITING_HANDSHAKE;
|
this.state = ConnectionState.AWAITING_HANDSHAKE;
|
||||||
this.manager.channel().pipeline().addFirst("fml:vanilla_detector", new VanillaTimeoutWaiter());
|
|
||||||
// Need to start the handler here, so we can send custompayload packets
|
// Need to start the handler here, so we can send custompayload packets
|
||||||
serverHandler = new NetHandlerPlayServer(scm.getServerInstance(), manager, player);
|
serverHandler = new NetHandlerPlayServer(scm.getServerInstance(), manager, player);
|
||||||
this.netHandler = serverHandler;
|
this.netHandler = serverHandler;
|
||||||
|
@ -170,6 +193,8 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
FMLLog.info("[%s] Server side %s connection established", Thread.currentThread().getName(), this.connectionType.name().toLowerCase(Locale.ENGLISH));
|
FMLLog.info("[%s] Server side %s connection established", Thread.currentThread().getName(), this.connectionType.name().toLowerCase(Locale.ENGLISH));
|
||||||
this.state = ConnectionState.CONNECTED;
|
this.state = ConnectionState.CONNECTED;
|
||||||
FMLCommonHandler.instance().bus().post(new FMLNetworkEvent.ServerConnectionFromClientEvent(manager));
|
FMLCommonHandler.instance().bus().post(new FMLNetworkEvent.ServerConnectionFromClientEvent(manager));
|
||||||
|
if (DEBUG_HANDSHAKE)
|
||||||
|
manager.closeChannel(new ChatComponentText("Handshake Complete review log file for details."));
|
||||||
scm.initializeConnectionToPlayer(manager, player, serverHandler);
|
scm.initializeConnectionToPlayer(manager, player, serverHandler);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -247,9 +272,41 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
manager.channel().config().setAutoRead(false);
|
manager.channel().config().setAutoRead(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MultiPartCustomPayload multipart = null;
|
||||||
private boolean handleClientSideCustomPacket(S3FPacketCustomPayload msg, ChannelHandlerContext context)
|
private boolean handleClientSideCustomPacket(S3FPacketCustomPayload msg, ChannelHandlerContext context)
|
||||||
{
|
{
|
||||||
String channelName = msg.func_149169_c();
|
String channelName = msg.func_149169_c();
|
||||||
|
if ("FML|MP".equals(channelName))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (multipart == null)
|
||||||
|
{
|
||||||
|
multipart = new MultiPartCustomPayload(msg.func_180735_b());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
multipart.processPart(msg.func_180735_b());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
this.kickWithMessage(e.getMessage());
|
||||||
|
multipart = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multipart.isComplete())
|
||||||
|
{
|
||||||
|
msg = multipart;
|
||||||
|
channelName = msg.func_149169_c();
|
||||||
|
multipart = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true; // Haven't received all so return till we have.
|
||||||
|
}
|
||||||
|
}
|
||||||
if ("FML|HS".equals(channelName) || "REGISTER".equals(channelName) || "UNREGISTER".equals(channelName))
|
if ("FML|HS".equals(channelName) || "REGISTER".equals(channelName) || "UNREGISTER".equals(channelName))
|
||||||
{
|
{
|
||||||
FMLProxyPacket proxy = new FMLProxyPacket(msg);
|
FMLProxyPacket proxy = new FMLProxyPacket(msg);
|
||||||
|
@ -283,7 +340,6 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
{
|
{
|
||||||
if (state == ConnectionState.AWAITING_HANDSHAKE)
|
if (state == ConnectionState.AWAITING_HANDSHAKE)
|
||||||
{
|
{
|
||||||
this.manager.channel().pipeline().remove("fml:vanilla_detector");
|
|
||||||
state = ConnectionState.HANDSHAKING;
|
state = ConnectionState.HANDSHAKING;
|
||||||
}
|
}
|
||||||
String channelName = msg.func_149559_c();
|
String channelName = msg.func_149559_c();
|
||||||
|
@ -315,34 +371,6 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VanillaTimeoutWaiter extends ChannelInboundHandlerAdapter
|
|
||||||
{
|
|
||||||
private ScheduledFuture<Void> future;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handlerAdded(final ChannelHandlerContext ctx) throws Exception
|
|
||||||
{
|
|
||||||
future = ctx.executor().schedule(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() throws Exception
|
|
||||||
{
|
|
||||||
if (state != ConnectionState.CONNECTED)
|
|
||||||
{
|
|
||||||
FMLLog.info("Timeout occurred waiting for response, assuming vanilla connection");
|
|
||||||
ctx.fireUserEventTriggered(ConnectionType.VANILLA);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}, 10, TimeUnit.HOURS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception
|
|
||||||
{
|
|
||||||
future.cancel(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendProxy(FMLProxyPacket msg)
|
public void sendProxy(FMLProxyPacket msg)
|
||||||
{
|
{
|
||||||
manager.func_179290_a(msg);
|
manager.func_179290_a(msg);
|
||||||
|
@ -414,9 +442,18 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
if (msg instanceof FMLProxyPacket)
|
if (msg instanceof FMLProxyPacket)
|
||||||
{
|
{
|
||||||
if (side == Side.CLIENT)
|
if (side == Side.CLIENT)
|
||||||
|
{
|
||||||
|
//Client to server large packets are not supported to prevent client being bad.
|
||||||
ctx.write(((FMLProxyPacket) msg).toC17Packet(), promise);
|
ctx.write(((FMLProxyPacket) msg).toC17Packet(), promise);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ctx.write(((FMLProxyPacket) msg).toS3FPacket(), promise);
|
{
|
||||||
|
List<Packet> parts = ((FMLProxyPacket)msg).toS3FPackets();
|
||||||
|
for (Packet pkt : parts)
|
||||||
|
{
|
||||||
|
ctx.write(pkt, promise);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -480,4 +517,57 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
|
||||||
this.handshakeChannel.attr(FML_DISPATCHER).remove();
|
this.handshakeChannel.attr(FML_DISPATCHER).remove();
|
||||||
this.manager.channel().attr(FML_DISPATCHER).remove();
|
this.manager.channel().attr(FML_DISPATCHER).remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class MultiPartCustomPayload extends S3FPacketCustomPayload
|
||||||
|
{
|
||||||
|
private String channel;
|
||||||
|
private byte[] data;
|
||||||
|
private PacketBuffer data_buf = null;
|
||||||
|
private int part_count = 0;
|
||||||
|
private int part_expected = 0;
|
||||||
|
private int offset = 0;
|
||||||
|
|
||||||
|
private MultiPartCustomPayload(PacketBuffer preamble) throws IOException
|
||||||
|
{
|
||||||
|
channel = preamble.readStringFromBuffer(20);
|
||||||
|
part_count = preamble.readUnsignedByte();
|
||||||
|
int length = preamble.readInt();
|
||||||
|
if (length <= 0 || length >= FMLProxyPacket.MAX_LENGTH)
|
||||||
|
{
|
||||||
|
throw new IOException("The received FML MultiPart packet outside of valid length bounds, Max: " + FMLProxyPacket.MAX_LENGTH + ", Received: " + length);
|
||||||
|
}
|
||||||
|
data = new byte[length];
|
||||||
|
data_buf = new PacketBuffer(Unpooled.wrappedBuffer(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processPart(PacketBuffer input) throws IOException
|
||||||
|
{
|
||||||
|
int part = (int)(input.readByte() & 0xFF);
|
||||||
|
if (part != part_expected)
|
||||||
|
{
|
||||||
|
throw new IOException("Received FML MultiPart packet out of order, Expected " + part_expected + " Got " + part);
|
||||||
|
}
|
||||||
|
int len = input.readableBytes() - 1;
|
||||||
|
input.readBytes(data, offset, len);
|
||||||
|
part_expected++;
|
||||||
|
offset += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isComplete()
|
||||||
|
{
|
||||||
|
return part_expected == part_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String func_149169_c() // getChannel
|
||||||
|
{
|
||||||
|
return this.channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PacketBuffer func_180735_b() // getData
|
||||||
|
{
|
||||||
|
return this.data_buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,26 @@ package cpw.mods.fml.common.network.internal;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import net.minecraft.network.INetHandler;
|
import net.minecraft.network.INetHandler;
|
||||||
import net.minecraft.network.NetworkManager;
|
import net.minecraft.network.NetworkManager;
|
||||||
import net.minecraft.network.Packet;
|
import net.minecraft.network.Packet;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.network.play.client.C17PacketCustomPayload;
|
import net.minecraft.network.play.client.C17PacketCustomPayload;
|
||||||
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
import org.apache.logging.log4j.core.helpers.Integers;
|
import org.apache.logging.log4j.core.helpers.Integers;
|
||||||
|
|
||||||
import com.google.common.collect.ConcurrentHashMultiset;
|
import com.google.common.collect.ConcurrentHashMultiset;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multiset;
|
import com.google.common.collect.Multiset;
|
||||||
import com.google.common.collect.Multiset.Entry;
|
import com.google.common.collect.Multiset.Entry;
|
||||||
import com.google.common.collect.Multisets;
|
import com.google.common.collect.Multisets;
|
||||||
|
|
||||||
import cpw.mods.fml.common.FMLLog;
|
import cpw.mods.fml.common.FMLLog;
|
||||||
import cpw.mods.fml.common.network.FMLNetworkException;
|
import cpw.mods.fml.common.network.FMLNetworkException;
|
||||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||||
|
@ -116,9 +123,42 @@ public class FMLProxyPacket implements Packet {
|
||||||
return new C17PacketCustomPayload(channel, payload);
|
return new C17PacketCustomPayload(channel, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Packet toS3FPacket()
|
static final int PART_SIZE = 0x1000000 - 0x50; // Make it a constant so that it gets inlined below.
|
||||||
|
public static final int MAX_LENGTH = PART_SIZE * 255;
|
||||||
|
public List<Packet> toS3FPackets() throws IOException
|
||||||
{
|
{
|
||||||
return new S3FPacketCustomPayload(channel, payload);
|
List<Packet> ret = Lists.newArrayList();
|
||||||
|
byte[] data = payload.array();
|
||||||
|
|
||||||
|
if (data.length < PART_SIZE)
|
||||||
|
{
|
||||||
|
ret.add(new S3FPacketCustomPayload(channel, payload));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int parts = (int)Math.ceil(data.length / (double)(PART_SIZE - 1)); //We add a byte header so -1
|
||||||
|
if (parts > 255)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Payload may not be larger than " + MAX_LENGTH + " bytes");
|
||||||
|
}
|
||||||
|
PacketBuffer preamble = new PacketBuffer(Unpooled.buffer());
|
||||||
|
preamble.func_180714_a(channel);
|
||||||
|
preamble.writeByte(parts);
|
||||||
|
preamble.writeInt(data.length);
|
||||||
|
ret.add(new S3FPacketCustomPayload("FML|MP", preamble));
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
for (int x = 0; x < parts; x++)
|
||||||
|
{
|
||||||
|
int length = Math.min(PART_SIZE, data.length - offset + 1);
|
||||||
|
byte[] tmp = new byte[length];
|
||||||
|
tmp[0] = (byte)(x & 0xFF);
|
||||||
|
System.arraycopy(data, offset, tmp, 1, tmp.length - 1);
|
||||||
|
offset += tmp.length - 1;
|
||||||
|
ret.add(new S3FPacketCustomPayload("FML|MP", new PacketBuffer(Unpooled.wrappedBuffer(tmp))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTarget(Side target)
|
public void setTarget(Side target)
|
||||||
|
|
|
@ -65,16 +65,8 @@ public class GameData {
|
||||||
|
|
||||||
private static final GameData mainData = new GameData();
|
private static final GameData mainData = new GameData();
|
||||||
|
|
||||||
/**
|
private static final FMLControlledNamespacedRegistry<Block> blockRegistry = getBlockRegistry();
|
||||||
* @deprecated use {@link #getBlockRegistry()} instead.
|
private static final FMLControlledNamespacedRegistry<Item> itemRegistry = getItemRegistry();
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final FMLControlledNamespacedRegistry<Block> blockRegistry = getBlockRegistry();
|
|
||||||
/**
|
|
||||||
* @deprecated use {@link #getItemRegistry()} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final FMLControlledNamespacedRegistry<Item> itemRegistry = getItemRegistry();
|
|
||||||
|
|
||||||
private static Table<String, String, ItemStack> customItemStacks = HashBasedTable.create();
|
private static Table<String, String, ItemStack> customItemStacks = HashBasedTable.create();
|
||||||
private static Map<UniqueIdentifier, ModContainer> customOwners = Maps.newHashMap();
|
private static Map<UniqueIdentifier, ModContainer> customOwners = Maps.newHashMap();
|
||||||
|
@ -970,7 +962,10 @@ public class GameData {
|
||||||
Object blockName = iBlockRegistry.func_177774_c(item.blockInstance);
|
Object blockName = iBlockRegistry.func_177774_c(item.blockInstance);
|
||||||
Object itemName = iItemRegistry.func_177774_c(item);
|
Object itemName = iItemRegistry.func_177774_c(item);
|
||||||
|
|
||||||
if (blockName != null && !blockName.equals(itemName))
|
//Vanilla has a mismatch:
|
||||||
|
//Block <-> ItemBlock name mismatch, block name minecraft:standing_banner, item name minecraft:banner
|
||||||
|
//TODO: Untie these in the rest of the registry
|
||||||
|
if (blockName != null && !blockName.equals(itemName) && !"minecraft:standing_banner".equals(blockName.toString()))
|
||||||
{
|
{
|
||||||
FMLLog.bigWarning("Block <-> ItemBlock name mismatch, block name %s, item name %s", blockName, itemName);
|
FMLLog.bigWarning("Block <-> ItemBlock name mismatch, block name %s, item name %s", blockName, itemName);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue