Add CpeTextHotKey support.

This commit is contained in:
UnknownShadow200 2015-10-25 19:28:27 +11:00
parent 0d255b4586
commit c81014d6ef
9 changed files with 211 additions and 6 deletions

View File

@ -201,7 +201,7 @@ namespace ClassicalSharp {
return textInput.HandlesKeyPress( key );
}
void OpenTextInputBar( string initialText ) {
public void OpenTextInputBar( string initialText ) {
if( !game.CursorVisible )
game.CursorVisible = true;
suppressNextPress = true;

View File

@ -121,6 +121,10 @@ namespace ClassicalSharp {
return false;
}
public void OpenTextInputBar( string text ) {
chat.OpenTextInputBar( text );
}
public override bool HandlesMouseScroll( int delta ) {
return chat.HandlesMouseScroll( delta );
}

View File

@ -138,6 +138,8 @@
<Compile Include="Commands\Command.cs" />
<Compile Include="Commands\DefaultCommands.cs" />
<Compile Include="GraphicsAPI\VertexFormats.cs" />
<Compile Include="Hotkeys\HotkeyList.cs" />
<Compile Include="Hotkeys\LwjglToKey.cs" />
<Compile Include="Ionic.Zlib\DeflateStream.cs" />
<Compile Include="Ionic.Zlib\Inflate.cs" />
<Compile Include="Ionic.Zlib\InfTree.cs" />
@ -234,6 +236,7 @@
<Folder Include="Map\Formats" />
<Folder Include="Model" />
<Folder Include="Network\Utils" />
<Folder Include="Hotkeys" />
<Folder Include="TexturePack" />
<Folder Include="Singleplayer" />
<Folder Include="Utils" />

View File

@ -264,7 +264,7 @@ namespace ClassicalSharp {
PitchDegrees = Utils.LerpAngle( lastPitch, nextPitch, t );
}
internal void HandleKeyDown( Key key ) {
internal bool HandleKeyDown( Key key ) {
KeyMap keys = game.InputHandler.Keys;
if( key == keys[KeyMapping.Respawn] && canRespawn ) {
Vector3I p = Vector3I.Floor( SpawnPoint );
@ -289,7 +289,10 @@ namespace ClassicalSharp {
flying = !flying;
} else if( key == keys[KeyMapping.NoClip] && canNoclip ) {
noClip = !noClip;
} else {
return false;
}
return true;
}
/// <summary> Calculates the jump velocity required such that when a client presses

View File

@ -1,11 +1,13 @@
using System;
using OpenTK;
using OpenTK.Input;
using ClassicalSharp.Hotkeys;
namespace ClassicalSharp {
public sealed class InputHandler {
public HotkeyList Hotkeys = new HotkeyList();
Game game;
public InputHandler( Game game ) {
this.game = game;
@ -268,12 +270,25 @@ namespace ClassicalSharp {
} else if( key == Keys[KeyMapping.Screenshot] ) {
game.screenshotRequested = true;
} else if( game.activeScreen == null || !game.activeScreen.HandlesKeyDown( key ) ) {
if( !HandleBuiltinKey( key ) ) {
game.LocalPlayer.HandleKeyDown( key );
if( !HandleBuiltinKey( key ) && !game.LocalPlayer.HandleKeyDown( key ) ) {
HandleHotkey( key );
}
}
}
void HandleHotkey( Key key ) {
string text;
bool more;
if( Hotkeys.IsHotkey( key, game.Keyboard, out text, out more ) ) {
if( !more )
game.Network.SendChat( text );
else if( game.activeScreen is NormalScreen )
((NormalScreen)game.activeScreen).OpenTextInputBar( text );
}
}
MouseButtonEventArgs simArgs = new MouseButtonEventArgs();
bool SimulateMouse( Key key, bool pressed ) {
if( !(key == mapLeft || key == mapMiddle || key == mapRight ) )

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using OpenTK.Input;
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>();
/// <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 ) {
if( !UpdateExistingHotkey( baseKey, flags, text, more ) )
AddNewHotkey( baseKey, flags, text, more );
}
/// <summary> Removes an existing hotkey with the given baseKey and modifier flags. </summary>
/// <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];
if( hKey.BaseKey == baseKey && hKey.Flags == flags ) {
hotkeys.RemoveAt( i );
return true;
}
}
return false;
}
bool UpdateExistingHotkey( Key baseKey, byte flags, string text, bool more ) {
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;
return true;
}
}
return false;
}
void AddNewHotkey( Key baseKey, byte flags, string text, bool more ) {
Hotkey hotkey;
hotkey.BaseKey = baseKey;
hotkey.Flags = flags;
hotkey.Text = text;
hotkey.MoreInput = more;
hotkeys.Add( hotkey );
// sort so that hotkeys with largest modifiers are first
hotkeys.Sort( (a, b) => b.Flags.CompareTo( a.Flags ) );
}
/// <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 ) {
byte flags = 0;
if( keyboard[Key.ControlLeft] || keyboard[Key.ControlRight] ) flags |= 1;
if( keyboard[Key.ShiftLeft] || keyboard[Key.ShiftRight] ) flags |= 2;
if( keyboard[Key.AltLeft] || keyboard[Key.AltRight] ) flags |= 4;
foreach( Hotkey hKey in hotkeys ) {
if( (hKey.Flags & flags) == hKey.Flags && hKey.BaseKey == key ) {
text = hKey.Text;
moreInput = hKey.MoreInput;
return true;
}
}
text = null;
moreInput = false;
return false;
}
}
}

