bool NegotiateProtocolExtension() { writer.Write(Packet.MakeExtInfo(12).Data); writer.Write(Packet.MakeExtEntry(CustomBlocksExtName, CustomBlocksExtVersion).Data); writer.Write(Packet.MakeExtEntry(ClickDistanceExtName, ClickDistanceExtVersion).Data); writer.Write(Packet.MakeExtEntry(EnvColorsExtName, EnvColorsExtVersion).Data); writer.Write(Packet.MakeExtEntry(ChangeModelExtName, ChangeModelExtVersion).Data); writer.Write(Packet.MakeExtEntry(EnvMapAppearanceExtName, EnvMapAppearanceExtVersion).Data); writer.Write(Packet.MakeExtEntry(HeldBlockExtName, HeldBlockExtVersion).Data); writer.Write(Packet.MakeExtEntry(ExtPlayerListExtName, ExtPlayerListExtVersion).Data); writer.Write(Packet.MakeExtEntry(SelectionCuboidExtName, SelectionCuboidExtVersion).Data); writer.Write(Packet.MakeExtEntry(MessageTypesExtName, MessageTypesExtVersion).Data); writer.Write(Packet.MakeExtEntry(HackControlExtName, HackControlExtVersion).Data); writer.Write(Packet.MakeExtEntry(LongerMessagesExtName, LongerMessagesExtVersion).Data); writer.Write(Packet.MakeExtEntry(FullCP437ExtName, FullCP437ExtVersion).Data); Logger.Log(LogType.Debug, "Sent ExtInfo and entry packets"); // Expect ExtInfo reply from the client OpCode extInfoReply = (OpCode)reader.ReadByte(); Logger.Log(LogType.Debug, "Expected: {0} / Received: {1}", OpCode.ExtInfo, extInfoReply); if (extInfoReply != OpCode.ExtInfo) { Logger.Log(LogType.Warning, "Player {0} from {1}: Unexpected ExtInfo reply({2})", Name, IP, extInfoReply); return(false); } //read EXT_INFO from client ClientName = reader.ReadString(); int expectedEntries = reader.ReadInt16(); // Get all of the ext info packets bool sendCustomBlockPacket = false; List <string> clientExts = new List <string>(); for (int i = 0; i < expectedEntries; i++) { // Expect ExtEntry replies(0 or more) OpCode extEntryReply = (OpCode)reader.ReadByte(); Logger.Log(LogType.Debug, "Expected: {0} / Received: {1}", OpCode.ExtEntry, extEntryReply); if (extEntryReply != OpCode.ExtEntry) { Logger.Log(LogType.Warning, "Player {0} from {1}: Unexpected ExtEntry reply({2})", Name, IP, extEntryReply); return(false); } string extName = reader.ReadString(); int extVersion = reader.ReadInt32(); if (extName == CustomBlocksExtName && extVersion == CustomBlocksExtVersion) { // Hooray, client supports custom blocks! We still need to check support level. sendCustomBlockPacket = true; clientExts.Add(extName + " " + extVersion); } else if (extName == ClickDistanceExtName && extVersion == ClickDistanceExtVersion) { SupportsClickDistance = true; clientExts.Add(extName + " " + extVersion); } else if (extName == EnvColorsExtName && extVersion == EnvColorsExtVersion) { SupportsEnvColors = true; clientExts.Add(extName + " " + extVersion); } else if (extName == ChangeModelExtName && extVersion == ChangeModelExtVersion) { SupportsChangeModel = true; clientExts.Add(extName + " " + extVersion); } else if (extName == EnvMapAppearanceExtName && extVersion == EnvMapAppearanceExtVersion) { SupportsEnvMapAppearance = true; clientExts.Add(extName + " " + extVersion); } else if (extName == HeldBlockExtName && extVersion == HeldBlockExtVersion) { SupportsHeldBlock = true; clientExts.Add(extName + " " + extVersion); } else if (extName == ExtPlayerListExtName && extVersion == ExtPlayerListExtVersion) { SupportsExtPlayerList = true; clientExts.Add(extName + " " + extVersion); } else if (extName == SelectionCuboidExtName && extVersion == SelectionCuboidExtVersion) { SupportsSelectionCuboid = true; clientExts.Add(extName + " " + extVersion); } else if (extName == MessageTypesExtName && extVersion == MessageTypesExtVersion) { SupportsMessageTypes = true; clientExts.Add(extName + " " + extVersion); } else if (extName == EnvWeatherTypeExtName && extVersion == EnvWeatherTypeExtVersion) { SupportsEnvWeatherType = true; clientExts.Add(extName + " " + extVersion); } else if (extName == HackControlExtName && extVersion == HackControlExtVersion) { SupportsHackControl = true; clientExts.Add(extName + " " + extVersion); } else if (extName == LongerMessagesExtName && extVersion == LongerMessagesExtVersion) { SupportsLongerMessages = true; clientExts.Add(extName + " " + extVersion); } else if (extName == FullCP437ExtName && extVersion == FullCP437ExtVersion) { SupportsFullCP437 = true; clientExts.Add(extName + " " + extVersion); } } // log client's capabilities if (clientExts.Count > 0) { Logger.Log(LogType.Debug, "Player {0} is using \"{1}\", supporting: {2}", Name, ClientName, clientExts.JoinToString(", ")); } if (sendCustomBlockPacket) { // if client also supports CustomBlockSupportLevel, figure out what level to use // Send CustomBlockSupportLevel writer.Write(Packet.MakeCustomBlockSupportLevel(CustomBlocksLevel).Data); // Expect CustomBlockSupportLevel reply OpCode customBlockSupportLevelReply = (OpCode)reader.ReadByte(); Logger.Log(LogType.Debug, "Expected: {0} / Received: {1}", OpCode.CustomBlocks, customBlockSupportLevelReply); if (customBlockSupportLevelReply != OpCode.CustomBlocks) { Logger.Log(LogType.Warning, "Player {0} from {1}: Unexpected CustomBlockSupportLevel reply({2})", Name, IP, customBlockSupportLevelReply); return(false); } byte clientLevel = reader.ReadByte(); UsesCustomBlocks = (clientLevel >= CustomBlocksLevel); } return(true); }