mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-11 23:27:24 -04:00
213 lines
5.9 KiB
C#
213 lines
5.9 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using ClassicalSharp.Entities;
|
|
using OpenTK.Input;
|
|
#if ANDROID
|
|
using Android.Graphics;
|
|
#endif
|
|
|
|
namespace ClassicalSharp.Gui.Widgets {
|
|
public sealed class ChatInputWidget : InputWidget {
|
|
|
|
int typingLogPos;
|
|
string originalText;
|
|
bool shownWarning;
|
|
|
|
public ChatInputWidget( Game game, Font font ) : base( game, font ) {
|
|
typingLogPos = game.Chat.InputLog.Count; // Index of newest entry + 1.
|
|
}
|
|
|
|
public override int MaxLines { get { return game.ClassicMode ? 1 : 3; } }
|
|
public override int MaxCharsPerLine {
|
|
get {
|
|
bool allChars = game.ClassicMode || game.Server.SupportsPartialMessages;
|
|
return allChars ? 64 : 62;
|
|
}
|
|
}
|
|
|
|
public override void Init() {
|
|
base.Init();
|
|
bool supports = game.Server.SupportsPartialMessages;
|
|
|
|
if( buffer.Length > MaxCharsPerLine && !shownWarning && !supports ) {
|
|
game.Chat.Add( "&eNote: Each line will be sent as a separate packet.", MessageType.ClientStatus6 );
|
|
shownWarning = true;
|
|
} else if( buffer.Length <= MaxCharsPerLine && shownWarning ) {
|
|
game.Chat.Add( null, MessageType.ClientStatus6 );
|
|
shownWarning = false;
|
|
}
|
|
}
|
|
|
|
public override bool HandlesKeyDown( Key key ) {
|
|
if( game.HideGui ) return key < Key.F1 || key > Key.F35;
|
|
bool controlDown = ControlDown();
|
|
|
|
if( key == Key.Tab ) { TabKey(); return true; }
|
|
if( key == Key.Up ) { UpKey( controlDown ); return true; }
|
|
if( key == Key.Down ) { DownKey( controlDown ); return true; }
|
|
|
|
return base.HandlesKeyDown( key );
|
|
}
|
|
|
|
public override void EnterInput() {
|
|
SendChat();
|
|
originalText = null;
|
|
typingLogPos = game.Chat.InputLog.Count; // Index of newest entry + 1.
|
|
|
|
game.Chat.Add( null, MessageType.ClientStatus4 );
|
|
game.Chat.Add( null, MessageType.ClientStatus5 );
|
|
game.Chat.Add( null, MessageType.ClientStatus6 );
|
|
base.EnterInput();
|
|
}
|
|
|
|
|
|
void SendChat() {
|
|
if( buffer.Empty ) return;
|
|
// Don't want trailing spaces in output message
|
|
string allText = new String( buffer.value, 0, buffer.TextLength );
|
|
game.Chat.InputLog.Add( allText );
|
|
|
|
if( game.Server.SupportsPartialMessages ) {
|
|
SendWithPartial( allText );
|
|
} else {
|
|
SendNormal();
|
|
}
|
|
}
|
|
|
|
void SendWithPartial( string allText ) {
|
|
// don't automatically word wrap the message.
|
|
while( allText.Length > Utils.StringLength ) {
|
|
game.Chat.Send( allText.Substring( 0, Utils.StringLength ), true );
|
|
allText = allText.Substring( Utils.StringLength );
|
|
}
|
|
game.Chat.Send( allText, false );
|
|
}
|
|
|
|
void SendNormal() {
|
|
int packetsCount = 0;
|
|
for( int i = 0; i < lines.Length; i++ ) {
|
|
if( lines[i] == null ) break;
|
|
packetsCount++;
|
|
}
|
|
|
|
// split up into both partial and final packet.
|
|
for( int i = 0; i < packetsCount - 1; i++ )
|
|
SendNormalText( i, true );
|
|
SendNormalText( packetsCount - 1, false );
|
|
}
|
|
|
|
void SendNormalText( int i, bool partial ) {
|
|
string text = lines[i];
|
|
char lastCol = GetLastColour( 0, i );
|
|
if( !IDrawer2D.IsWhiteColour( lastCol ) )
|
|
text = "&" + lastCol + text;
|
|
game.Chat.Send( text, partial );
|
|
}
|
|
|
|
|
|
#region Input handling
|
|
|
|
void UpKey( bool controlDown ) {
|
|
if( controlDown ) {
|
|
int pos = caret == -1 ? buffer.Length : caret;
|
|
if( pos < MaxCharsPerLine ) return;
|
|
|
|
caret = pos - MaxCharsPerLine;
|
|
UpdateCaret();
|
|
return;
|
|
}
|
|
|
|
if( typingLogPos == game.Chat.InputLog.Count )
|
|
originalText = buffer.ToString();
|
|
if( game.Chat.InputLog.Count > 0 ) {
|
|
typingLogPos--;
|
|
if( typingLogPos < 0 ) typingLogPos = 0;
|
|
|
|
buffer.Clear();
|
|
buffer.Append( 0, game.Chat.InputLog[typingLogPos] );
|
|
caret = -1;
|
|
Recreate();
|
|
}
|
|
}
|
|
|
|
void DownKey( bool controlDown ) {
|
|
if( controlDown ) {
|
|
if( caret == -1 || caret >= (lines.Length - 1) * MaxCharsPerLine ) return;
|
|
caret += MaxCharsPerLine;
|
|
UpdateCaret();
|
|
return;
|
|
}
|
|
|
|
if( game.Chat.InputLog.Count > 0 ) {
|
|
typingLogPos++;
|
|
buffer.Clear();
|
|
if( typingLogPos >= game.Chat.InputLog.Count ) {
|
|
typingLogPos = game.Chat.InputLog.Count;
|
|
if( originalText != null )
|
|
buffer.Append( 0, originalText );
|
|
} else {
|
|
buffer.Append( 0, game.Chat.InputLog[typingLogPos] );
|
|
}
|
|
caret = -1;
|
|
Recreate();
|
|
}
|
|
}
|
|
|
|
void TabKey() {
|
|
int pos = caret == -1 ? buffer.Length - 1 : caret;
|
|
int start = pos;
|
|
char[] value = buffer.value;
|
|
|
|
while( start >= 0 && IsNameChar( value[start] ) )
|
|
start--;
|
|
start++;
|
|
if( pos < 0 || start > pos ) return;
|
|
|
|
string part = new String( value, start, pos + 1 - start );
|
|
List<string> matches = new List<string>();
|
|
game.Chat.Add( null, MessageType.ClientStatus5 );
|
|
|
|
TabListEntry[] entries = game.TabList.Entries;
|
|
for( int i = 0; i < EntityList.MaxCount; i++ ) {
|
|
if( entries[i] == null ) continue;
|
|
|
|
string rawName = entries[i].PlayerName;
|
|
string name = Utils.StripColours( rawName );
|
|
if( name.StartsWith( part, StringComparison.OrdinalIgnoreCase ) )
|
|
matches.Add( name );
|
|
}
|
|
|
|
if( matches.Count == 1 ) {
|
|
if( caret == -1 ) pos++;
|
|
int len = pos - start;
|
|
for( int i = 0; i < len; i++ )
|
|
buffer.DeleteAt( start );
|
|
if( caret != -1 ) caret -= len;
|
|
Append( matches[0] );
|
|
} else if( matches.Count > 1 ) {
|
|
StringBuffer sb = new StringBuffer( Utils.StringLength );
|
|
int index = 0;
|
|
sb.Append( ref index, "&e" );
|
|
sb.AppendNum( ref index, matches.Count );
|
|
sb.Append( ref index, " matching names: " );
|
|
|
|
for( int i = 0; i < matches.Count; i++) {
|
|
string match = matches[i];
|
|
if( (sb.Length + match.Length + 1) > sb.Capacity ) break;
|
|
sb.Append( ref index, match );
|
|
sb.Append( ref index, ' ' );
|
|
}
|
|
game.Chat.Add( sb.ToString(), MessageType.ClientStatus5 );
|
|
}
|
|
}
|
|
|
|
bool IsNameChar( char c ) {
|
|
return c == '_' || c == '.' || (c >= '0' && c <= '9')
|
|
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |