Add hotkey gui, workaround MCDzienny servers adding a + for classicube.net accounts.

This commit is contained in:
UnknownShadow200 2015-10-26 10:46:48 +11:00
parent e83957c685
commit a9406906cb
24 changed files with 526 additions and 143 deletions

View file

@ -0,0 +1,48 @@
using System;
using System.Drawing;
using OpenTK.Input;
namespace ClassicalSharp {
public abstract class ClickableScreen : Screen {
public ClickableScreen( Game game ) : base( game ) {
}
protected bool HandleMouseClick( Widget[] widgets, int mouseX, int mouseY, MouseButton button ) {
if( button != MouseButton.Left ) return false;
// iterate backwards (because last elements rendered are shown over others)
for( int i = widgets.Length - 1; i >= 0; i-- ) {
Widget widget = widgets[i];
if( widget != null && widget.Bounds.Contains( mouseX, mouseY ) ) {
if( widget.OnClick != null )
widget.OnClick( game, widget );
return true;
}
}
return false;
}
protected bool HandleMouseMove( Widget[] widgets, int mouseX, int mouseY ) {
for( int i = 0; i < widgets.Length; i++ ) {
if( widgets[i] == null ) continue;
widgets[i].Active = false;
}
for( int i = widgets.Length - 1; i >= 0; i-- ) {
Widget widget = widgets[i];
if( widget != null && widget.Bounds.Contains( mouseX, mouseY ) ) {
widget.Active = true;
WidgetSelected( widget );
return true;
}
}
WidgetSelected( null );
return false;
}
protected virtual void WidgetSelected( Widget widget ) {
}
}
}

View file

@ -4,7 +4,7 @@ using OpenTK.Input;
namespace ClassicalSharp {
public abstract class FilesScreen : Screen {
public abstract class FilesScreen : ClickableScreen {
public FilesScreen( Game game ) : base( game ) {
}
@ -55,12 +55,12 @@ namespace ClassicalSharp {
Anchor.Centre, Anchor.Centre, textFont, TextButtonClick );
}
ButtonWidget Make( int x, int y, string text, Action<Game, ButtonWidget> onClick ) {
ButtonWidget Make( int x, int y, string text, Action<Game, Widget> onClick ) {
return ButtonWidget.Create( game, x, y, 40, 40, text,
Anchor.Centre, Anchor.Centre, arrowFont, onClick );
}
protected abstract void TextButtonClick( Game game, ButtonWidget widget );
protected abstract void TextButtonClick( Game game, Widget widget );
protected void PageClick( bool forward ) {
currentIndex += forward ? 5 : -5;
@ -88,29 +88,11 @@ namespace ClassicalSharp {
}
public override bool HandlesMouseMove( int mouseX, int mouseY ) {
for( int i = 0; i < buttons.Length; i++ )
buttons[i].Active = false;
for( int i = 0; i < buttons.Length; i++ ) {
ButtonWidget widget = buttons[i];
if( widget.Bounds.Contains( mouseX, mouseY ) ) {
widget.Active = true;
return true;
}
}
return false;
return HandleMouseMove( buttons, mouseX, mouseY );
}
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
if( button != MouseButton.Left ) return false;
for( int i = 0; i < buttons.Length; i++ ) {
ButtonWidget widget = buttons[i];
if( widget.Bounds.Contains( mouseX, mouseY ) ) {
widget.OnClick( game, widget );
return true;
}
}
return false;
return HandleMouseClick( buttons, mouseX, mouseY, button );
}
public override bool HandlesAllInput {

View file

@ -0,0 +1,310 @@
using System;
using System.Drawing;
using ClassicalSharp.Hotkeys;
using OpenTK.Input;
namespace ClassicalSharp {
// TODO: Hotkey added event for CPE
// TODO: save hotkeys
public sealed class HotkeyScreen : MenuScreen {
HotkeyList hotkeys;
public HotkeyScreen( Game game ) : base( game ) {
hotkeys = game.InputHandler.Hotkeys;
}
Font hintFont, arrowFont, textFont;
public override void Render( double delta ) {
RenderMenuBounds();
graphicsApi.Texturing = true;
RenderMenuButtons( delta );
if( currentAction != null ) {
currentAction.Render( delta );
currentMoreInputLabel.Render( delta );
}
graphicsApi.Texturing = false;
}
public override bool HandlesMouseMove( int mouseX, int mouseY ) {
return HandleMouseMove( buttons, mouseX, mouseY );
}
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
return HandleMouseClick( buttons, mouseX, mouseY, button );
}
bool supressNextPress;
public override bool HandlesKeyPress( char key ) {
if( supressNextPress ) {
supressNextPress = false;
return true;
}
return currentAction == null ? false :
currentAction.HandlesKeyPress( key );
}
public override bool HandlesKeyDown( Key key ) {
if( key == Key.Escape ) {
game.SetNewScreen( new NormalScreen( game ) );
return true;
} else if( focusWidget != null ) {
FocusKeyDown( key );
return true;
}
if( key == Key.Left ) {
PageClick( false );
return true;
} else if( key == Key.Right ) {
PageClick( true );
return true;
}
return currentAction == null ? false :
currentAction.HandlesKeyDown( key );
}
public override bool HandlesKeyUp( Key key ) {
return currentAction == null ? false :
currentAction.HandlesKeyUp( key );
}
public override void Init() {
game.Keyboard.KeyRepeat = true;
titleFont = new Font( "Arial", 16, FontStyle.Bold );
regularFont = new Font( "Arial", 16, FontStyle.Regular );
hintFont = new Font( "Arial", 14, FontStyle.Italic );
arrowFont = new Font( "Arial", 18, FontStyle.Bold );
textFont = new Font( "Arial", 14, FontStyle.Bold );
buttons = new [] {
MakeHotkey( 0, -160, 0 ),
MakeHotkey( 0, -120, 1 ),
MakeHotkey( 0, -80, 2 ),
MakeHotkey( 0, -40, 3 ),
MakeAddNew( 0, 0 ),
Make( -160, -80, "<", 40, 40, arrowFont, (g, w) => PageClick( false ) ),
Make( 160, -80, ">", 40, 40, arrowFont, (g, w) => PageClick( true ) ),
ButtonWidget.Create( game, 0, 5, 240, 35, "Back to menu", Anchor.Centre, Anchor.BottomOrRight,
titleFont, (g, w) => g.SetNewScreen( new PauseScreen( g ) ) ),
null, // current key
null, // current modifiers
null, // leave open current
null, // save current
null, // remove current
null,
};
}
public override void OnResize( int oldWidth, int oldHeight, int width, int height ) {
if( currentAction != null ) {
currentAction.OnResize( oldWidth, oldHeight, width, height );
currentMoreInputLabel.OnResize( oldWidth, oldHeight, width, height );
}
base.OnResize( oldWidth, oldHeight, width, height );
}
public override void Dispose() {
game.Keyboard.KeyRepeat = false;
DisposeEditingWidgets();
hintFont.Dispose();
arrowFont.Dispose();
textFont.Dispose();
base.Dispose();
}
ButtonWidget Make( int x, int y, string text, int width, int height,
Font font, Action<Game, Widget> onClick ) {
return ButtonWidget.Create( game, x, y, width, height, text,
Anchor.Centre, Anchor.Centre, font, onClick );
}
ButtonWidget MakeHotkey( int x, int y, int index ) {
string text = Get( index );
ButtonWidget button = ButtonWidget.Create(
game, x, y, 240, 30, text, Anchor.Centre, Anchor.Centre,
textFont, TextButtonClick );
if( text != "-----" )
button.Metadata = hotkeys.Hotkeys[index];
return button;
}
ButtonWidget MakeAddNew( int x, int y ) {
ButtonWidget button = ButtonWidget.Create(
game, x, y, 240, 30, "Add new", Anchor.Centre, Anchor.Centre,
textFont, TextButtonClick );
button.Metadata = default( Hotkey );
return button;
}
string Get( int index ) {
if( index >= hotkeys.Hotkeys.Count ) return "-----";
Hotkey hKey = hotkeys.Hotkeys[index];
return hKey.BaseKey + " | " + MakeFlagsString( hKey.Flags );
}
void Set( int index ) {
string text = Get( index );
ButtonWidget button = buttons[index];
button.SetText( text);
button.Metadata = null;
if( text != "-----" )
button.Metadata = hotkeys.Hotkeys[index];
}
string MakeFlagsString( byte flags ) {
if( flags == 0 ) return "None";
return ((flags & 1) == 0 ? " " : "Ctrl ") +
((flags & 2) == 0 ? " " : "Shift ") +
((flags & 4) == 0 ? " " : "Alt ");
}
int currentIndex;
void PageClick( bool forward ) {
currentIndex += forward ? 4 : -4;
if( currentIndex >= hotkeys.Hotkeys.Count ) currentIndex -= 4;
if( currentIndex < 0 ) currentIndex = 0;
LostFocus();
for( int i = 0; i < 4; i++ )
Set( currentIndex + i );
}
void TextButtonClick( Game game, Widget widget ) {
LostFocus();
ButtonWidget button = (ButtonWidget)widget;
if( button.Metadata != null ) {
curHotkey = (Hotkey)button.Metadata;
origHotkey = curHotkey;
// do stuff here
CreateEditingWidgets();
}
}
#region Modifying hotkeys
Hotkey curHotkey, origHotkey;
MenuInputWidget currentAction;
TextWidget currentMoreInputLabel;
ButtonWidget focusWidget;
void CreateEditingWidgets() {
DisposeEditingWidgets();
buttons[8] = Make( -140, 60, "Key: " + curHotkey.BaseKey,
250, 30, textFont, BaseKeyClick );
buttons[9] = Make( 140, 60, "Modifiers: " + MakeFlagsString( curHotkey.Flags ),
250, 30, textFont, ModifiersClick );
buttons[10] = Make( -10, 120, curHotkey.MoreInput ? "yes" : "no",
50, 25, textFont, LeaveOpenClick );
buttons[11] = Make( -100, 160, "Save changes",
160, 30, textFont, SaveChangesClick );
buttons[12] = Make( 100, 160, "Remove hotkey",
160, 30, textFont, RemoveHotkeyClick );
currentAction = MenuInputWidget.Create(
game, 0, 90, 600, 25, "", Anchor.Centre, Anchor.Centre,
regularFont, titleFont, hintFont, new StringValidator( 64 ) );
currentMoreInputLabel = TextWidget.Create(
game, -170, 120, "Leave open for further input:",
Anchor.Centre, Anchor.Centre, textFont );
if( curHotkey.Text == null ) curHotkey.Text = "";
currentAction.SetText( curHotkey.Text );
}
void DisposeEditingWidgets() {
if( currentAction != null ) {
currentAction.Dispose();
currentAction = null;
}
for( int i = 8; i < buttons.Length - 1; i++ ) {
if( buttons[i] != null ) {
buttons[i].Dispose();
buttons[i] = null;
}
}
focusWidget = null;
}
void LeaveOpenClick( Game game, Widget widget ) {
LostFocus();
curHotkey.MoreInput = !curHotkey.MoreInput;
buttons[10].SetText( curHotkey.MoreInput ? "yes" : "no" );
}
void SaveChangesClick( Game game, Widget widget ) {
if( origHotkey.BaseKey != Key.Unknown )
hotkeys.RemoveHotkey( origHotkey.BaseKey, origHotkey.Flags );
if( curHotkey.BaseKey != Key.Unknown )
hotkeys.AddHotkey( curHotkey.BaseKey, curHotkey.Flags,
currentAction.GetText(), curHotkey.MoreInput );
for( int i = 0; i < 4; i++ )
Set( currentIndex + i );
DisposeEditingWidgets();
}
void RemoveHotkeyClick( Game game, Widget widget ) {
if( origHotkey.BaseKey != Key.Unknown )
hotkeys.RemoveHotkey( origHotkey.BaseKey, origHotkey.Flags );
for( int i = 0; i < 4; i++ )
Set( currentIndex + i );
DisposeEditingWidgets();
}
void BaseKeyClick( Game game, Widget widget ) {
focusWidget = buttons[8];
focusWidget.SetText( "Key: press a key.." );
supressNextPress = true;
}
void ModifiersClick( Game game, Widget widget ) {
focusWidget = buttons[9];
focusWidget.SetText( "Modifiers: press a key.." );
supressNextPress = true;
}
void FocusKeyDown( Key key ) {
if( focusWidget == buttons[8] ) {
curHotkey.BaseKey = key;
buttons[8].SetText( "Key: " + curHotkey.BaseKey );
supressNextPress = true;
} else if( focusWidget == buttons[9] ) {
if( key == Key.ControlLeft || key == Key.ControlRight ) curHotkey.Flags |= 1;
else if( key == Key.ShiftLeft || key == Key.ShiftRight ) curHotkey.Flags |= 2;
else if( key == Key.AltLeft || key == Key.AltRight ) curHotkey.Flags |= 4;
else curHotkey.Flags = 0;
buttons[9].SetText( "Modifiers: " + MakeFlagsString( curHotkey.Flags ) );
supressNextPress = true;
}
focusWidget = null;
}
void LostFocus() {
if( focusWidget == null ) return;
if( focusWidget == buttons[8] ) {
buttons[8].SetText( "Key: " + curHotkey.BaseKey );
} else if( focusWidget == buttons[9] ) {
buttons[9].SetText( "Modifiers: " + MakeFlagsString( curHotkey.Flags ) );
}
focusWidget = null;
supressNextPress = false;
}
#endregion
}
}

View file

@ -71,7 +71,7 @@ namespace ClassicalSharp {
okayIndex = buttons.Length - 1;
}
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, ButtonWidget> onClick,
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, Widget> onClick,
Func<Game, string> getter, Action<Game, string> setter ) {
ButtonWidget widget = ButtonWidget.Create( game, x, y, 240, 35, text, Anchor.Centre, vDocking, titleFont, onClick );
widget.GetValue = getter;

View file

@ -53,10 +53,10 @@ namespace ClassicalSharp {
}
}
ButtonWidget widget;
void OnWidgetClick( Game game, ButtonWidget widget ) {
this.widget = widget;
int index = Array.IndexOf<ButtonWidget>( buttons, widget );
ButtonWidget curWidget;
void OnWidgetClick( Game game, Widget realWidget ) {
this.curWidget = (ButtonWidget)realWidget;
int index = Array.IndexOf<ButtonWidget>( buttons, curWidget );
statusWidget.Dispose();
string text = "Press new key binding for " + descriptions[index] + ":";
@ -66,8 +66,8 @@ namespace ClassicalSharp {
public override bool HandlesKeyDown( Key key ) {
if( key == Key.Escape ) {
game.SetNewScreen( new NormalScreen( game ) );
} else if( widget != null ) {
int index = Array.IndexOf<ButtonWidget>( buttons, widget );
} else if( curWidget != null ) {
int index = Array.IndexOf<ButtonWidget>( buttons, curWidget );
KeyBinding mapping = (KeyBinding)index;
KeyMap map = game.InputHandler.Keys;
Key oldKey = map[mapping];
@ -81,15 +81,15 @@ namespace ClassicalSharp {
statusWidget.SetText( String.Format( format, descriptions[index], oldKey, key ) );
string text = descriptions[index] + " : " + keyNames[(int)key];
widget.SetText( text );
curWidget.SetText( text );
map[mapping] = key;
}
widget = null;
curWidget = null;
}
return true;
}
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, ButtonWidget> onClick ) {
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, Widget> onClick ) {
return ButtonWidget.Create( game, x, y, 240, 35, text, Anchor.Centre, vDocking, keyFont, onClick );
}

View file

@ -27,13 +27,13 @@ namespace ClassicalSharp {
Make( 0, 5, "Back to menu", (g, w) => g.SetNewScreen( new PauseScreen( g ) ) );
}
ButtonWidget Make( int x, int y, string text, Action<Game, ButtonWidget> onClick ) {
ButtonWidget Make( int x, int y, string text, Action<Game, Widget> onClick ) {
return ButtonWidget.Create( game, x, y, 240, 35, text,
Anchor.Centre, Anchor.BottomOrRight, titleFont, onClick );
}
protected override void TextButtonClick( Game game, ButtonWidget widget ) {
string path = widget.Text;
protected override void TextButtonClick( Game game, Widget widget ) {
string path = ((ButtonWidget)widget).Text;
if( File.Exists( path ) )
LoadMap( path );
}

View file

@ -75,11 +75,12 @@ namespace ClassicalSharp {
}
ButtonWidget selectedWidget, targetWidget;
protected override void WidgetSelected( ButtonWidget widget ) {
if( selectedWidget == widget || widget == null ||
widget == buttons[buttons.Length - 2] ) return;
protected override void WidgetSelected( Widget widget ) {
ButtonWidget button = (ButtonWidget)widget;
if( selectedWidget == button || button == null ||
button == buttons[buttons.Length - 2] ) return;
selectedWidget = widget;
selectedWidget = button;
if( targetWidget != null ) return;
UpdateDescription( selectedWidget );
}
@ -93,18 +94,19 @@ namespace ClassicalSharp {
descWidget = TextWidget.Create( game, 0, 100, text, Anchor.Centre, Anchor.Centre, regularFont );
}
protected void OnWidgetClick( Game game, ButtonWidget widget ) {
protected void OnWidgetClick( Game game, Widget widget ) {
if( widget == buttons[okayIndex] ) {
ChangeSetting();
return;
}
ButtonWidget button = (ButtonWidget)widget;
int index = Array.IndexOf<ButtonWidget>( buttons, widget );
int index = Array.IndexOf<ButtonWidget>( buttons, button );
MenuInputValidator validator = validators[index];
if( validator is BooleanValidator ) {
string value = widget.GetValue( game );
widget.SetValue( game, value == "yes" ? "no" : "yes" );
UpdateDescription( widget );
string value = button.GetValue( game );
button.SetValue( game, value == "yes" ? "no" : "yes" );
UpdateDescription( button );
return;
}
@ -112,7 +114,7 @@ namespace ClassicalSharp {
inputWidget.Dispose();
targetWidget = selectedWidget;
inputWidget = MenuInputWidget.Create( game, 0, 150, 400, 25, widget.GetValue( game ),
inputWidget = MenuInputWidget.Create( game, 0, 150, 400, 25, button.GetValue( game ),
Anchor.Centre, Anchor.Centre, regularFont, titleFont,
hintFont, validator );
buttons[okayIndex] = ButtonWidget.Create( game, 240, 150, 30, 30, "OK",

View file

@ -4,7 +4,7 @@ using OpenTK.Input;
namespace ClassicalSharp {
public abstract class MenuScreen : Screen {
public abstract class MenuScreen : ClickableScreen {
public MenuScreen( Game game ) : base( game ) {
}
@ -44,34 +44,11 @@ namespace ClassicalSharp {
}
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
if( button != MouseButton.Left ) return false;
for( int i = 0; i < buttons.Length; i++ ) {
ButtonWidget widget = buttons[i];
if( widget != null && widget.Bounds.Contains( mouseX, mouseY ) ) {
if( widget.OnClick != null )
widget.OnClick( game, widget );
return true;
}
}
return false;
return HandleMouseClick( buttons, mouseX, mouseY, button );
}
public override bool HandlesMouseMove( int mouseX, int mouseY ) {
for( int i = 0; i < buttons.Length; i++ ) {
if( buttons[i] == null ) continue;
buttons[i].Active = false;
}
for( int i = 0; i < buttons.Length; i++ ) {
ButtonWidget widget = buttons[i];
if( widget != null && widget.Bounds.Contains( mouseX, mouseY ) ) {
widget.Active = true;
WidgetSelected( widget );
return true;
}
}
WidgetSelected( null );
return false;
return HandleMouseMove( buttons, mouseX, mouseY );
}
public override bool HandlesKeyPress( char key ) {
@ -85,8 +62,5 @@ namespace ClassicalSharp {
public override bool HandlesKeyUp( Key key ) {
return true;
}
protected virtual void WidgetSelected( ButtonWidget widget ) {
}
}
}

View file

@ -79,7 +79,7 @@ namespace ClassicalSharp {
okayIndex = buttons.Length - 1;
}
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, ButtonWidget> onClick,
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, Widget> onClick,
Func<Game, string> getter, Action<Game, string> setter ) {
ButtonWidget widget = ButtonWidget.Create( game, x, y, 240, 35, text, Anchor.Centre, vDocking, titleFont, onClick );
widget.GetValue = getter;

View file

@ -18,30 +18,23 @@ namespace ClassicalSharp {
public override void Init() {
titleFont = new Font( "Arial", 16, FontStyle.Bold );
if( game.Network.IsSinglePlayer ) {
buttons = new ButtonWidget[] {
Make( -140, -50, "Options", Anchor.Centre, (g, w) => g.SetNewScreen( new OptionsScreen( g ) ) ),
Make( -140, 0, "Environment settings", Anchor.Centre, (g, w) => g.SetNewScreen( new EnvSettingsScreen( g ) ) ),
Make( -140, 50, "Select texture pack", Anchor.Centre, (g, w) => g.SetNewScreen( new TexturePackScreen( g ) ) ),
Make( 140, -50, "Save level", Anchor.Centre, (g, w) => g.SetNewScreen( new SaveLevelScreen( g ) ) ),
Make( 140, 0, "Load level", Anchor.Centre, (g, w) => g.SetNewScreen( new LoadLevelScreen( g ) ) ),
// TODO: singleplayer Make( 0, 50, "Load/Save/Gen level", Docking.Centre, (g, w) => g.SetNewScreen( new SaveLevelScreen( g ) ) ),
Make( 0, 55, "Back to game", Anchor.BottomOrRight, (g, w) => g.SetNewScreen( new NormalScreen( g ) ) ),
Make( 0, 5, "Quit game", Anchor.BottomOrRight, (g, w) => g.Exit() ),
};
} else {
buttons = new ButtonWidget[] {
Make( 0, -100, "Options", Anchor.Centre, (g, w) => g.SetNewScreen( new OptionsScreen( g ) ) ),
Make( 0, -50, "Environment settings", Anchor.Centre, (g, w) => g.SetNewScreen( new EnvSettingsScreen( g ) ) ),
Make( 0, 0, "Select texture pack", Anchor.Centre, (g, w) => g.SetNewScreen( new TexturePackScreen( g ) ) ),
Make( 0, 50, "Save level", Anchor.Centre, (g, w) => g.SetNewScreen( new SaveLevelScreen( g ) ) ),
Make( 0, 55, "Back to game", Anchor.BottomOrRight, (g, w) => g.SetNewScreen( new NormalScreen( g ) ) ),
Make( 0, 5, "Quit game", Anchor.BottomOrRight, (g, w) => g.Exit() ),
};
}
buttons = new ButtonWidget[] {
Make( -140, -100, "Options", Anchor.Centre, (g, w) => g.SetNewScreen( new OptionsScreen( g ) ) ),
Make( -140, -50, "Environment settings", Anchor.Centre, (g, w) => g.SetNewScreen( new EnvSettingsScreen( g ) ) ),
Make( -140, 0, "Select texture pack", Anchor.Centre, (g, w) => g.SetNewScreen( new TexturePackScreen( g ) ) ),
Make( -140, 50, "Hotkeys", Anchor.Centre, (g, w) => g.SetNewScreen( new HotkeyScreen( g ) ) ),
Make( 140, -100, "Save level", Anchor.Centre, (g, w) => g.SetNewScreen( new SaveLevelScreen( g ) ) ),
!game.Network.IsSinglePlayer ? null :
Make( 140, -50, "Load level", Anchor.Centre, (g, w) => g.SetNewScreen( new LoadLevelScreen( g ) ) ),
// TODO: singleplayer Generate level screen
Make( 0, 55, "Back to game", Anchor.BottomOrRight, (g, w) => g.SetNewScreen( new NormalScreen( g ) ) ),
Make( 0, 5, "Quit game", Anchor.BottomOrRight, (g, w) => g.Exit() ),
};
}
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, ButtonWidget> onClick ) {
ButtonWidget Make( int x, int y, string text, Anchor vDocking, Action<Game, Widget> onClick ) {
return ButtonWidget.Create( game, x, y, 240, 35, text, Anchor.Centre, vDocking, titleFont, onClick );
}

View file

@ -77,7 +77,7 @@ namespace ClassicalSharp {
base.Dispose();
}
void OkButtonClick( Game game, ButtonWidget widget ) {
void OkButtonClick( Game game, Widget widget ) {
string text = inputWidget.GetText();
if( text.Length == 0 ) {
MakeDescWidget( "Please enter a filename" );

View file

@ -25,13 +25,13 @@ namespace ClassicalSharp {
Make( 0, 5, "Back to menu", (g, w) => g.SetNewScreen( new PauseScreen( g ) ) );
}
ButtonWidget Make( int x, int y, string text, Action<Game, ButtonWidget> onClick ) {
ButtonWidget Make( int x, int y, string text, Action<Game, Widget> onClick ) {
return ButtonWidget.Create( game, x, y, 240, 35, text,
Anchor.Centre, Anchor.BottomOrRight, titleFont, onClick );
}
protected override void TextButtonClick( Game game, ButtonWidget widget ) {
string path = widget.Text;
protected override void TextButtonClick( Game game, Widget widget ) {
string path = ((ButtonWidget)widget).Text;
if( File.Exists( path ) ) {
TexturePackExtractor extractor = new TexturePackExtractor();
extractor.Extract( path, game );

View file

@ -11,15 +11,13 @@ namespace ClassicalSharp {
}
public static ButtonWidget Create( Game game, int x, int y, int width, int height, string text, Anchor horizontal,
Anchor vertical, Font font, Action<Game, ButtonWidget> onClick ) {
Anchor vertical, Font font, Action<Game, Widget> onClick ) {
ButtonWidget widget = new ButtonWidget( game, font );
widget.Init();
widget.HorizontalAnchor = horizontal;
widget.VerticalAnchor = vertical;
widget.XOffset = x;
widget.YOffset = y;
widget.DesiredMaxWidth = width;
widget.DesiredMaxHeight = height;
widget.XOffset = x; widget.YOffset = y;
widget.DesiredMaxWidth = width; widget.DesiredMaxHeight = height;
widget.SetText( text );
widget.OnClick = onClick;
return widget;
@ -75,10 +73,8 @@ namespace ClassicalSharp {
Y = newY;
}
public Action<Game, ButtonWidget> OnClick;
public Func<Game, string> GetValue;
public Action<Game, string> SetValue;
public bool Active;
void MakeTexture( string text ) {
DrawTextArgs args = new DrawTextArgs( text, font, true );

View file

@ -126,4 +126,21 @@ namespace ClassicalSharp {
return s == "yes" || s == "no";
}
}
public sealed class StringValidator : MenuInputValidator {
int maxLen;
public StringValidator( int len ) {
Range = "&7(Enter text)";
maxLen = len;
}
public override bool IsValidChar( char c ) {
return !(c < ' ' || c == '&' || c > '~');
}
public override bool IsValidString( string s ) {
return s.Length <= maxLen;
}
}
}

View file

@ -11,6 +11,12 @@ namespace ClassicalSharp {
VerticalAnchor = Anchor.LeftOrTop;
}
/// <summary> Whether this widget is currently being moused over. </summary>
public bool Active;
/// <summary> Invoked when this widget is clicked on. Can be left null. </summary>
public Action<Game, Widget> OnClick;
/// <summary> Horizontal coordinate of top left corner in window space. </summary>
public int X;

View file

@ -82,9 +82,11 @@
<Compile Include="2D\Drawing\IDrawer2D.cs" />
<Compile Include="2D\Screens\BlockSelectScreen.cs" />
<Compile Include="2D\Screens\ChatScreen.cs" />
<Compile Include="2D\Screens\ClickableScreen.cs" />
<Compile Include="2D\Screens\ErrorScreen.cs" />
<Compile Include="2D\Screens\FilesScreen.cs" />
<Compile Include="2D\Screens\FpsScreen.cs" />
<Compile Include="2D\Screens\HotkeyScreen.cs" />
<Compile Include="2D\Screens\LoadingMapScreen.cs" />
<Compile Include="2D\Screens\Menu\EnvSettingsScreen.cs" />
<Compile Include="2D\Screens\Menu\KeyBindingsScreen.cs" />

View file

@ -17,6 +17,7 @@ namespace ClassicalSharp.Commands {
RegisterCommand( new HelpCommand() );
RegisterCommand( new InfoCommand() );
RegisterCommand( new RenderTypeCommand() );
RegisterCommand( new HotkeyCommand() );
}
public void RegisterCommand( Command command ) {

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using ClassicalSharp.Renderers;
using OpenTK.Input;
namespace ClassicalSharp.Commands {
@ -100,6 +101,46 @@ namespace ClassicalSharp.Commands {
}
}
public sealed class HotkeyCommand : Command {
public HotkeyCommand() {
Name = "Hotkey";
Help = new [] {
"&a/client hotkey [key] [modifiers] [more] [action]",
};
}
public override void Execute( CommandReader reader ) {
Key key;
byte modifiers;
bool more;
if( !reader.NextOf( out key, ParseKey ) ||
!reader.NextOf( out modifiers, Byte.TryParse ) ||
!reader.NextOf( out more, Boolean.TryParse ) ) {
game.Chat.Add( "NOPE!" );
return;
}
string action = reader.NextAll();
if( action != null ) {
game.InputHandler.Hotkeys
.AddHotkey( key, modifiers, action, more );
game.Chat.Add( "Added" );
}
}
bool ParseKey( string value, out Key key ) {
try {
key = (Key)Enum.Parse( typeof( Key ), value, true );
return true;
} catch {
key = Key.Unknown;
return false;
}
}
}
public sealed class RenderTypeCommand : Command {
public RenderTypeCommand() {

View file

@ -7,14 +7,7 @@ namespace ClassicalSharp.Hotkeys {
/// <summary> Maintains the list of hotkeys defined by the client and by SetTextHotkey packets. </summary>
public sealed class HotkeyList {
struct Hotkey {
public Key BaseKey;
public byte Flags; // ctrl 1, shift 2, alt 4
public string Text; // contents to copy directly into the input bar
public bool MoreInput; // whether the user is able to enter further input
}
List<Hotkey> hotkeys = new List<Hotkey>();
public List<Hotkey> Hotkeys = new List<Hotkey>();
/// <summary> Creates or updates an existing hotkey with the given baseKey and modifier flags. </summary>
public void AddHotkey( Key baseKey, byte flags, string text, bool more ) {
@ -26,10 +19,10 @@ namespace ClassicalSharp.Hotkeys {
/// <returns> Whether a hotkey with the given baseKey and modifier flags was found
/// and subsequently removed. </returns>
public bool RemoveHotkey( Key baseKey, byte flags ) {
for( int i = 0; i < hotkeys.Count; i++ ) {
Hotkey hKey = hotkeys[i];
for( int i = 0; i < Hotkeys.Count; i++ ) {
Hotkey hKey = Hotkeys[i];
if( hKey.BaseKey == baseKey && hKey.Flags == flags ) {
hotkeys.RemoveAt( i );
Hotkeys.RemoveAt( i );
return true;
}
}
@ -37,12 +30,12 @@ namespace ClassicalSharp.Hotkeys {
}
bool UpdateExistingHotkey( Key baseKey, byte flags, string text, bool more ) {
for( int i = 0; i < hotkeys.Count; i++ ) {
Hotkey hKey = hotkeys[i];
for( int i = 0; i < Hotkeys.Count; i++ ) {
Hotkey hKey = Hotkeys[i];
if( hKey.BaseKey == baseKey && hKey.Flags == flags ) {
hKey.Text = text;
hKey.MoreInput = more;
hotkeys[i] = hKey;
Hotkeys[i] = hKey;
return true;
}
}
@ -50,17 +43,18 @@ namespace ClassicalSharp.Hotkeys {
}
void AddNewHotkey( Key baseKey, byte flags, string text, bool more ) {
Hotkey hotkey;
Hotkey hotkey;
hotkey.BaseKey = baseKey;
hotkey.Flags = flags;
hotkey.Text = text;
hotkey.MoreInput = more;
hotkeys.Add( hotkey );
Hotkeys.Add( hotkey );
// sort so that hotkeys with largest modifiers are first
hotkeys.Sort( (a, b) => b.Flags.CompareTo( a.Flags ) );
Hotkeys.Sort( (a, b) => b.Flags.CompareTo( a.Flags ) );
}
/// <summary> Determines whether a hotkey is active based on the given key,
/// <summary> Determines whether a hotkey is active based on the given key,
/// and the currently active control, alt, and shift modifiers </summary>
public bool IsHotkey( Key key, KeyboardDevice keyboard,
out string text, out bool moreInput ) {
@ -69,7 +63,7 @@ namespace ClassicalSharp.Hotkeys {
if( keyboard[Key.ShiftLeft] || keyboard[Key.ShiftRight] ) flags |= 2;
if( keyboard[Key.AltLeft] || keyboard[Key.AltRight] ) flags |= 4;
foreach( Hotkey hKey in hotkeys ) {
foreach( Hotkey hKey in Hotkeys ) {
if( (hKey.Flags & flags) == hKey.Flags && hKey.BaseKey == key ) {
text = hKey.Text;
moreInput = hKey.MoreInput;
@ -81,5 +75,12 @@ namespace ClassicalSharp.Hotkeys {
moreInput = false;
return false;
}
}
public struct Hotkey {
public Key BaseKey;
public byte Flags; // ctrl 1, shift 2, alt 4
public string Text; // contents to copy directly into the input bar
public bool MoreInput; // whether the user is able to enter further input
}
}

View file

@ -140,18 +140,20 @@ namespace ClassicalSharp {
Console.WriteLine( "CPE Hotkey added: " + key + "," + keyMods + " : " + action );
if( action == "" ) {
game.InputHandler.Hotkeys.RemoveHotkey( key, keyMods );
} else if( action[action.Length - 1] == '\n' ) { // more input needed by user
} else if( action[action.Length - 1] == '\n' ) {
action = action.Substring( 0, action.Length - 1 );
game.InputHandler.Hotkeys.AddHotkey( key, keyMods, action, true );
} else {
game.InputHandler.Hotkeys.AddHotkey( key, keyMods, action, false );
} else { // more input needed by user
game.InputHandler.Hotkeys.AddHotkey( key, keyMods, action, true );
}
}
void HandleCpeExtAddPlayerName() {
short nameId = reader.ReadInt16();
string playerName = Utils.StripColours( reader.ReadAsciiString() );
playerName = Utils.RemoveEndPlus( playerName );
string listName = reader.ReadAsciiString();
listName = Utils.RemoveEndPlus( listName );
string groupName = reader.ReadAsciiString();
byte groupRank = reader.ReadUInt8();
@ -159,7 +161,6 @@ namespace ClassicalSharp {
CpeListInfo oldInfo = game.CpePlayersList[nameId];
CpeListInfo info = new CpeListInfo( (byte)nameId, playerName, listName, groupName, groupRank );
game.CpePlayersList[nameId] = info;
//Console.WriteLine( nameId + ": " + groupRank + " , " + groupName + " : " + listName );
if( oldInfo != null ) {
game.Events.RaiseCpeListInfoChanged( (byte)nameId );
@ -172,7 +173,9 @@ namespace ClassicalSharp {
void HandleCpeExtAddEntity() {
byte entityId = reader.ReadUInt8();
string displayName = reader.ReadAsciiString();
displayName = Utils.RemoveEndPlus( displayName );
string skinName = reader.ReadAsciiString();
skinName = Utils.RemoveEndPlus( skinName );
AddEntity( entityId, displayName, skinName, false );
}

View file

@ -99,7 +99,7 @@ namespace ClassicalSharp {
reader.ReadPendingData();
} catch( IOException ex ) {
ErrorHandler.LogError( "reading packets", ex );
game.Disconnect( "&eLost connection to the server", "IO error when reading packets" );
game.Disconnect( "&eLost connection to the server", "I/O error when reading packets" );
Dispose();
return;
}
@ -205,7 +205,7 @@ namespace ClassicalSharp {
stream.Write( outBuffer, 0, packetLength );
} catch( IOException ex ) {
ErrorHandler.LogError( "wrting packets", ex );
game.Disconnect( "&eLost connection to the server", "IO Error while writing packets" );
game.Disconnect( "&eLost connection to the server", "I/O Error while writing packets" );
Dispose();
}
}
@ -334,6 +334,7 @@ namespace ClassicalSharp {
void HandleAddEntity() {
byte entityId = reader.ReadUInt8();
string name = reader.ReadAsciiString();
name = Utils.RemoveEndPlus( name );
AddEntity( entityId, name, name, true );
}

View file

@ -7,18 +7,14 @@ namespace ClassicalSharp {
public float U1, V1, U2, V2;
public TextureRec( float u, float v, float uWidth, float vHeight ) {
U1 = u;
V1 = v;
U2 = u + uWidth;
V2 = v + vHeight;
U1 = u; V1 = v;
U2 = u + uWidth; V2 = v + vHeight;
}
public static TextureRec FromPoints( float u1, float u2, float v1, float v2 ) {
TextureRec rec;
rec.U1 = u1;
rec.U2 = u2;
rec.V1 = v1;
rec.V2 = v2;
rec.U1 = u1;rec.U2 = u2;
rec.V1 = v1; rec.V2 = v2;
return rec;
}

View file

@ -65,6 +65,16 @@ namespace ClassicalSharp {
return new String( output, 0, usedChars );
}
/// <summary> Returns a string with a + removed if it is the last character in the string. </summary>
public static string RemoveEndPlus( string value ) {
// Some servers (e.g. MCDzienny) use a '+' at the end to distinguish classicube.net accounts
// from minecraft.net accounts. Unfortunately they also send this ending + to the client.
if( String.IsNullOrEmpty( value ) ) return value;
return value[value.Length - 1] == '+' ?
value.Substring( 0, value.Length - 1 ) : value;
}
/// <summary> Returns whether a equals b, ignoring any case differences. </summary>
public static bool CaselessEquals( string a, string b ) {
return a.Equals( b, StringComparison.OrdinalIgnoreCase );

View file

@ -104,7 +104,7 @@ namespace Launcher2 {
MakeButtonAt( "No", 60, 30, textFont, Anchor.Centre,
50, 40, (x, y) => game.SetScreen( new MainScreen( game ) ) );
} else {
MakeButtonAt( "Dismiss", 120, 30, textFont, Anchor.Centre,
MakeButtonAt( "Cancel", 120, 30, textFont, Anchor.Centre,
0, 40, (x, y) => game.SetScreen( new MainScreen( game ) ) );
}
}