Text input now properly wraps colour codes across multiple lines. (Thanks xnotx123)

This commit is contained in:
UnknownShadow200 2016-03-24 13:11:26 +11:00
parent d70851a1b9
commit 7af045f9a9
7 changed files with 95 additions and 44 deletions

View File

@ -184,8 +184,9 @@ namespace ClassicalSharp {
} }
} }
/// <summary> Splits the input string by recognised colour codes. (e.g &amp;f) </summary>
protected void SplitText( string value ) { protected void SplitText( string value ) {
char code = 'F'; char code = 'f';
for( int i = 0; i < value.Length; i++ ) { for( int i = 0; i < value.Length; i++ ) {
int nextAnd = value.IndexOf( '&', i ); int nextAnd = value.IndexOf( '&', i );
int partLength = nextAnd == -1 ? value.Length - i : nextAnd - i; int partLength = nextAnd == -1 ? value.Length - i : nextAnd - i;
@ -199,8 +200,8 @@ namespace ClassicalSharp {
if( nextAnd >= 0 && nextAnd + 1 < value.Length ) { if( nextAnd >= 0 && nextAnd + 1 < value.Length ) {
if( !ValidColour( value[nextAnd + 1] ) ) { if( !ValidColour( value[nextAnd + 1] ) ) {
code = 'F'; code = 'f';
i--; // include the character that isn't a colour code. i--; // include character that isn't a valid colour code.
} else { } else {
code = value[nextAnd + 1]; code = value[nextAnd + 1];
} }
@ -208,8 +209,27 @@ namespace ClassicalSharp {
} }
} }
internal bool ValidColour( char c ) { /// <summary> Returns whenever the given character is a valid colour code. </summary>
public bool ValidColour( char c ) {
return (int)c < 256 && Colours[c].A > 0; return (int)c < 256 && Colours[c].A > 0;
} }
/// <summary> Returns the last valid colour code in the given input,
/// or \0 if no valid colour code was found. </summary>
public char LastColour( string input, int start ) {
if( start >= input.Length )
start = input.Length - 1;
for( int i = start; i >= 0; i--) {
if( input[i] != '&' ) continue;
if( i < input.Length - 1 && ValidColour( input[i + 1] ) )
return input[i + 1];
}
return '\0';
}
public static bool IsWhiteColour( char c ) {
return c == '\0' || c == 'f' || c == 'F';
}
} }
} }

View File

