diff --git a/ClassicalSharp/2D/Screens/BlockSelectScreen.cs b/ClassicalSharp/2D/Screens/BlockSelectScreen.cs
index 4f748071e..6780c8753 100644
--- a/ClassicalSharp/2D/Screens/BlockSelectScreen.cs
+++ b/ClassicalSharp/2D/Screens/BlockSelectScreen.cs
@@ -130,7 +130,7 @@ namespace ClassicalSharp {
Block block = blocksTable[selectedIndex].BlockId;
UpdateBlockInfoString( block );
- string value = buffer.UpdateCachedString();
+ string value = buffer.GetString();
Size size = Utils2D.MeasureSize( value, font, true );
int x = startX + ( blockSize * blocksPerRow ) / 2 - size.Width / 2;
diff --git a/ClassicalSharp/2D/Screens/FpsScreen.cs b/ClassicalSharp/2D/Screens/FpsScreen.cs
index d5de28130..2302255ef 100644
--- a/ClassicalSharp/2D/Screens/FpsScreen.cs
+++ b/ClassicalSharp/2D/Screens/FpsScreen.cs
@@ -38,7 +38,7 @@ namespace ClassicalSharp {
.Append( ref ptr2, ", vertices: " ).AppendNum( ref ptr2, game.Vertices );
}
- string textString = text.UpdateCachedString();
+ string textString = text.GetString();
fpsTextWidget.SetText( textString );
maxDelta = 0;
accumulator = 0;
diff --git a/ClassicalSharp/2D/Widgets/TextInputWidget.cs b/ClassicalSharp/2D/Widgets/TextInputWidget.cs
index 498de49b2..08c6e7753 100644
--- a/ClassicalSharp/2D/Widgets/TextInputWidget.cs
+++ b/ClassicalSharp/2D/Widgets/TextInputWidget.cs
@@ -40,7 +40,7 @@ namespace ClassicalSharp {
X = 10;
DrawTextArgs caretArgs = new DrawTextArgs( graphicsApi, "_", Color.White, false );
chatCaretTexture = Utils2D.MakeTextTexture( boldFont, 0, 0, ref caretArgs );
- string value = chatInputText.UpdateCachedString();
+ string value = chatInputText.GetString();
if( chatInputText.Empty ) {
caretPos = -1;
@@ -50,27 +50,32 @@ namespace ClassicalSharp {
if( caretPos == -1 ) {
chatCaretTexture.X1 = 10 + size.Width;
size.Width += chatCaretTexture.Width;
+ DrawString( size, value, true );
} else {
string subString = chatInputText.GetSubstring( caretPos );
Size trimmedSize = Utils2D.MeasureSize( subString, font, false );
- chatInputText.RestoreLength();
chatCaretTexture.X1 = 10 + trimmedSize.Width;
Size charSize = Utils2D.MeasureSize( new String( value[caretPos], 1 ), font, false );
chatCaretTexture.Width = charSize.Width;
+ DrawString( size, value, false );
}
+ }
+
+ void DrawString( Size size, string value, bool skipCheck ) {
size.Height = Math.Max( size.Height, chatCaretTexture.Height );
-
int y = game.Height - ChatInputYOffset - size.Height / 2;
+
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height );
DrawTextArgs args = new DrawTextArgs( graphicsApi, value, Color.White, false );
- args.SkipPartsCheck = true;
+ args.SkipPartsCheck = skipCheck;
Utils2D.DrawText( g, font, ref args, 0, 0 );
}
chatInputTexture = Utils2D.Make2DTexture( graphicsApi, bmp, size, 10, y );
}
+
chatCaretTexture.Y1 = chatInputTexture.Y1;
Y = y;
Width = size.Width;
diff --git a/ClassicalSharp/Network/NetworkProcessor.cs b/ClassicalSharp/Network/NetworkProcessor.cs
index ad1dda4d0..4c6fbef12 100644
--- a/ClassicalSharp/Network/NetworkProcessor.cs
+++ b/ClassicalSharp/Network/NetworkProcessor.cs
@@ -341,7 +341,7 @@ namespace ClassicalSharp {
sentWomId = true;
}
gzipStream = null;
- GC.Collect();
+ GC.Collect( 0 );
} break;
case PacketId.SetBlock:
diff --git a/ClassicalSharp/Utils/StringBuffer.cs b/ClassicalSharp/Utils/StringBuffer.cs
index 13b3076bd..fee39b6ef 100644
--- a/ClassicalSharp/Utils/StringBuffer.cs
+++ b/ClassicalSharp/Utils/StringBuffer.cs
@@ -3,34 +3,11 @@ using System.Reflection;
namespace ClassicalSharp {
- // Class used to minimise memory allocations of strings.
- // Really, only useful for FpsScreen and TextInputWidget as they allocate lots of very small strings.
- // Seriously, you should *not* use this anywhere else, as Empty and Length are O(N).
internal sealed unsafe class StringBuffer {
internal string value;
internal int capacity;
- static readonly FieldInfo arrayField, lengthField;
- static bool supportsLengthSetting;
-
- static StringBuffer() {
- if( OpenTK.Configuration.RunningOnMono )
- return;
-
- arrayField = typeof( String ).GetField( "m_arrayLength", BindingFlags.NonPublic | BindingFlags.Instance );
- lengthField = typeof( String ).GetField( "m_stringLength", BindingFlags.NonPublic | BindingFlags.Instance );
-
- // Make sure we are running on a framework that has both methods -
- // otherwise we play it safe and just use TrimEnd().
- if( arrayField != null && lengthField != null ) {
- supportsLengthSetting = true;
- } else {
- arrayField = null;
- lengthField = null;
- }
- }
-
public StringBuffer( int capacity ) {
this.capacity = capacity;
value = new String( '\0', capacity );
@@ -140,11 +117,8 @@ namespace ClassicalSharp {
}
}
- /// Hack that modifies the underlying string's length to avoid memory allocations.
- /// The underlying string - ***do not*** store this because it is mutable!
- /// You should only use this string for temporary measuring and drawing.
- public string UpdateCachedString() {
- return supportsLengthSetting ? SetLength( Length ) : value.TrimEnd( trimEnd );
+ public string GetString() {
+ return value.TrimEnd( trimEnd );
}
static char[] trimEnd = { '\0' };
@@ -153,18 +127,7 @@ namespace ClassicalSharp {
}
public string GetSubstring( int length ) {
- return supportsLengthSetting ? SetLength( length ) : GetCopy( length );
- }
-
- public void RestoreLength() {
- if( supportsLengthSetting )
- SetLength( Length );
- }
-
- string SetLength( int len ) {
- arrayField.SetValue( value, len + 1 );
- lengthField.SetValue( value, len );
- return value;
+ return GetCopy( length );
}
string GetCopy( int len ) {