View File

@ -0,0 +1,73 @@
using System;
using OpenTK.Input;
namespace ClassicalSharp.Hotkeys {
/// <summary> Maps LWJGL keycodes to OpenTK keys. </summary>
public static class LwjglToKey {
public static Key[] Map = new Key[256];
static int curIndex = 0;
static void Add( Key key ) {
Map[curIndex++] = key;
}
static void Add( string value ) {
for( int i = 0; i < value.Length; i++ ) {
Add( (Key)(value[i] - 'A' + (int)Key.A) );
}
}
static void Skip( int amount ) {
curIndex += amount;
}
static LwjglToKey() {
Add( Key.Unknown ); Add( Key.Escape );
for( int i = 0; i < 9; i++ )
Add( (Key)(i + Key.Number1) );
Add( Key.Number0 ); Add( Key.Minus );
Add( Key.Plus ); Add( Key.BackSpace );
Add( Key.Tab ); Add( "QWERTYUIOP" );
Add( Key.BracketLeft ); Add( Key.BracketRight );
Add( Key.Enter ); Add( Key.ControlLeft );
Add( "ASDFGHJKL" ); Add( Key.Semicolon );
Add( Key.Quote ); Add( Key.Tilde );
Add( Key.ShiftLeft ); Add( Key.BackSlash );
Add( "ZXCVBNM" ); Add( Key.Comma );
Add( Key.Period ); Add( Key.Slash );
Add( Key.ShiftRight ); Skip( 1 ); // TODO: multiply
Add( Key.AltLeft ); Add( Key.Space );
Add( Key.CapsLock );
for( int i = 0; i < 10; i++ )
Add( (Key)(i + Key.F1) );
Add( Key.NumLock ); Add( Key.ScrollLock );
Add( Key.Number7 ); Add( Key.Number8 );
Add( Key.Number9 ); Add( Key.KeypadSubtract );
Add( Key.Number4 ); Add( Key.Number5 );
Add( Key.Number6 ); Add( Key.KeypadAdd );
Add( Key.Number1 ); Add( Key.Number2 );
Add( Key.Number3 ); Add( Key.Number0 );
Add( Key.KeypadDecimal ); Skip( 3 );
Add( Key.F11 ); Add( Key.F12 );
Skip( 11 );
for( int i = 0; i < 6; i++ )
Add( (Key)(i + Key.F13) );
Skip( 35 ); Add( Key.KeypadAdd );
Skip( 14 ); Add( Key.KeypadEnter );
Add( Key.ControlRight ); Skip( 23 );
Add( Key.KeypadDivide ); Skip( 2 );
Add( Key.AltRight ); Skip( 12 );
Add( Key.Pause ); Skip( 1 );
Add( Key.Home ); Add( Key.Up );
Add( Key.PageUp ); Skip( 1 );
Add( Key.Left ); Skip( 1 );
Add( Key.Right ); Skip( 1 );
Add( Key.End ); Add( Key.Down );
Add( Key.PageDown ); Add( Key.Insert );
Add( Key.Delete ); Skip( 7 );
Add( Key.WinLeft ); Add( Key.WinRight );
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using ClassicalSharp.TexturePack;
using OpenTK.Input;
using ClassicalSharp.Hotkeys;
namespace ClassicalSharp {
@ -57,7 +58,7 @@ namespace ClassicalSharp {
"EmoteFix", "ClickDistance", "HeldBlock", "BlockPermissions",
"SelectionCuboid", "MessageTypes", "CustomBlocks", "EnvColors",
"HackControl", "EnvMapAppearance", "ExtPlayerList", "ChangeModel",
"EnvWeatherType", "PlayerClick", // NOTE: There are no plans to support TextHotKey.
"EnvWeatherType", "PlayerClick", "TextHotKey",
};
void HandleCpeExtInfo() {
@ -126,6 +127,27 @@ namespace ClassicalSharp {
game.Inventory.CanChangeHeldBlock = canChange;
}
void HandleCpeSetTextHotkey() {
string label = reader.ReadAsciiString();
string action = reader.ReadAsciiString();
int keyCode = reader.ReadInt32();
byte keyMods = reader.ReadUInt8();
if( keyCode < 0 || keyCode > 255 ) return;
Key key = LwjglToKey.Map[keyCode];
if( key == Key.Unknown ) return;
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
action = action.Substring( 0, action.Length - 1 );
game.InputHandler.Hotkeys.AddHotkey( key, keyMods, action, true );
} else {
game.InputHandler.Hotkeys.AddHotkey( key, keyMods, action, false );
}
}
void HandleCpeExtAddPlayerName() {
short nameId = reader.ReadInt16();
string playerName = Utils.StripColours( reader.ReadAsciiString() );

View File

@ -455,7 +455,7 @@ namespace ClassicalSharp {
HandleMessage, HandleKick, HandleSetPermission,
HandleCpeExtInfo, HandleCpeExtEntry, HandleCpeSetClickDistance,
HandleCpeCustomBlockSupportLevel, HandleCpeHoldThis, null,
HandleCpeCustomBlockSupportLevel, HandleCpeHoldThis, HandleCpeSetTextHotkey,
HandleCpeExtAddPlayerName, HandleCpeExtAddEntity, HandleCpeExtRemovePlayerName,
HandleCpeEnvColours, HandleCpeMakeSelection, HandleCpeRemoveSelection,
HandleCpeSetBlockPermission, HandleCpeChangeModel, HandleCpeEnvSetMapApperance,