@ -81,7 +81,7 @@ namespace ClassicalSharp {
buffer.Append( ref index, " matching names: " ); buffer.Append( ref index, " matching names: " );
foreach( string match in matches ) { foreach( string match in matches ) {
if( (match.Length + 1 + buffer.Length) > 64 ) break; if( (match.Length + 1 + buffer.Length) > LineLength ) break;
buffer.Append( ref index, match ); buffer.Append( ref index, match );
buffer.Append( ref index, ' ' ); buffer.Append( ref index, ' ' );
} }
@ -163,9 +163,9 @@ namespace ClassicalSharp {
void UpKey( bool controlDown ) { void UpKey( bool controlDown ) {
if( controlDown ) { if( controlDown ) {
int pos = caretPos == -1 ? chatInputText.Length : caretPos; int pos = caretPos == -1 ? chatInputText.Length : caretPos;
if( pos < 64 ) return; if( pos < LineLength ) return;
caretPos = pos - 64; caretPos = pos - LineLength;
CalculateCaretData(); CalculateCaretData();
return; return;
} }
@ -185,8 +185,8 @@ namespace ClassicalSharp {
void DownKey( bool controlDown ) { void DownKey( bool controlDown ) {
if( controlDown ) { if( controlDown ) {
if( caretPos == -1 || caretPos >= (lines - 1) * 64 ) return; if( caretPos == -1 || caretPos >= (lines - 1) * LineLength ) return;
caretPos += 64; caretPos += LineLength;
CalculateCaretData(); CalculateCaretData();
return; return;
} }
@ -290,7 +290,7 @@ namespace ClassicalSharp {
CalculateCaretData(); return; CalculateCaretData(); return;
} }
} }
offset += partLens[y]; offset += line.Length;
} }
caretPos = -1; caretPos = -1;
CalculateCaretData(); CalculateCaretData();

View File

@ -42,7 +42,7 @@ namespace ClassicalSharp {
graphicsApi.Texturing = false; graphicsApi.Texturing = false;
int y = Y, x = X; int y = Y, x = X;
for( int i = 0; i < sizes.Length; i++ ) { for( int i = 0; i < sizes.Length; i++ ) {
bool caretAtEnd = caretTex.Y1 == y && (indexX == 64 || caretPos == -1); bool caretAtEnd = caretTex.Y1 == y && (indexX == LineLength || caretPos == -1);
int offset = caretAtEnd ? defaultWidth : 0; int offset = caretAtEnd ? defaultWidth : 0;
graphicsApi.Draw2DQuad( x + 5, y, sizes[i].Width + offset, sizes[i].Height, backColour ); graphicsApi.Draw2DQuad( x + 5, y, sizes[i].Width + offset, sizes[i].Height, backColour );
y += sizes[i].Height; y += sizes[i].Height;
@ -64,9 +64,11 @@ namespace ClassicalSharp {
int indexX, indexY; int indexX, indexY;
bool shownWarning; bool shownWarning;
int LineLength { get { return game.Network.ServerSupportsPartialMessages ? 64 : 62; } }
public override void Init() { public override void Init() {
X = 5; X = 5;
chatInputText.WordWrap( game.Drawer2D, ref parts, ref partLens, 64 ); chatInputText.WordWrap( game.Drawer2D, ref parts, ref partLens, LineLength );
maxWidth = 0; maxWidth = 0;
DrawTextArgs args = new DrawTextArgs( null, font, true ); DrawTextArgs args = new DrawTextArgs( null, font, true );
@ -77,10 +79,10 @@ namespace ClassicalSharp {
} }
bool supports = game.Network.ServerSupportsPartialMessages; bool supports = game.Network.ServerSupportsPartialMessages;
if( chatInputText.Length > 64 && !shownWarning && !supports ) { if( chatInputText.Length > LineLength && !shownWarning && !supports ) {
game.Chat.Add( "&eNote: Each line will be sent as a separate packet.", MessageType.ClientStatus6 ); game.Chat.Add( "&eNote: Each line will be sent as a separate packet.", MessageType.ClientStatus6 );
shownWarning = true; shownWarning = true;
} else if( chatInputText.Length <= 64 && shownWarning ) { } else if( chatInputText.Length <= LineLength && shownWarning ) {
game.Chat.Add( null, MessageType.ClientStatus6 ); game.Chat.Add( null, MessageType.ClientStatus6 );
shownWarning = false; shownWarning = false;
} }
@ -96,7 +98,7 @@ namespace ClassicalSharp {
chatInputText.MakeCoords( caretPos, partLens, out indexX, out indexY ); chatInputText.MakeCoords( caretPos, partLens, out indexX, out indexY );
DrawTextArgs args = new DrawTextArgs( null, font, true ); DrawTextArgs args = new DrawTextArgs( null, font, true );
if( indexX == 64 ) { if( indexX == LineLength ) {
caretTex.X1 = 10 + sizes[indexY].Width; caretTex.X1 = 10 + sizes[indexY].Width;
caretCol = FastColour.Yellow; caretCol = FastColour.Yellow;
} else { } else {
@ -111,7 +113,7 @@ namespace ClassicalSharp {
caretCol = FastColour.Scale( FastColour.White, 0.8f ); caretCol = FastColour.Scale( FastColour.White, 0.8f );
} }
caretTex.Y1 = sizes[0].Height * indexY + Y; caretTex.Y1 = sizes[0].Height * indexY + Y;
CalculateCaretCol(); CalcCaretColour();
} }
void DrawString() { void DrawString() {
@ -130,6 +132,9 @@ namespace ClassicalSharp {
for( int i = 0; i < parts.Length; i++ ) { for( int i = 0; i < parts.Length; i++ ) {
if( parts[i] == null ) break; if( parts[i] == null ) break;
args.Text = parts[i]; args.Text = parts[i];
char lastCol = GetLastColour( 0, i );
if( !IDrawer2D.IsWhiteColour( lastCol ) )
args.Text = "&" + lastCol + args.Text;
drawer.DrawChatText( ref args, 0, realHeight ); drawer.DrawChatText( ref args, 0, realHeight );
realHeight += sizes[i].Height; realHeight += sizes[i].Height;
@ -143,20 +148,23 @@ namespace ClassicalSharp {
Width = size.Width; Width = size.Width;
} }
void CalculateCaretCol() { void CalcCaretColour() {
IDrawer2D drawer = game.Drawer2D;
char code = GetLastColour( indexX, indexY );
if( code != '\0' )
caretCol = drawer.Colours[code];
}
char GetLastColour( int indexX, int indexY ) {
int x = indexX; int x = indexX;
IDrawer2D drawer = game.Drawer2D; IDrawer2D drawer = game.Drawer2D;
for( int y = indexY; y >= 0; y-- ) { for( int y = indexY; y >= 0; y-- ) {
string part = parts[y]; string part = parts[y];
if( x == partLens[y] ) x = partLens[y] - 1; char code = drawer.LastColour( part, x );
int start = part.LastIndexOf( '&', x, x + 1 ); if( code != '\0' ) return code;
bool validIndex = start >= 0 && start < partLens[y] - 1; if( y > 0 ) x = parts[y - 1].Length;
if( validIndex && drawer.ValidColour( part[start + 1] ) ) {
caretCol = drawer.Colours[part[start + 1]]; return;
}
if( y > 0 ) x = partLens[y - 1] - 1;
} }
return '\0';
} }
public override void Dispose() { public override void Dispose() {
@ -197,26 +205,40 @@ namespace ClassicalSharp {
string allText = chatInputText.GetString(); string allText = chatInputText.GetString();
game.Chat.InputLog.Add( allText ); game.Chat.InputLog.Add( allText );
if( game.Network.ServerSupportsPartialMessages ) { if( game.Network.ServerSupportsPartialMessages )
SendWithPartial( allText );
else
SendNormal();
}
void SendWithPartial( string allText ) {
// don't automatically word wrap the message. // don't automatically word wrap the message.
while( allText.Length > 64 ) { while( allText.Length > 64 ) {
game.Chat.Send( allText.Substring( 0, 64 ), true ); game.Chat.Send( allText.Substring( 0, 64 ), true );
allText = allText.Substring( 64 ); allText = allText.Substring( 64 );
} }
game.Chat.Send( allText, false ); game.Chat.Send( allText, false );
return;
} }
void SendNormal() {
int packetsCount = 0; int packetsCount = 0;
for( int i = 0; i < parts.Length; i++ ) { for( int i = 0; i < parts.Length; i++ ) {
if( parts[i] == null ) break; if( parts[i] == null ) break;
packetsCount++; packetsCount++;
} }
// split up into both partial and final packet. // split up into both partial and final packet.
for( int i = 0; i < packetsCount - 1; i++ ) { for( int i = 0; i < packetsCount - 1; i++ )
game.Chat.Send( parts[i], true ); SendNormalText( i, true );
SendNormalText( packetsCount - 1, false );
} }
game.Chat.Send( parts[packetsCount - 1], false );
void SendNormalText( int i, bool partial ) {
string text = parts[i];
char lastCol = GetLastColour( 0, i );
if( !IDrawer2D.IsWhiteColour( lastCol ) )
text = "&" + lastCol + text;
game.Chat.Send( text, partial );
} }
public void Clear() { public void Clear() {

View File

@ -4,7 +4,7 @@
<ProjectGuid>{BEB1C785-5CAD-48FF-A886-876BF0A318D4}</ProjectGuid> <ProjectGuid>{BEB1C785-5CAD-48FF-A886-876BF0A318D4}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Exe</OutputType> <OutputType>WinExe</OutputType>
<RootNamespace>ClassicalSharp</RootNamespace> <RootNamespace>ClassicalSharp</RootNamespace>
<AssemblyName>ClassicalSharp</AssemblyName> <AssemblyName>ClassicalSharp</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion> <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>

View File

@ -137,7 +137,6 @@ namespace ClassicalSharp {
lastOpcode = (PacketId)opcode; lastOpcode = (PacketId)opcode;
Action handler = handlers[opcode]; Action handler = handlers[opcode];
lastPacket = DateTime.UtcNow; lastPacket = DateTime.UtcNow;
Console.WriteLine( "IN " + lastOpcode );
if( handler == null ) if( handler == null )
throw new NotImplementedException( "Unsupported packet:" + (PacketId)opcode ); throw new NotImplementedException( "Unsupported packet:" + (PacketId)opcode );

View File

@ -37,9 +37,20 @@ namespace ClassicalSharp.Singleplayer {
GenMap( 128, 64, 128, seed, new NotchyGenerator() ); GenMap( 128, 64, 128, seed, new NotchyGenerator() );
} }
char lastCol = '\0';
public override void SendChat( string text, bool partial ) { public override void SendChat( string text, bool partial ) {
if( String.IsNullOrEmpty( text ) ) return; if( !String.IsNullOrEmpty( text ) )
AddChat( text );
if( !partial ) lastCol = '\0';
}
void AddChat( string text ) {
text = text.TrimEnd().Replace( '%', '&' ); text = text.TrimEnd().Replace( '%', '&' );
if( !IDrawer2D.IsWhiteColour( lastCol ) )
text = "&" + lastCol + text;
char col = game.Drawer2D.LastColour( text, text.Length );
if( col != '\0' ) lastCol = col;
game.Chat.Add( text, MessageType.Normal ); game.Chat.Add( text, MessageType.Normal );
} }

View File

@ -68,10 +68,9 @@ namespace ClassicalSharp {
value[i] = '&'; value[i] = '&';
} }
for( int i = 0; i < Math.Max( 1, linesCount ); i++ ) { for( int i = 0; i < Math.Max( 1, linesCount ); i++ )
lines[i] = new String( value, i * lineSize, lineLens[i] ); lines[i] = new String( value, i * lineSize, lineLens[i] );
} }
}
int WrapLine( int index, int lineSize ) { int WrapLine( int index, int lineSize ) {
int lineEnd = index + (lineSize - 1); int lineEnd = index + (lineSize - 1);