bool NegotiateProtocolExtension() { // write our ExtInfo and ExtEntry packets writer.Write(Packet.MakeExtInfo("ProCraft", 30).Bytes); writer.Write(Packet.MakeExtEntry(ClickDistanceExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(CustomBlocksExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(HeldBlockExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(TextHotKeyExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(ExtPlayerListExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(EnvColorsExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(SelectionCuboidExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(BlockPermissionsExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(ChangeModelExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(EnvMapAppearanceExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(EnvWeatherTypeExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(HackControlExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(ExtPlayerListExtName, 2).Bytes); writer.Write(Packet.MakeExtEntry(PlayerClickExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(MessageTypesExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(EmoteFixExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(LongerMessagesExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(FullCP437ExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(BlockDefinitionsExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(BlockDefinitionsExtExtName, 2).Bytes); writer.Write(Packet.MakeExtEntry(BulkBlockUpdateExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(TextColorsExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(EnvMapAspectExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(ExtPlayerPositionsExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(EntityPropertyExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(TwoWayPingExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(InventoryOrderExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(InstantMOTDExtName, 1).Bytes); writer.Write(Packet.MakeExtEntry(FastMapExtName, 1).Bytes); // Fix for ClassiCube Client which violates the spec - // If server supports version > 1 but client version 1, client should reply with version 1. // ClassiCube just doesn't reply at all in that case. writer.Write(Packet.MakeExtEntry(EnvMapAppearanceExtName, 2).Bytes); // Expect ExtInfo reply from the client OpCode extInfoReply = reader.ReadOpCode(); //Logger.Log(LogType.Debug, "Expected: {0} / Received: {1}", OpCode.ExtInfo, extInfoReply ); if (extInfoReply != OpCode.ExtInfo) { Logger.Log(LogType.Debug, "Player {0}: Unexpected ExtInfo reply ({1})", Info.Name, extInfoReply); return(false); } ClientName = reader.ReadString(); int expectedEntries = reader.ReadInt16(); // wait for client to send its ExtEntries for (int i = 0; i < expectedEntries; i++) { // Expect ExtEntry replies (0 or more) OpCode extEntryReply = reader.ReadOpCode(); if (extEntryReply != OpCode.ExtEntry) { Logger.Log(LogType.Warning, "Player {0} from {1}: Unexpected ExtEntry reply ({2})", Name, IP, extInfoReply); return(false); } string extName = reader.ReadString(); int version = reader.ReadInt32(); CpeExt ext = CpeExt.None; switch (extName) { case CustomBlocksExtName: if (version == 1) { ext = CpeExt.CustomBlocks; } break; case BlockPermissionsExtName: if (version == 1) { ext = CpeExt.BlockPermissions; } break; case ClickDistanceExtName: if (version == 1) { ext = CpeExt.ClickDistance; } break; case EnvColorsExtName: if (version == 1) { ext = CpeExt.EnvColors; } break; case ChangeModelExtName: if (version == 1) { ext = CpeExt.ChangeModel; } break; case EnvMapAppearanceExtName: if (version == 1) { ext = CpeExt.EnvMapAppearance; } if (version == 2) { ext = CpeExt.EnvMapAppearance2; } break; case EnvWeatherTypeExtName: if (version == 1) { ext = CpeExt.EnvWeatherType; } break; case HeldBlockExtName: if (version == 1) { ext = CpeExt.HeldBlock; } break; case ExtPlayerListExtName: if (version == 1) { ext = CpeExt.ExtPlayerList; if (Supports(CpeExt.ExtPlayerList2)) { ext = CpeExt.ExtPlayerList2; } } else if (version == 2) { ext = CpeExt.ExtPlayerList2; if (Supports(CpeExt.ExtPlayerList)) { supportedExts.Remove(CpeExt.ExtPlayerList); } } break; case SelectionCuboidExtName: if (version == 1) { ext = CpeExt.SelectionCuboid; } break; case MessageTypesExtName: if (version == 1) { ext = CpeExt.MessageType; } break; case HackControlExtName: if (version == 1) { ext = CpeExt.HackControl; } break; case EmoteFixExtName: if (version == 1) { ext = CpeExt.EmoteFix; } break; case TextHotKeyExtName: if (version == 1) { ext = CpeExt.TextHotKey; } break; case PlayerClickExtName: if (version == 1) { ext = CpeExt.PlayerClick; } break; case LongerMessagesExtName: if (version == 1) { ext = CpeExt.LongerMessages; } break; case FullCP437ExtName: if (version == 1) { ext = CpeExt.FullCP437; } break; case BlockDefinitionsExtName: if (version == 1) { ext = CpeExt.BlockDefinitions; } break; case BlockDefinitionsExtExtName: if (version == 1) { ext = CpeExt.BlockDefinitionsExt; } if (version == 2) { ext = CpeExt.BlockDefinitionsExt2; } break; case BulkBlockUpdateExtName: if (version == 1) { ext = CpeExt.BulkBlockUpdate; } break; case TextColorsExtName: if (version == 1) { ext = CpeExt.TextColors; } break; case EnvMapAspectExtName: if (version == 1) { ext = CpeExt.EnvMapAspect; } break; case ExtPlayerPositionsExtName: if (version == 1) { ext = CpeExt.ExtPlayerPositions; } supportsExtPositions = true; break; case EntityPropertyExtName: if (version == 1) { ext = CpeExt.EntityProperty; } break; case TwoWayPingExtName: if (version == 1) { ext = CpeExt.TwoWayPing; } break; case InventoryOrderExtName: if (version == 1) { ext = CpeExt.InventoryOrder; } break; case InstantMOTDExtName: if (version == 1) { ext = CpeExt.InstantMOTD; } break; case FastMapExtName: if (version == 1) { ext = CpeExt.FastMap; } break; } if (ext != CpeExt.None) { supportedExts.Add(ext); } } supportsCustomBlocks = Supports(CpeExt.CustomBlocks); supportsBlockDefs = Supports(CpeExt.BlockDefinitions); // log client's capabilities if (supportedExts.Count > 0) { Logger.Log(LogType.Debug, "Player {0} is using \"{1}\", supporting: {2}", Info.Name, ClientName, supportedExts.JoinToString(", ")); } else if (supportedExts.Count == 0) { Kick("Please use the ClassicalSharp client", LeaveReason.InvalidOpcodeKick); } // if client also supports CustomBlockSupportLevel, figure out what level to use // Send CustomBlockSupportLevel writer.Write(Packet.MakeCustomBlockSupportLevel(CustomBlocksLevel).Bytes); if (Supports(CpeExt.TextColors)) { for (int i = 0; i < Color.ExtColors.Length; i++) { if (Color.ExtColors[i].Undefined) { continue; } writer.Write(Packet.MakeSetTextColor(Color.ExtColors[i]).Bytes); } } return(true); }
bool NegotiateProtocolExtension() { writer.Write(Packet.MakeExtInfo(13).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); writer.Write(Packet.MakeExtEntry(BlockPermissionsExtName, BlockPermissionsExtVersion).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); } else if (extName == BlockPermissionsExtName && extVersion == BlockPermissionsExtVersion) { SupportsBlockPermissions = 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); }
bool NegotiateProtocolExtension() { this.reader = new PacketReader(this.stream); // write our ExtInfo and ExtEntry packets writer.Write(Packet.MakeExtInfo(2).Data); writer.Write(Packet.MakeExtEntry(CustomBlocksExtName, CustomBlocksExtVersion).Data); writer.Write(Packet.MakeExtEntry(BlockPermissionsExtName, BlockPermissionsExtVersion).Data); Logger.Log(LogType.SystemActivity, "Sent ExtInfo and entry packets"); // Expect ExtInfo reply from the client OpCode extInfoReply = ( OpCode )reader.ReadByte(); Logger.Log(LogType.SystemActivity, "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 ClientName = reader.ReadString(); int expectedEntries = reader.ReadInt16(); // wait for client to send its ExtEntries 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.SystemActivity, "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 == BlockPermissionsExtName && extVersion == BlockPermissionsExtVersion) { SupportsBlockPermissions = true; clientExts.Add(extName + " " + extVersion); } else if (extName == SelectionBoxExtName && extVersion == SelectionBoxExtVersion) { SelectionBoxExt = true; } } // log client's capabilities if (clientExts.Count > 0) { Logger.Log(LogType.SystemActivity, "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.SystemActivity, "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); } this.reader = new BinaryReader(this.stream); return(true); }