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 ) {
char code = 'F';
char code = 'f';
for( int i = 0; i < value.Length; i++ ) {
int nextAnd = value.IndexOf( '&', i );
int partLength = nextAnd == -1 ? value.Length - i : nextAnd - i;
@ -199,8 +200,8 @@ namespace ClassicalSharp {
if( nextAnd >= 0 && nextAnd + 1 < value.Length ) {
if( !ValidColour( value[nextAnd + 1] ) ) {
code = 'F';
i--; // include the character that isn't a colour code.
code = 'f';
i--; // include character that isn't a valid colour code.
} else {
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;
}
/// <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: " );
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, ' ' );
}
@ -163,9 +163,9 @@ namespace ClassicalSharp {
void UpKey( bool controlDown ) {
if( controlDown ) {
int pos = caretPos == -1 ? chatInputText.Length : caretPos;
if( pos < 64 ) return;
if( pos < LineLength ) return;
caretPos = pos - 64;
caretPos = pos - LineLength;
CalculateCaretData();
return;
}
@ -185,8 +185,8 @@ namespace ClassicalSharp {
void DownKey( bool controlDown ) {
if( controlDown ) {
if( caretPos == -1 || caretPos >= (lines - 1) * 64 ) return;
caretPos += 64;
if( caretPos == -1 || caretPos >= (lines - 1) * LineLength ) return;
caretPos += LineLength;
CalculateCaretData();
return;
}
@ -290,7 +290,7 @@ namespace ClassicalSharp {
CalculateCaretData(); return;
}
}
offset += partLens[y];
offset += line.Length;
}
caretPos = -1;
CalculateCaretData();

View File

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

View File

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

View File

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

View File

@ -37,9 +37,20 @@ namespace ClassicalSharp.Singleplayer {
GenMap( 128, 64, 128, seed, new NotchyGenerator() );
}
char lastCol = '\0';
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( '%', '&' );
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 );
}

View File

@ -68,9 +68,8 @@ namespace ClassicalSharp {
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] );
}
}
int WrapLine( int index, int lineSize ) {