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;
}