Separate writing methods, allow entering CP437 directly into chat via clipboard if server supports FullCP437.

This commit is contained in:
UnknownShadow200 2015-11-05 18:43:16 +11:00
parent 1b72c67cac
commit 5218124c6c
9 changed files with 228 additions and 118 deletions

View File

@ -140,14 +140,16 @@ namespace ClassicalSharp {
chatInputTexture.Y1 += deltaY;
}
static bool IsInvalidChar( char c ) {
bool IsValidChar( char c ) {
if( c == '&' ) return false;
if( c >= ' ' && c <= '~' ) return true; // ascii
bool isCP437 = Utils.ControlCharReplacements.IndexOf( c ) >= 0 ||
Utils.ExtendedCharReplacements.IndexOf( c ) >= 0;
// Make sure we're in the printable text range from 0x20 to 0x7E
return c < ' ' || c == '&' || c > '~';
bool supportsCP437 = game.Network.ServerSupportsFullCP437;
return supportsCP437 && isCP437;
}
static char[] trimChars = { ' ' };
public void SendTextInBufferAndReset() {
SendInBuffer();
typingLogPos = game.Chat.InputLog.Count; // Index of newest entry + 1.
@ -209,7 +211,7 @@ namespace ClassicalSharp {
#region Input handling
public override bool HandlesKeyPress( char key ) {
if( chatInputText.Length < len && !IsInvalidChar( key ) ) {
if( chatInputText.Length < len && IsValidChar( key ) ) {
if( caretPos == -1 ) {
chatInputText.Append( chatInputText.Length, key );
} else {
@ -326,7 +328,7 @@ namespace ClassicalSharp {
if( String.IsNullOrEmpty( text ) ) return true;
for( int i = 0; i < text.Length; i++ ) {
if( IsInvalidChar( text[i] ) ) {
if( !IsValidChar( text[i] ) ) {
game.Chat.Add( "&eClipboard contained characters that can't be sent." );
return true;
}

View File

@ -176,12 +176,13 @@
<Compile Include="Network\NetworkProcessor.CPE.cs" />
<Compile Include="Network\NetworkProcessor.cs" />
<Compile Include="Network\Utils\AsyncDownloader.cs" />
<Compile Include="Network\Utils\FastNetReader.cs" />
<Compile Include="Network\Utils\NetReader.cs" />
<Compile Include="Network\Utils\FixedBufferStream.cs" />
<Compile Include="Network\Utils\GZipHeaderReader.cs" />
<Compile Include="Network\NetworkProcessor.WoM.cs" />
<Compile Include="Commands\CommandManager.cs" />
<Compile Include="Commands\CommandReader.cs" />
<Compile Include="Network\Utils\NetWriter.cs" />
<Compile Include="Physics\BoundingBox.cs" />
<Compile Include="Physics\IntersectionUtils.cs" />
<Compile Include="Physics\PickedPos.cs" />

View File

@ -0,0 +1,84 @@
using System;
using System.Drawing;
using ClassicalSharp.GraphicsAPI;
using OpenTK;
namespace ClassicalSharp.Model {
public class TestModel : IModel {
ModelSet Set, SetSlim;
public TestModel( Game window ) : base( window ) {
vertices = new ModelVertex[boxVertices * ( 7 + 2 )];
Set = new ModelSet();
Set.Head = BuildBox( MakeBoxBounds( -0, 0, -0, 8, 8, 8 )
.SetTexOrigin( 0, 0 ) );
Set.Torso = BuildBox( MakeBoxBounds( -4, 12, -2, 4, 24, 2 )
.SetTexOrigin( 16, 16 ) );
Set.LeftLeg = BuildBox( MakeBoxBounds( 0, 0, -2, -4, 12, 2 )
.SetTexOrigin( 0, 16 ) );
Set.RightLeg = BuildBox( MakeBoxBounds( 0, 0, -2, 4, 12, 2 ).
SetTexOrigin( 0, 16 ) );
Set.Hat = BuildBox( MakeBoxBounds( -4, 24, -4, 4, 32, 4 )
.SetTexOrigin( 32, 0 )
.SetModelBounds( -4.5f, 23.5f, -4.5f, 4.5f, 32.5f, 4.5f ) );
Set.LeftArm = BuildBox( MakeBoxBounds( -4, 12, -2, -8, 24, 2 )
.SetTexOrigin( 40, 16 ) );
Set.RightArm = BuildBox( MakeBoxBounds( 4, 12, -2, 8, 24, 2 )
.SetTexOrigin( 40, 16 ) );
SetSlim = new ModelSet();
SetSlim.Head = Set.Head;
SetSlim.Torso = Set.Torso;
SetSlim.LeftLeg = Set.LeftLeg;
SetSlim.RightLeg = Set.RightLeg;
SetSlim.LeftArm = BuildBox( MakeBoxBounds( -7, 12, -2, -4, 24, 2 )
.SetTexOrigin( 32, 48 ) );
SetSlim.RightArm = BuildBox( MakeBoxBounds( 4, 12, -2, 7, 24, 2 )
.SetTexOrigin( 40, 16 ) );
SetSlim.Hat = Set.Hat;
}
public override float NameYOffset {
get { return 2.1375f; }
}
public override float GetEyeY( Player player ) {
return 27/16f;
}
public override Vector3 CollisionSize {
get { return new Vector3( 8/16f, 28.5f/16f, 8/16f ); }
}
public override BoundingBox PickingBounds {
get { return new BoundingBox( -8/16f, 0, -4/16f, 8/16f, 32/16f, 4/16f ); }
}
protected override void DrawPlayerModel( Player p ) {
graphics.Texturing = true;
int texId = p.MobTextureId <= 0 ? cache.TestTexId : p.MobTextureId;
graphics.BindTexture( texId );
SkinType skinType = p.SkinType;
_64x64 = skinType != SkinType.Type64x32;
ModelSet model = skinType == SkinType.Type64x64Slim ? SetSlim : Set;
DrawRotate( 0, 24/16f, 0, -p.PitchRadians, 0, 0, model.Head );
DrawPart( model.Torso );
DrawRotate( 0, 12/16f, 0, p.leftLegXRot, 0, 0, model.LeftLeg );
DrawRotate( 0, 12/16f, 0, p.rightLegXRot, 0, 0, model.RightLeg );
DrawRotate( -6/16f, 22/16f, 0, p.leftArmXRot, 0, p.leftArmZRot, model.LeftArm );
DrawRotate( 6/16f, 22/16f, 0, p.rightArmXRot, 0, p.rightArmZRot, model.RightArm );
graphics.AlphaTest = true;
if( p.RenderHat )
DrawRotate( 0, 24f/16f, 0, -p.PitchRadians, 0, 0, model.Hat );
}
class ModelSet {
public ModelPart Head, Torso, LeftLeg, RightLeg, LeftArm, RightArm, Hat;
}
}
}

View File

@ -28,5 +28,6 @@ namespace ClassicalSharp {
public bool Disconnected;
public bool UsingExtPlayerList, UsingPlayerClick;
public bool ServerSupportsPatialMessages;
public bool ServerSupportsFullCP437;
}
}

View File

@ -16,35 +16,35 @@ namespace ClassicalSharp {
SendPacket();
}
private static void MakeExtInfo( string appName, int extensionsCount ) {
WriteUInt8( (byte)PacketId.CpeExtInfo );
WriteString( appName );
WriteInt16( (short)extensionsCount );
void MakeExtInfo( string appName, int extensionsCount ) {
writer.WriteUInt8( (byte)PacketId.CpeExtInfo );
writer.WriteString( appName );
writer.WriteInt16( (short)extensionsCount );
}
private static void MakeExtEntry( string extensionName, int extensionVersion ) {
WriteUInt8( (byte)PacketId.CpeExtEntry );
WriteString( extensionName );
WriteInt32( extensionVersion );
void MakeExtEntry( string extensionName, int extensionVersion ) {
writer.WriteUInt8( (byte)PacketId.CpeExtEntry );
writer.WriteString( extensionName );
writer.WriteInt32( extensionVersion );
}
private static void MakeCustomBlockSupportLevel( byte version ) {
WriteUInt8( (byte)PacketId.CpeCustomBlockSupportLevel );
WriteUInt8( version );
void MakeCustomBlockSupportLevel( byte version ) {
writer.WriteUInt8( (byte)PacketId.CpeCustomBlockSupportLevel );
writer.WriteUInt8( version );
}
private static void MakePlayerClick( byte button, bool buttonDown, float yaw, float pitch, byte targetEntity,
Vector3I targetPos, CpeBlockFace targetFace ) {
WriteUInt8( (byte)PacketId.CpePlayerClick );
WriteUInt8( button );
WriteUInt8( buttonDown ? (byte)0 : (byte)1 );
WriteInt16( (short)Utils.DegreesToPacked( yaw, 65536 ) );
WriteInt16( (short)Utils.DegreesToPacked( pitch, 65536 ) );
WriteUInt8( targetEntity );
WriteInt16( (short)targetPos.X );
WriteInt16( (short)targetPos.Y );
WriteInt16( (short)targetPos.Z );
WriteUInt8( (byte)targetFace );
void MakePlayerClick( byte button, bool buttonDown, float yaw, float pitch, byte targetEntity,
Vector3I targetPos, CpeBlockFace targetFace ) {
writer.WriteUInt8( (byte)PacketId.CpePlayerClick );
writer.WriteUInt8( button );
writer.WriteUInt8( buttonDown ? (byte)0 : (byte)1 );
writer.WriteInt16( (short)Utils.DegreesToPacked( yaw, 65536 ) );
writer.WriteInt16( (short)Utils.DegreesToPacked( pitch, 65536 ) );
writer.WriteUInt8( targetEntity );
writer.WriteInt16( (short)targetPos.X );
writer.WriteInt16( (short)targetPos.Y );
writer.WriteInt16( (short)targetPos.Z );
writer.WriteUInt8( (byte)targetFace );
}
#endregion
@ -88,6 +88,8 @@ namespace ClassicalSharp {
packetSizes[(int)PacketId.CpeEnvSetMapApperance] += 4;
} else if( extName == "LongerMessages" ) {
ServerSupportsPatialMessages = true;
} else if( extName == "FullCP437" ) {
ServerSupportsFullCP437 = true;
}
cpeServerExtensionsCount--;

View File

@ -26,7 +26,6 @@ namespace ClassicalSharp {
}
Socket socket;
NetworkStream stream;
Game game;
bool receivedFirstPosition;
@ -42,32 +41,14 @@ namespace ClassicalSharp {
return;
}
stream = new NetworkStream( socket, true );
reader = new FastNetReader( stream );
NetworkStream stream = new NetworkStream( socket, true );
reader = new NetReader( stream );
writer = new NetWriter( stream );
gzippedMap = new FixedBufferStream( reader.buffer );
MakeLoginPacket( game.Username, game.Mppass );
SendPacket();
}
public override void SendChat( string text, bool partial ) {
if( String.IsNullOrEmpty( text ) ) return;
byte payload = !ServerSupportsPatialMessages ? (byte)0xFF:
partial ? (byte)1 : (byte)0;
MakeMessagePacket( text, payload );
SendPacket();
}
public override void SendPosition( Vector3 pos, float yaw, float pitch ) {
byte payload = sendHeldBlock ? (byte)game.Inventory.HeldBlock : (byte)0xFF;
MakePositionPacket( pos, yaw, pitch, payload );
SendPacket();
}
public override void SendSetBlock( int x, int y, int z, bool place, byte block ) {
MakeSetBlockPacket( (short)x, (short)y, (short)z, place, block );
SendPacket();
}
public override void Dispose() {
socket.Close();
@ -133,79 +114,57 @@ namespace ClassicalSharp {
8, 86, 2, 4, 66, 69, 2, 8, 138, 0, 80, 2,
};
#region Writing
NetWriter writer;
static byte[] outBuffer = new byte[131];
static int outIndex;
private static void MakeLoginPacket( string username, string verKey ) {
WriteUInt8( (byte)PacketId.Handshake );
WriteUInt8( 7 ); // protocol version
WriteString( username );
WriteString( verKey );
WriteUInt8( 0x42 );
public override void SendChat( string text, bool partial ) {
if( String.IsNullOrEmpty( text ) ) return;
byte payload = !ServerSupportsPatialMessages ? (byte)0xFF:
partial ? (byte)1 : (byte)0;
writer.WriteUInt8( (byte)PacketId.Message );
writer.WriteUInt8( payload );
writer.WriteString( text );
SendPacket();
}
private static void MakeSetBlockPacket( short x, short y, short z, bool place, byte block ) {
WriteUInt8( (byte)PacketId.SetBlockClient );
WriteInt16( x );
WriteInt16( y );
WriteInt16( z );
WriteUInt8( place ? (byte)1 : (byte)0 );
WriteUInt8( block );
public override void SendPosition( Vector3 pos, float yaw, float pitch ) {
byte payload = sendHeldBlock ? (byte)game.Inventory.HeldBlock : (byte)0xFF;
MakePositionPacket( pos, yaw, pitch, payload );
SendPacket();
}
private static void MakePositionPacket( Vector3 pos, float yaw, float pitch, byte payload ) {
WriteUInt8( (byte)PacketId.EntityTeleport );
WriteUInt8( payload ); // held block when using HeldBlock, otherwise just 255
WriteInt16( (short)( pos.X * 32 ) );
WriteInt16( (short)( (int)( pos.Y * 32 ) + 51 ) );
WriteInt16( (short)( pos.Z * 32 ) );
WriteUInt8( (byte)Utils.DegreesToPacked( yaw, 256 ) );
WriteUInt8( (byte)Utils.DegreesToPacked( pitch, 256 ) );
public override void SendSetBlock( int x, int y, int z, bool place, byte block ) {
writer.WriteUInt8( (byte)PacketId.SetBlockClient );
writer.WriteInt16( (short)x );
writer.WriteInt16( (short)y );
writer.WriteInt16( (short)z );
writer.WriteUInt8( place ? (byte)1 : (byte)0 );
writer.WriteUInt8( block );
SendPacket();
}
private static void MakeMessagePacket( string text, byte payload ) {
WriteUInt8( (byte)PacketId.Message );
WriteUInt8( payload );
WriteString( text );
void MakeLoginPacket( string username, string verKey ) {
writer.WriteUInt8( (byte)PacketId.Handshake );
writer.WriteUInt8( 7 ); // protocol version
writer.WriteString( username );
writer.WriteString( verKey );
writer.WriteUInt8( 0x42 );
}
static void WriteString( string value ) {
int count = Math.Min( value.Length, 64 );
for( int i = 0; i < count; i++ ) {
char c = value[i];
outBuffer[outIndex + i] = (byte)( c >= '\u0080' ? '?' : c );
}
for( int i = value.Length; i < 64; i++ ) {
outBuffer[outIndex + i] = (byte)' ';
}
outIndex += 64;
}
static void WriteUInt8( byte value ) {
outBuffer[outIndex++] = value;
}
static void WriteInt16( short value ) {
outBuffer[outIndex++] = (byte)( value >> 8 );
outBuffer[outIndex++] = (byte)( value );
}
static void WriteInt32( int value ) {
outBuffer[outIndex++] = (byte)( value >> 24 );
outBuffer[outIndex++] = (byte)( value >> 16 );
outBuffer[outIndex++] = (byte)( value >> 8 );
outBuffer[outIndex++] = (byte)( value );
void MakePositionPacket( Vector3 pos, float yaw, float pitch, byte payload ) {
writer.WriteUInt8( (byte)PacketId.EntityTeleport );
writer.WriteUInt8( payload ); // held block when using HeldBlock, otherwise just 255
writer.WriteInt16( (short)(pos.X * 32) );
writer.WriteInt16( (short)((int)(pos.Y * 32) + 51) );
writer.WriteInt16( (short)(pos.Z * 32) );
writer.WriteUInt8( (byte)Utils.DegreesToPacked( yaw, 256 ) );
writer.WriteUInt8( (byte)Utils.DegreesToPacked( pitch, 256 ) );
}
void SendPacket() {
int packetLength = outIndex;
outIndex = 0;
if( Disconnected ) return;
try {
stream.Write( outBuffer, 0, packetLength );
writer.Send( Disconnected );
} catch( IOException ex ) {
ErrorHandler.LogError( "wrting packets", ex );
game.Disconnect( "&eLost connection to the server", "I/O Error while writing packets" );
@ -218,7 +177,7 @@ namespace ClassicalSharp {
#region Reading
FastNetReader reader;
NetReader reader;
DateTime receiveStart;
DeflateStream gzipStream;
GZipHeaderReader gzipHeader;

View File

@ -1,15 +1,15 @@
using System;
using System.Net.Sockets;
using System;
using System.Net.Sockets;
namespace ClassicalSharp {
// Basically a much faster version of List<byte>( capacity )
internal class FastNetReader {
internal class NetReader {
public byte[] buffer = new byte[4096 * 4];
public int size = 0;
public NetworkStream Stream;
public FastNetReader( NetworkStream stream ) {
public NetReader( NetworkStream stream ) {
Stream = stream;
}

View File

@ -0,0 +1,60 @@
using System;
using System.Net.Sockets;
namespace ClassicalSharp {
internal class NetWriter {
public byte[] buffer = new byte[131];
public int index = 0;
public NetworkStream Stream;
public NetWriter( NetworkStream stream ) {
Stream = stream;
}
public void WriteString( string value ) {
int count = Math.Min( value.Length, 64 );
for( int i = 0; i < count; i++ ) {
char c = value[i];
int cpIndex = 0;
if( c >= ' ' && c <= '~' ) {
buffer[index + i] = (byte)c;
} else if( (cpIndex = Utils.ControlCharReplacements.IndexOf( c ) ) >= 0 ) {
buffer[index + i] = (byte)cpIndex;
} else if( (cpIndex = Utils.ExtendedCharReplacements.IndexOf( c ) ) >= 0 ) {
buffer[index + i] = (byte)(cpIndex + 127);
} else {
buffer[index + i] = (byte)'?';
}
}
for( int i = value.Length; i < 64; i++ ) {
buffer[index + i] = (byte)' ';
}
index += 64;
}
public void WriteUInt8( byte value ) {
buffer[index++] = value;
}
public void WriteInt16( short value ) {
buffer[index++] = (byte)(value >> 8);
buffer[index++] = (byte)(value );
}
public void WriteInt32( int value ) {
buffer[index++] = (byte)(value >> 24);
buffer[index++] = (byte)(value >> 16);
buffer[index++] = (byte)(value >> 8);
buffer[index++] = (byte)(value);
}
public void Send( bool disconnected ) {
int packetLength = index;
index = 0;
if( !disconnected )
Stream.Write( buffer, 0, packetLength );
}
}
}

View File

@ -12,6 +12,7 @@ namespace ClassicalSharp.Singleplayer {
public SinglePlayerServer( Game window ) {
game = window;
physics = new Physics( game );
ServerSupportsFullCP437 = true;
}
public override bool IsSinglePlayer {