mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 19:45:23 -04:00
More work on new launcher.
This commit is contained in:
parent
92d32f6b3b
commit
87be12ec71
@ -91,6 +91,13 @@ namespace ClassicalSharp {
|
||||
g.Clear( colour );
|
||||
}
|
||||
|
||||
public override void Clear( Color colour, int x, int y, int width, int height ) {
|
||||
g.SmoothingMode = SmoothingMode.None;
|
||||
Brush brush = GetOrCreateBrush( colour );
|
||||
g.FillRectangle( brush, x, y, width, height );
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
g.Dispose();
|
||||
g = null;
|
||||
|
@ -35,6 +35,9 @@ namespace ClassicalSharp {
|
||||
/// <summary> Clears the entire bound bitmap to the specified colour. </summary>
|
||||
public abstract void Clear( Color colour );
|
||||
|
||||
/// <summary> Clears the entire bound bitmap to the specified colour. </summary>
|
||||
public abstract void Clear( Color colour, int x, int y, int width, int height );
|
||||
|
||||
/// <summary> Disposes of any resources used by this class that are associated with the underlying bitmap. </summary>
|
||||
public abstract void Dispose();
|
||||
|
||||
|
@ -11,9 +11,8 @@ namespace ClassicalSharp {
|
||||
|
||||
[STAThread]
|
||||
public static void Main( string[] args ) {
|
||||
if( !Debugger.IsAttached ) {
|
||||
if( !Debugger.IsAttached )
|
||||
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
|
||||
}
|
||||
|
||||
Utils.Log( "Starting " + Utils.AppName + ".." );
|
||||
if( !File.Exists( "default.zip" ) ) {
|
||||
|
52
Launcher2/Client.cs
Normal file
52
Launcher2/Client.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using ClassicalSharp;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public static class Client {
|
||||
|
||||
public static bool Start( GameStartData data, bool classicubeSkins ) {
|
||||
string skinServer = classicubeSkins ? "http://www.classicube.net/static/skins/" : "http://s3.amazonaws.com/MinecraftSkins/";
|
||||
string args = data.Username + " " + data.Mppass + " " +
|
||||
data.Ip + " " + data.Port + " " + skinServer;
|
||||
|
||||
UpdateResumeInfo( data, classicubeSkins );
|
||||
return Start( args );
|
||||
}
|
||||
|
||||
public static bool Start( string args ) {
|
||||
Process process = null;
|
||||
|
||||
if( !File.Exists( "ClassicalSharp.exe" ) )
|
||||
return false;
|
||||
|
||||
if( Type.GetType( "Mono.Runtime" ) != null ) {
|
||||
process = Process.Start( "mono", "\"ClassicalSharp.exe\" " + args );
|
||||
} else {
|
||||
process = Process.Start( "ClassicalSharp.exe", args );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void UpdateResumeInfo( GameStartData data, bool classiCubeSkins ) {
|
||||
// If the client has changed some settings in the meantime, make sure we keep the changes
|
||||
try {
|
||||
Options.Load();
|
||||
} catch( IOException ) {
|
||||
}
|
||||
|
||||
Options.Set( "launcher-username", data.Username );
|
||||
Options.Set( "launcher-ip", data.Ip );
|
||||
Options.Set( "launcher-port", data.Port );
|
||||
Options.Set( "launcher-mppass", Secure.Encode( data.Mppass, data.Username ) );
|
||||
Options.Set( "launcher-ccskins", classiCubeSkins );
|
||||
|
||||
try {
|
||||
Options.Save();
|
||||
} catch( IOException ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
252
Launcher2/Gui/ClassiCubeScreen.cs
Normal file
252
Launcher2/Gui/ClassiCubeScreen.cs
Normal file
@ -0,0 +1,252 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using ClassicalSharp;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class ClassiCubeScreen : LauncherScreen {
|
||||
|
||||
public ClassiCubeScreen( LauncherWindow game ) : base( game ) {
|
||||
textFont = new Font( "Arial", 16, FontStyle.Bold );
|
||||
widgets = new LauncherWidget[7];
|
||||
game.Window.Mouse.Move += MouseMove;
|
||||
game.Window.Mouse.ButtonDown += MouseButtonDown;
|
||||
|
||||
game.Window.KeyPress += KeyPress;
|
||||
game.Window.Keyboard.KeyDown += KeyDown;
|
||||
game.Window.Keyboard.KeyRepeat = true;
|
||||
}
|
||||
|
||||
void KeyDown( object sender, KeyboardKeyEventArgs e ) {
|
||||
if( lastInput != null && e.Key == Key.BackSpace ) {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
lastInput.RemoveChar( textFont );
|
||||
Dirty = true;
|
||||
}
|
||||
} else if( e.Key == Key.Enter ) { // Click sign in button
|
||||
LauncherWidget widget = widgets[4];
|
||||
if( widget.OnClick != null )
|
||||
widget.OnClick();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyPress( object sender, KeyPressEventArgs e ) {
|
||||
if( lastInput != null ) {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
lastInput.AddChar( e.KeyChar, textFont );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
Resize();
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
LoadSavedInfo( drawer );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSavedInfo( IDrawer2D drawer ) {
|
||||
try {
|
||||
Options.Load();
|
||||
} catch( IOException ) {
|
||||
return;
|
||||
}
|
||||
|
||||
string user = Options.Get( "launcher-cc-username" ) ?? "";
|
||||
string pass = Options.Get( "launcher-cc-password" ) ?? "";
|
||||
pass = Secure.Decode( pass, user );
|
||||
|
||||
Set( 2, user );
|
||||
Set( 3, pass );
|
||||
}
|
||||
|
||||
public override void Resize() {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
DrawButtons( drawer );
|
||||
}
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
Font textFont;
|
||||
static FastColour boxCol = new FastColour( 169, 143, 192 ), shadowCol = new FastColour( 97, 81, 110 );
|
||||
void DrawButtons( IDrawer2D drawer ) {
|
||||
widgetIndex = 0;
|
||||
MakeTextAt( drawer, "Username", -180, -100 );
|
||||
MakeTextAt( drawer, "Password", -180, -50 );
|
||||
|
||||
MakeTextInputAt( drawer, false, Get( widgetIndex ), 30, -100 );
|
||||
MakeTextInputAt( drawer, true, Get( widgetIndex ), 30, -50 );
|
||||
|
||||
MakeButtonAt( drawer, "Sign in", 110, 35, -65, 0, StartClient );
|
||||
MakeButtonAt( drawer, "Back", 80, 35, 140, 0, () => game.SetScreen( new MainScreen( game ) ) );
|
||||
MakeTextAt( drawer, "", 0, 50 );
|
||||
}
|
||||
|
||||
ClassicubeSession session = new ClassicubeSession();
|
||||
List<ServerListEntry> servers = new List<ServerListEntry>();
|
||||
void StartClient() {
|
||||
if( String.IsNullOrEmpty( Get( 2 ) ) ) {
|
||||
SetStatus( "&ePlease enter a username" ); return;
|
||||
}
|
||||
if( String.IsNullOrEmpty( Get( 3 ) ) ) {
|
||||
SetStatus( "&ePlease enter a username" ); return;
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine( Get( 2 ) );
|
||||
System.Diagnostics.Debug.WriteLine( Get( 3 ) );
|
||||
|
||||
SetStatus( "&eSigning in..." );
|
||||
try {
|
||||
session.Login( Get( 2 ), Get( 3 ) );
|
||||
} catch( WebException ex ) {
|
||||
session.Username = null;
|
||||
DisplayWebException( ex, "sign in" );
|
||||
return;
|
||||
} catch( InvalidOperationException ex ) {
|
||||
session.Username = null;
|
||||
string text = "&eFailed to sign in: " +
|
||||
Environment.NewLine + ex.Message;
|
||||
SetStatus( text );
|
||||
return;
|
||||
}
|
||||
|
||||
SetStatus( "&eRetrieving public servers list.." );
|
||||
try {
|
||||
servers = session.GetPublicServers();
|
||||
} catch( WebException ex ) {
|
||||
servers = new List<ServerListEntry>();
|
||||
DisplayWebException( ex, "retrieve servers list" );
|
||||
return;
|
||||
}
|
||||
SetStatus( "&eSigned in" );
|
||||
}
|
||||
|
||||
string Get( int index ) {
|
||||
LauncherWidget widget = widgets[index];
|
||||
return widget == null ? "" : ((widget as LauncherTextInputWidget)).Text;
|
||||
}
|
||||
|
||||
void Set( int index, string text ) {
|
||||
(widgets[index] as LauncherTextInputWidget)
|
||||
.Redraw( game.Drawer, text, textFont );
|
||||
}
|
||||
|
||||
void SetStatus( string text ) {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
LauncherTextWidget widget = (LauncherTextWidget)widgets[6];
|
||||
drawer.Clear( LauncherWindow.clearColour, widget.X, widget.Y,
|
||||
widget.Width, widget.Height );
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, 0, 50 );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MakeTextAt( IDrawer2D drawer, string text, int x, int y ) {
|
||||
LauncherTextWidget widget = new LauncherTextWidget( game );
|
||||
widget.Text = text;
|
||||
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, x, y );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
void MakeTextInputAt( IDrawer2D drawer, bool password, string text, int x, int y ) {
|
||||
LauncherTextInputWidget widget = new LauncherTextInputWidget( game );
|
||||
widget.OnClick = InputClick;
|
||||
widget.Password = password;
|
||||
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, 300, 30, x, y );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
void MakeButtonAt( IDrawer2D drawer, string text, int width, int height,
|
||||
int x, int y, Action onClick ) {
|
||||
LauncherButtonWidget widget = new LauncherButtonWidget( game );
|
||||
widget.Text = text;
|
||||
widget.OnClick = onClick;
|
||||
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, width, height, x, y );
|
||||
FilterArea( widget.X, widget.Y, widget.Width, widget.Height, 180 );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
protected override void UnselectWidget( LauncherWidget widget ) {
|
||||
LauncherButtonWidget button = widget as LauncherButtonWidget;
|
||||
if( button != null ) {
|
||||
button.Redraw( game.Drawer, button.Text, textFont );
|
||||
FilterArea( widget.X, widget.Y, widget.Width, widget.Height, 180 );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SelectWidget( LauncherWidget widget ) {
|
||||
LauncherButtonWidget button = widget as LauncherButtonWidget;
|
||||
if( button != null ) {
|
||||
button.Redraw( game.Drawer, button.Text, textFont );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
LauncherTextInputWidget lastInput;
|
||||
void InputClick() {
|
||||
LauncherTextInputWidget input = selectedWidget as LauncherTextInputWidget;
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
if( lastInput != null ) {
|
||||
lastInput.Active = false;
|
||||
lastInput.Redraw( game.Drawer, lastInput.Text, textFont );
|
||||
}
|
||||
|
||||
input.Active = true;
|
||||
input.Redraw( game.Drawer, input.Text, textFont );
|
||||
}
|
||||
lastInput = input;
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
textFont.Dispose();
|
||||
game.Window.Mouse.Move -= MouseMove;
|
||||
game.Window.Mouse.ButtonDown -= MouseButtonDown;
|
||||
|
||||
game.Window.KeyPress -= KeyPress;
|
||||
game.Window.Keyboard.KeyDown -= KeyDown;
|
||||
game.Window.Keyboard.KeyRepeat = false;
|
||||
}
|
||||
|
||||
void DisplayWebException( WebException ex, string action ) {
|
||||
Program.LogException( ex );
|
||||
if( ex.Status == WebExceptionStatus.Timeout ) {
|
||||
string text = "&eFailed to " + action + ":" +
|
||||
Environment.NewLine + "Timed out while connecting to classicube.net.";
|
||||
SetStatus( text );
|
||||
} else if( ex.Status == WebExceptionStatus.ProtocolError ) {
|
||||
HttpWebResponse response = (HttpWebResponse)ex.Response;
|
||||
int errorCode = (int)response.StatusCode;
|
||||
string description = response.StatusDescription;
|
||||
string text = "&eFailed to " + action + ":" +
|
||||
Environment.NewLine + " classicube.net returned: (" + errorCode + ") " + description;
|
||||
SetStatus(text );
|
||||
} else if( ex.Status == WebExceptionStatus.NameResolutionFailure ) {
|
||||
string text = "&eFailed to " + action + ":" +
|
||||
Environment.NewLine + "Unable to resolve classicube.net" +
|
||||
Environment.NewLine + "you may not be connected to the internet.";
|
||||
SetStatus( text );
|
||||
} else {
|
||||
string text = "&eFailed to " + action + ":" +
|
||||
Environment.NewLine + ex.Status;
|
||||
SetStatus( text );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
226
Launcher2/Gui/DirectConnectScreen.cs
Normal file
226
Launcher2/Gui/DirectConnectScreen.cs
Normal file
@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using ClassicalSharp;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class DirectConnectScreen : LauncherScreen {
|
||||
|
||||
public DirectConnectScreen( LauncherWindow game ) : base( game ) {
|
||||
textFont = new Font( "Arial", 16, FontStyle.Bold );
|
||||
widgets = new LauncherWidget[9];
|
||||
game.Window.Mouse.Move += MouseMove;
|
||||
game.Window.Mouse.ButtonDown += MouseButtonDown;
|
||||
|
||||
game.Window.KeyPress += KeyPress;
|
||||
game.Window.Keyboard.KeyDown += KeyDown;
|
||||
game.Window.Keyboard.KeyRepeat = true;
|
||||
}
|
||||
|
||||
void KeyDown( object sender, KeyboardKeyEventArgs e ) {
|
||||
if( lastInput != null && e.Key == Key.BackSpace ) {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
lastInput.RemoveChar( textFont );
|
||||
Dirty = true;
|
||||
}
|
||||
} else if( e.Key == Key.Enter ) { // Click connect button
|
||||
LauncherWidget widget = widgets[6];
|
||||
if( widget.OnClick != null )
|
||||
widget.OnClick();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyPress( object sender, KeyPressEventArgs e ) {
|
||||
if( lastInput != null ) {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
lastInput.AddChar( e.KeyChar, textFont );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
Resize();
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
LoadSavedInfo( drawer );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSavedInfo( IDrawer2D drawer ) {
|
||||
try {
|
||||
Options.Load();
|
||||
} catch( IOException ) {
|
||||
return;
|
||||
}
|
||||
|
||||
string user = Options.Get( "launcher-username" ) ?? "";
|
||||
string ip = Options.Get( "launcher-ip" ) ?? "127.0.0.1";
|
||||
string port = Options.Get( "launcher-port" ) ?? "25565";
|
||||
|
||||
IPAddress address;
|
||||
if( !IPAddress.TryParse( ip, out address ) ) ip = "127.0.0.1";
|
||||
ushort portNum;
|
||||
if( !UInt16.TryParse( port, out portNum ) ) port = "25565";
|
||||
|
||||
string mppass = Options.Get( "launcher-mppass" ) ?? null;
|
||||
mppass = Secure.Decode( mppass, user );
|
||||
|
||||
Set( 3, user );
|
||||
Set( 4, ip + ":" + port );
|
||||
Set( 5, mppass );
|
||||
}
|
||||
|
||||
public override void Resize() {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
DrawButtons( drawer );
|
||||
}
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
Font textFont;
|
||||
static FastColour boxCol = new FastColour( 169, 143, 192 ), shadowCol = new FastColour( 97, 81, 110 );
|
||||
void DrawButtons( IDrawer2D drawer ) {
|
||||
widgetIndex = 0;
|
||||
MakeTextAt( drawer, "Username", -180, -100 );
|
||||
MakeTextAt( drawer, "Address", -180, -50 );
|
||||
MakeTextAt( drawer, "Mppass", -180, 0 );
|
||||
|
||||
MakeTextInputAt( drawer, Get( widgetIndex ), 30, -100 );
|
||||
MakeTextInputAt( drawer, Get( widgetIndex ), 30, -50 );
|
||||
MakeTextInputAt( drawer, Get( widgetIndex ), 30, 0 );
|
||||
|
||||
MakeButtonAt( drawer, "Connect", 110, 35, -65, 50, StartClient );
|
||||
MakeButtonAt( drawer, "Back", 80, 35, 140, 50, () => game.SetScreen( new MainScreen( game ) ) );
|
||||
MakeTextAt( drawer, "", 0, 100 );
|
||||
}
|
||||
|
||||
void StartClient() {
|
||||
SetStatus( "" );
|
||||
|
||||
if( String.IsNullOrEmpty( Get( 3 ) ) ) {
|
||||
SetStatus( "&ePlease enter a username" ); return;
|
||||
}
|
||||
|
||||
string address = Get( 4 );
|
||||
int index = address.LastIndexOf( ':' );
|
||||
if( index <= 0 || index == address.Length - 1 ) {
|
||||
SetStatus( "&eInvalid address" ); return;
|
||||
}
|
||||
|
||||
string ipPart = address.Substring( 0, index ); IPAddress ip;
|
||||
if( !IPAddress.TryParse( ipPart, out ip ) ) {
|
||||
SetStatus( "&eInvalid ip" ); return;
|
||||
}
|
||||
string portPart = address.Substring( index + 1, address.Length - index - 1 ); ushort port;
|
||||
if( !UInt16.TryParse( portPart, out port ) ) {
|
||||
SetStatus( "&eInvalid port" ); return;
|
||||
}
|
||||
|
||||
string mppass = Get( 5 );
|
||||
if( String.IsNullOrEmpty( mppass ) ) mppass = "(none)";
|
||||
GameStartData data = new GameStartData( Get( 3 ), mppass, ipPart, portPart );
|
||||
Client.Start( data, false );
|
||||
}
|
||||
|
||||
string Get( int index ) {
|
||||
LauncherWidget widget = widgets[index];
|
||||
return widget == null ? "" : ((widget as LauncherTextInputWidget)).Text;
|
||||
}
|
||||
|
||||
void Set( int index, string text ) {
|
||||
(widgets[index] as LauncherTextInputWidget)
|
||||
.Redraw( game.Drawer, text, textFont );
|
||||
}
|
||||
|
||||
void SetStatus( string text ) {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
LauncherTextWidget widget = (LauncherTextWidget)widgets[8];
|
||||
drawer.Clear( LauncherWindow.clearColour, widget.X, widget.Y,
|
||||
widget.Width, widget.Height );
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, 0, 100 );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MakeTextAt( IDrawer2D drawer, string text, int x, int y ) {
|
||||
LauncherTextWidget widget = new LauncherTextWidget( game );
|
||||
widget.Text = text;
|
||||
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, x, y );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
void MakeTextInputAt( IDrawer2D drawer, string text, int x, int y ) {
|
||||
LauncherTextInputWidget widget = new LauncherTextInputWidget( game );
|
||||
widget.OnClick = InputClick;
|
||||
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, 300, 30, x, y );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
void MakeButtonAt( IDrawer2D drawer, string text, int width, int height,
|
||||
int x, int y, Action onClick ) {
|
||||
LauncherButtonWidget widget = new LauncherButtonWidget( game );
|
||||
widget.Text = text;
|
||||
widget.OnClick = onClick;
|
||||
|
||||
widget.DrawAt( drawer, text, textFont, Anchor.Centre, Anchor.Centre, width, height, x, y );
|
||||
FilterArea( widget.X, widget.Y, widget.Width, widget.Height, 180 );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
protected override void UnselectWidget( LauncherWidget widget ) {
|
||||
LauncherButtonWidget button = widget as LauncherButtonWidget;
|
||||
if( button != null ) {
|
||||
button.Redraw( game.Drawer, button.Text, textFont );
|
||||
FilterArea( widget.X, widget.Y, widget.Width, widget.Height, 180 );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SelectWidget( LauncherWidget widget ) {
|
||||
LauncherButtonWidget button = widget as LauncherButtonWidget;
|
||||
if( button != null ) {
|
||||
button.Redraw( game.Drawer, button.Text, textFont );
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
LauncherTextInputWidget lastInput;
|
||||
void InputClick() {
|
||||
LauncherTextInputWidget input = selectedWidget as LauncherTextInputWidget;
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
if( lastInput != null ) {
|
||||
lastInput.Active = false;
|
||||
lastInput.Redraw( game.Drawer, lastInput.Text, textFont );
|
||||
}
|
||||
|
||||
input.Active = true;
|
||||
input.Redraw( game.Drawer, input.Text, textFont );
|
||||
}
|
||||
lastInput = input;
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
textFont.Dispose();
|
||||
game.Window.Mouse.Move -= MouseMove;
|
||||
game.Window.Mouse.ButtonDown -= MouseButtonDown;
|
||||
|
||||
game.Window.KeyPress -= KeyPress;
|
||||
game.Window.Keyboard.KeyDown -= KeyDown;
|
||||
game.Window.Keyboard.KeyRepeat = false;
|
||||
}
|
||||
}
|
||||
}
|
87
Launcher2/Gui/LauncherScreen.cs
Normal file
87
Launcher2/Gui/LauncherScreen.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using ClassicalSharp;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public abstract class LauncherScreen {
|
||||
protected LauncherWindow game;
|
||||
|
||||
public bool Dirty;
|
||||
protected int widgetIndex;
|
||||
|
||||
public LauncherScreen( LauncherWindow game ) {
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
public abstract void Init();
|
||||
|
||||
public abstract void Resize();
|
||||
|
||||
public abstract void Dispose();
|
||||
|
||||
static uint clearColourBGRA = (uint)LauncherWindow.clearColour.ToArgb();
|
||||
protected unsafe void FilterArea( int x, int y, int width, int height, byte scale ) {
|
||||
using( FastBitmap bmp = new FastBitmap( game.Framebuffer, true ) ) {
|
||||
for( int yy = y; yy < y + height; yy++ ) {
|
||||
int* row = bmp.GetRowPtr( yy ) + x;
|
||||
for( int xx = 0; xx < width; xx++ ) {
|
||||
uint pixel = (uint)row[xx];
|
||||
if( pixel == clearColourBGRA ) continue;
|
||||
|
||||
uint a = pixel & 0xFF000000;
|
||||
uint r = (pixel >> 16) & 0xFF;
|
||||
uint g = (pixel >> 8) & 0xFF;
|
||||
uint b = pixel & 0xFF;
|
||||
|
||||
r = (r * scale) / 255;
|
||||
g = (g * scale) / 255;
|
||||
b = (b * scale) / 255;
|
||||
row[xx] = (int)(a | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected LauncherWidget selectedWidget;
|
||||
protected LauncherWidget[] widgets;
|
||||
protected void MouseMove( object sender, MouseMoveEventArgs e ) {
|
||||
for( int i = 0; i < widgets.Length; i++ ) {
|
||||
LauncherWidget widget = widgets[i];
|
||||
if( e.X >= widget.X && e.Y >= widget.Y &&
|
||||
e.X < widget.X + widget.Width && e.Y < widget.Y + widget.Height ) {
|
||||
if( selectedWidget == widget ) return;
|
||||
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
if( selectedWidget != null )
|
||||
UnselectWidget( selectedWidget );
|
||||
SelectWidget( widget );
|
||||
}
|
||||
selectedWidget = widget;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( selectedWidget == null ) return;
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
UnselectWidget( selectedWidget );
|
||||
}
|
||||
selectedWidget = null;
|
||||
}
|
||||
|
||||
protected virtual void UnselectWidget( LauncherWidget widget ) {
|
||||
}
|
||||
|
||||
protected virtual void SelectWidget( LauncherWidget widget ) {
|
||||
}
|
||||
|
||||
protected void MouseButtonDown( object sender, MouseButtonEventArgs e ) {
|
||||
if( e.Button != MouseButton.Left ) return;
|
||||
|
||||
if( selectedWidget != null && selectedWidget.OnClick != null )
|
||||
selectedWidget.OnClick();
|
||||
}
|
||||
}
|
||||
}
|
78
Launcher2/Gui/MainScreen.cs
Normal file
78
Launcher2/Gui/MainScreen.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using ClassicalSharp;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class MainScreen : LauncherScreen {
|
||||
|
||||
public MainScreen( LauncherWindow game ) : base( game ) {
|
||||
game.Window.Mouse.Move += MouseMove;
|
||||
game.Window.Mouse.ButtonDown += MouseButtonDown;
|
||||
textFont = new Font( "Arial", 16, FontStyle.Bold );
|
||||
widgets = new LauncherWidget[4];
|
||||
}
|
||||
|
||||
protected override void UnselectWidget( LauncherWidget widget ) {
|
||||
LauncherButtonWidget button = widget as LauncherButtonWidget;
|
||||
button.Redraw( game.Drawer, button.Text, textFont );
|
||||
FilterArea( widget.X, widget.Y, widget.Width, widget.Height, 180 );
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
protected override void SelectWidget( LauncherWidget widget ) {
|
||||
LauncherButtonWidget button = widget as LauncherButtonWidget;
|
||||
button.Redraw( game.Drawer, button.Text, textFont );
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
public override void Init() { Resize(); }
|
||||
|
||||
public override void Resize() {
|
||||
using( IDrawer2D drawer = game.Drawer ) {
|
||||
drawer.SetBitmap( game.Framebuffer );
|
||||
DrawButtons( drawer );
|
||||
}
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
Font textFont;
|
||||
static FastColour boxCol = new FastColour( 169, 143, 192 ), shadowCol = new FastColour( 97, 81, 110 );
|
||||
void DrawButtons( IDrawer2D drawer ) {
|
||||
widgetIndex = 0;
|
||||
MakeButtonAt( drawer, "Direct connect", Anchor.Centre, Anchor.Centre,
|
||||
buttonWidth, buttonHeight, 0, -100,
|
||||
() => game.SetScreen( new DirectConnectScreen( game ) ) );
|
||||
|
||||
MakeButtonAt( drawer, "ClassiCube.net", Anchor.Centre, Anchor.Centre,
|
||||
buttonWidth, buttonHeight, 0, -50,
|
||||
() => game.SetScreen( new ClassiCubeScreen( game ) ) );
|
||||
|
||||
MakeButtonAt( drawer, "Singleplayer", Anchor.LeftOrTop, Anchor.BottomOrRight,
|
||||
sideButtonWidth, buttonHeight, 10, -10,
|
||||
() => Client.Start( "default.zip" ) );
|
||||
|
||||
MakeButtonAt( drawer, "Resume", Anchor.BottomOrRight, Anchor.BottomOrRight,
|
||||
sideButtonWidth, buttonHeight, -10, -10, null );
|
||||
}
|
||||
|
||||
const int buttonWidth = 220, buttonHeight = 35, sideButtonWidth = 150;
|
||||
void MakeButtonAt( IDrawer2D drawer, string text, Anchor horAnchor,
|
||||
Anchor verAnchor, int width, int height, int x, int y, Action onClick ) {
|
||||
LauncherButtonWidget widget = new LauncherButtonWidget( game );
|
||||
widget.Text = text;
|
||||
widget.OnClick = onClick;
|
||||
|
||||
widget.DrawAt( drawer, text, textFont, horAnchor, verAnchor, width, height, x, y );
|
||||
FilterArea( widget.X, widget.Y, widget.Width, widget.Height, 180 );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
game.Window.Mouse.Move -= MouseMove;
|
||||
game.Window.Mouse.ButtonDown -= MouseButtonDown;
|
||||
textFont.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,17 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using ClassicalSharp;
|
||||
using OpenTK;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class FastButtonWidget {
|
||||
public sealed class LauncherButtonWidget : LauncherWidget {
|
||||
|
||||
public int ButtonWidth, ButtonHeight;
|
||||
public int X, Y, Width, Height;
|
||||
public NativeWindow Window;
|
||||
public Action OnClick;
|
||||
public string Text;
|
||||
|
||||
public LauncherButtonWidget( LauncherWindow window ) : base( window ) {
|
||||
}
|
||||
|
||||
static FastColour boxCol = new FastColour( 169, 143, 192 ), shadowCol = new FastColour( 97, 81, 110 );
|
||||
public void DrawAt( IDrawer2D drawer, string text, Font font, Anchor horAnchor,
|
||||
Anchor verAnchor, int width, int height, int x, int y ) {
|
||||
@ -22,16 +21,6 @@ namespace Launcher2 {
|
||||
Redraw( drawer, text, font );
|
||||
}
|
||||
|
||||
void CalculateOffset( int x, int y, Anchor horAnchor, Anchor verAnchor ) {
|
||||
if( horAnchor == Anchor.LeftOrTop ) X = x;
|
||||
else if( horAnchor == Anchor.Centre ) X = x + Window.Width / 2 - Width / 2;
|
||||
else if( horAnchor == Anchor.BottomOrRight ) X = x + Window.Width - Width;
|
||||
|
||||
if( verAnchor == Anchor.LeftOrTop ) Y = y;
|
||||
else if( verAnchor == Anchor.Centre ) Y = y + Window.Height / 2 - Height / 2;
|
||||
else if( verAnchor == Anchor.BottomOrRight ) Y = y + Window.Height - Height;
|
||||
}
|
||||
|
||||
public void Redraw( IDrawer2D drawer, string text, Font font ) {
|
||||
Size size = drawer.MeasureSize( text, font, true );
|
||||
int width = ButtonWidth, height = ButtonHeight;
|
55
Launcher2/Gui/Widgets/LauncherTextInputWidget.cs
Normal file
55
Launcher2/Gui/Widgets/LauncherTextInputWidget.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using ClassicalSharp;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class LauncherTextInputWidget : LauncherWidget {
|
||||
|
||||
public int ButtonWidth, ButtonHeight;
|
||||
public string Text;
|
||||
public bool Active;
|
||||
public bool Password;
|
||||
|
||||
public LauncherTextInputWidget( LauncherWindow window ) : base( window ) {
|
||||
}
|
||||
|
||||
public void DrawAt( IDrawer2D drawer, string text, Font font,
|
||||
Anchor horAnchor, Anchor verAnchor, int width, int height, int x, int y ) {
|
||||
ButtonWidth = width; ButtonHeight = height;
|
||||
Width = width; Height = height;
|
||||
CalculateOffset( x, y, horAnchor, verAnchor );
|
||||
Redraw( drawer, text, font );
|
||||
}
|
||||
|
||||
public void Redraw( IDrawer2D drawer, string text, Font font ) {
|
||||
Text = text;
|
||||
if( Password )
|
||||
text = new String( '*', text.Length );
|
||||
Size size = drawer.MeasureSize( text, font, true );
|
||||
Width = Math.Max( ButtonWidth, size.Width + 7 );
|
||||
|
||||
FastColour col = Active ? FastColour.White : new FastColour( 160, 160, 160 );
|
||||
drawer.DrawRectBounds( col, 2, X, Y, Width, Height );
|
||||
drawer.DrawRect( FastColour.Black, X + 2, Y + 2, Width - 4, Height - 4 );
|
||||
|
||||
DrawTextArgs args = new DrawTextArgs( text, true );
|
||||
args.SkipPartsCheck = true;
|
||||
drawer.DrawText( font, ref args, X + 7, Y + 2 );
|
||||
}
|
||||
|
||||
public void AddChar( char c, Font font ) {
|
||||
if( c >= ' ' && c <= '~' ) {
|
||||
Text += c;
|
||||
Redraw( Window.Drawer, Text, font );
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveChar( Font font ) {
|
||||
if( Text.Length == 0 ) return;
|
||||
|
||||
Text = Text.Substring( 0, Text.Length - 1 );
|
||||
Redraw( Window.Drawer, Text, font );
|
||||
}
|
||||
}
|
||||
}
|
28
Launcher2/Gui/Widgets/LauncherTextWidget.cs
Normal file
28
Launcher2/Gui/Widgets/LauncherTextWidget.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using ClassicalSharp;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class LauncherTextWidget : LauncherWidget {
|
||||
|
||||
public string Text;
|
||||
|
||||
public LauncherTextWidget( LauncherWindow window ) : base( window ) {
|
||||
}
|
||||
|
||||
public void DrawAt( IDrawer2D drawer, string text, Font font,
|
||||
Anchor horAnchor, Anchor verAnchor, int x, int y ) {
|
||||
Size size = drawer.MeasureSize( text, font, true );
|
||||
Width = size.Width; Height = size.Height;
|
||||
|
||||
CalculateOffset( x, y, horAnchor, verAnchor );
|
||||
Redraw( drawer, text, font );
|
||||
}
|
||||
|
||||
public void Redraw( IDrawer2D drawer, string text, Font font ) {
|
||||
DrawTextArgs args = new DrawTextArgs( text, true );
|
||||
drawer.DrawText( font, ref args, X, Y );
|
||||
}
|
||||
}
|
||||
}
|
26
Launcher2/Gui/Widgets/LauncherWidget.cs
Normal file
26
Launcher2/Gui/Widgets/LauncherWidget.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using ClassicalSharp;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public abstract class LauncherWidget {
|
||||
|
||||
public int X, Y, Width, Height;
|
||||
public LauncherWindow Window;
|
||||
public Action OnClick;
|
||||
|
||||
public LauncherWidget( LauncherWindow window ) {
|
||||
Window = window;
|
||||
}
|
||||
|
||||
protected void CalculateOffset( int x, int y, Anchor horAnchor, Anchor verAnchor ) {
|
||||
if( horAnchor == Anchor.LeftOrTop ) X = x;
|
||||
else if( horAnchor == Anchor.Centre ) X = x + Window.Width / 2 - Width / 2;
|
||||
else if( horAnchor == Anchor.BottomOrRight ) X = x + Window.Width - Width;
|
||||
|
||||
if( verAnchor == Anchor.LeftOrTop ) Y = y;
|
||||
else if( verAnchor == Anchor.Centre ) Y = y + Window.Height / 2 - Height / 2;
|
||||
else if( verAnchor == Anchor.BottomOrRight ) Y = y + Window.Height - Height;
|
||||
}
|
||||
}
|
||||
}
|
@ -45,16 +45,27 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FastButtonWidget.cs" />
|
||||
<Compile Include="Client.cs" />
|
||||
<Compile Include="GameStartData.cs" />
|
||||
<Compile Include="MainScreen.cs" />
|
||||
<Compile Include="Gui\ClassiCubeScreen.cs" />
|
||||
<Compile Include="Gui\DirectConnectScreen.cs" />
|
||||
<Compile Include="Gui\LauncherScreen.cs" />
|
||||
<Compile Include="Gui\MainScreen.cs" />
|
||||
<Compile Include="Gui\Widgets\LauncherButtonWidget.cs" />
|
||||
<Compile Include="Gui\Widgets\LauncherTextInputWidget.cs" />
|
||||
<Compile Include="Gui\Widgets\LauncherTextWidget.cs" />
|
||||
<Compile Include="Gui\Widgets\LauncherWidget.cs" />
|
||||
<Compile Include="LauncherWindow.cs" />
|
||||
<Compile Include="Patcher\Animations.cs" />
|
||||
<Compile Include="Patcher\ResourceFetcher.cs" />
|
||||
<Compile Include="Patcher\ZipWriter.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Secure.cs" />
|
||||
<Compile Include="WebService\ClassiCubeSession.cs" />
|
||||
<Compile Include="WebService\GameSession.cs" />
|
||||
<Compile Include="WebService\ServerListEntry.cs" />
|
||||
@ -71,6 +82,8 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Gui" />
|
||||
<Folder Include="Gui\Widgets" />
|
||||
<Folder Include="Patcher" />
|
||||
<Folder Include="WebService" />
|
||||
</ItemGroup>
|
||||
|
110
Launcher2/LauncherWindow.cs
Normal file
110
Launcher2/LauncherWindow.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using ClassicalSharp;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Platform.Windows;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class LauncherWindow {
|
||||
|
||||
public NativeWindow Window;
|
||||
public IDrawer2D Drawer;
|
||||
public LauncherScreen screen;
|
||||
public bool Dirty;
|
||||
|
||||
public int Width { get { return Window.Width; } }
|
||||
|
||||
public int Height { get { return Window.Height; } }
|
||||
|
||||
public Bitmap Framebuffer;
|
||||
Font logoFont, logoItalicFont;
|
||||
public void Init() {
|
||||
Window.Resize += Resize;
|
||||
Window.FocusedChanged += FocusedChanged;
|
||||
logoFont = new Font( "Times New Roman", 28, FontStyle.Bold );
|
||||
logoItalicFont = new Font( "Times New Roman", 28, FontStyle.Italic );
|
||||
}
|
||||
|
||||
void FocusedChanged( object sender, EventArgs e ) {
|
||||
MakeBackground();
|
||||
screen.Resize();
|
||||
}
|
||||
|
||||
void Resize( object sender, EventArgs e ) {
|
||||
MakeBackground();
|
||||
screen.Resize();
|
||||
}
|
||||
|
||||
public void SetScreen( LauncherScreen screen ) {
|
||||
if( this.screen != null )
|
||||
this.screen.Dispose();
|
||||
|
||||
MakeBackground();
|
||||
this.screen = screen;
|
||||
screen.Init();
|
||||
}
|
||||
|
||||
public void Run() {
|
||||
Window = new NativeWindow( 480, 480, Program.AppName, 0,
|
||||
GraphicsMode.Default, DisplayDevice.Default );
|
||||
Window.Visible = true;
|
||||
screen = new MainScreen( this );
|
||||
Drawer = new GdiPlusDrawer2D( null );
|
||||
Init();
|
||||
SetScreen( new MainScreen( this ) );
|
||||
|
||||
while( true ) {
|
||||
Window.ProcessEvents();
|
||||
if( !Window.Exists ) break;
|
||||
|
||||
if( Dirty || (screen != null && screen.Dirty) )
|
||||
Display();
|
||||
Thread.Sleep( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
void Display() {
|
||||
Dirty = false;
|
||||
if( screen != null )
|
||||
screen.Dirty = false;
|
||||
|
||||
WinWindowInfo info = (WinWindowInfo)Window.WindowInfo;
|
||||
IntPtr dc = info.DeviceContext;
|
||||
|
||||
using( Graphics g = Graphics.FromHdc( dc ) )
|
||||
g.DrawImage( Framebuffer, 0, 0, Framebuffer.Width, Framebuffer.Height );
|
||||
}
|
||||
|
||||
internal static FastColour clearColour = new FastColour( 30, 30, 30 );
|
||||
public void MakeBackground() {
|
||||
if( Framebuffer != null )
|
||||
Framebuffer.Dispose();
|
||||
|
||||
Framebuffer = new Bitmap( Width, Height );
|
||||
using( IDrawer2D drawer = Drawer ) {
|
||||
drawer.SetBitmap( Framebuffer );
|
||||
drawer.Clear( clearColour );
|
||||
|
||||
Size size1 = drawer.MeasureSize( "&eClassical", logoItalicFont, true );
|
||||
Size size2 = drawer.MeasureSize( "&eSharp", logoFont, true );
|
||||
int xStart = Width / 2 - (size1.Width + size2.Width ) / 2;
|
||||
|
||||
DrawTextArgs args = new DrawTextArgs( "&eClassical", true );
|
||||
drawer.DrawText( logoItalicFont, ref args, xStart, 20 );
|
||||
args.Text = "&eSharp";
|
||||
drawer.DrawText( logoFont, ref args, xStart + size1.Width, 20 );
|
||||
}
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
logoFont.Dispose();
|
||||
logoItalicFont.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using ClassicalSharp;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Platform.Windows;
|
||||
using OpenTK.Platform;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public sealed class MainScreen {
|
||||
public IDrawer2D Drawer;
|
||||
public NativeWindow Window;
|
||||
|
||||
public void Init() {
|
||||
Window.Resize += HandleResize;
|
||||
Window.Mouse.Move += MouseMove;
|
||||
Window.Mouse.ButtonDown += MouseButtonDown;
|
||||
|
||||
logoFont = new Font( "Times New Roman", 28, FontStyle.Bold );
|
||||
logoItalicFont = new Font( "Times New Roman", 28, FontStyle.Italic );
|
||||
textFont = new Font( "Arial", 16, FontStyle.Bold );
|
||||
}
|
||||
|
||||
FastButtonWidget selectedWidget;
|
||||
void MouseMove( object sender, MouseMoveEventArgs e ) {
|
||||
//System.Diagnostics.Debug.Print( "moved" );
|
||||
for( int i = 0; i < widgets.Length; i++ ) {
|
||||
FastButtonWidget widget = widgets[i];
|
||||
if( e.X >= widget.X && e.Y >= widget.Y &&
|
||||
e.X < widget.X + widget.Width && e.Y < widget.Y + widget.Height ) {
|
||||
if( selectedWidget != widget && selectedWidget != null ) {
|
||||
using( IDrawer2D drawer = Drawer ) {
|
||||
drawer.SetBitmap( background );
|
||||
selectedWidget.Redraw( Drawer, selectedWidget.Text, textFont );
|
||||
FilterButton( selectedWidget.X, selectedWidget.Y,
|
||||
selectedWidget.Width, selectedWidget.Height, 180 );
|
||||
widget.Redraw( Drawer, widget.Text, textFont );
|
||||
}
|
||||
}
|
||||
selectedWidget = widget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MouseButtonDown( object sender, MouseButtonEventArgs e ) {
|
||||
if( e.Button != MouseButton.Left ) return;
|
||||
|
||||
if( selectedWidget != null && selectedWidget.OnClick != null )
|
||||
selectedWidget.OnClick();
|
||||
}
|
||||
|
||||
public void Display() {
|
||||
WinWindowInfo info = ((WinWindowInfo)Window.WindowInfo);
|
||||
IntPtr dc = info.DeviceContext;
|
||||
|
||||
|
||||
using( Graphics g = Graphics.FromHdc( dc ) ) {
|
||||
g.DrawImage( background, 0, 0, background.Width, background.Height );
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap background;
|
||||
Font textFont, logoFont, logoItalicFont;
|
||||
static FastColour clearColour = new FastColour( 30, 30, 30 );
|
||||
static uint clearColourBGRA = (uint)(new FastColour( 30, 30, 30 ).ToArgb());
|
||||
public void RecreateBackground() {
|
||||
System.Diagnostics.Debug.Print( "DISPLAY" );
|
||||
if( background != null )
|
||||
background.Dispose();
|
||||
|
||||
background = new Bitmap( Window.Width, Window.Height );
|
||||
using( IDrawer2D drawer = Drawer ) {
|
||||
drawer.SetBitmap( background );
|
||||
drawer.Clear( clearColour );
|
||||
|
||||
Size size1 = drawer.MeasureSize( "&eClassical", logoItalicFont, true );
|
||||
Size size2 = drawer.MeasureSize( "&eSharp", logoFont, true );
|
||||
int xStart = Window.Width / 2 - (size1.Width + size2.Width ) / 2;
|
||||
|
||||
DrawTextArgs args = new DrawTextArgs( "&eClassical", true );
|
||||
drawer.DrawText( logoItalicFont, ref args, xStart, 20 );
|
||||
args.Text = "&eSharp";
|
||||
drawer.DrawText( logoFont, ref args, xStart + size1.Width, 20 );
|
||||
DrawButtons( drawer );
|
||||
}
|
||||
|
||||
logoFont.Dispose();
|
||||
logoItalicFont.Dispose();
|
||||
}
|
||||
|
||||
static FastColour boxCol = new FastColour( 169, 143, 192 ), shadowCol = new FastColour( 97, 81, 110 );
|
||||
void DrawButtons( IDrawer2D drawer ) {
|
||||
widgetIndex = 0;
|
||||
MakeButtonAt( drawer, "Direct connect", Anchor.Centre, Anchor.Centre,
|
||||
buttonWidth, buttonHeight, 0, -100 );
|
||||
MakeButtonAt( drawer, "ClassiCube.net", Anchor.Centre, Anchor.Centre,
|
||||
buttonWidth, buttonHeight, 0, -50 );
|
||||
MakeButtonAt( drawer, "Default texture pack", Anchor.Centre, Anchor.Centre,
|
||||
buttonWidth, buttonHeight, 0, 50 );
|
||||
|
||||
MakeButtonAt( drawer, "Singleplayer", Anchor.LeftOrTop, Anchor.BottomOrRight,
|
||||
sideButtonWidth, buttonHeight, 10, -10 );
|
||||
widgets[widgetIndex - 1].OnClick
|
||||
= () => Program.StartClient( "default.zip" );
|
||||
MakeButtonAt( drawer, "Resume", Anchor.BottomOrRight, Anchor.BottomOrRight,
|
||||
sideButtonWidth, buttonHeight, -10, -10 );
|
||||
}
|
||||
|
||||
FastButtonWidget[] widgets = new FastButtonWidget[5];
|
||||
int widgetIndex = 0;
|
||||
const int buttonWidth = 220, buttonHeight = 35, sideButtonWidth = 150;
|
||||
void MakeButtonAt( IDrawer2D drawer, string text, Anchor horAnchor,
|
||||
Anchor verAnchor, int width, int height, int x, int y ) {
|
||||
FastButtonWidget widget = new FastButtonWidget();
|
||||
widget.Window = Window;
|
||||
widget.Text = text;
|
||||
widget.DrawAt( drawer, text, textFont, horAnchor, verAnchor, width, height, x, y );
|
||||
FilterButton( widget.X, widget.Y, widget.Width, widget.Height, 180 );
|
||||
widgets[widgetIndex++] = widget;
|
||||
}
|
||||
|
||||
void HandleResize( object sender, EventArgs e ) {
|
||||
RecreateBackground();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
logoFont.Dispose();
|
||||
logoItalicFont.Dispose();
|
||||
textFont.Dispose();
|
||||
}
|
||||
|
||||
unsafe void FilterButton( int x, int y, int width, int height, byte scale ) {
|
||||
using( FastBitmap bmp = new FastBitmap( background, true ) ) {
|
||||
for( int yy = y; yy < y + height; yy++ ) {
|
||||
int* row = bmp.GetRowPtr( yy ) + x;
|
||||
for( int xx = 0; xx < width; xx++ ) {
|
||||
uint pixel = (uint)row[xx];
|
||||
if( pixel == clearColourBGRA ) continue;
|
||||
uint a = pixel & 0xFF000000;
|
||||
uint r = (pixel >> 16) & 0xFF;
|
||||
uint g = (pixel >> 8) & 0xFF;
|
||||
uint b = pixel & 0xFF;
|
||||
|
||||
r = (r * scale) / 255;
|
||||
g = (g * scale) / 255;
|
||||
b = (b * scale) / 255;
|
||||
row[xx] = (int)(a | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using ClassicalSharp;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
@ -13,43 +11,43 @@ namespace Launcher2 {
|
||||
|
||||
[STAThread]
|
||||
private static void Main( string[] args ) {
|
||||
NativeWindow window = new NativeWindow( 480, 480, AppName, 0,
|
||||
GraphicsMode.Default, DisplayDevice.Default );
|
||||
window.Visible = true;
|
||||
if( !Debugger.IsAttached )
|
||||
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
|
||||
|
||||
MainScreen screen = new MainScreen();
|
||||
screen.Drawer = new GdiPlusDrawer2D( null );
|
||||
screen.Window = window;
|
||||
screen.Init();
|
||||
screen.RecreateBackground();
|
||||
|
||||
while( true ) {
|
||||
window.ProcessEvents();
|
||||
if( !window.Exists ) break;
|
||||
|
||||
screen.Display();
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
}
|
||||
LauncherWindow window = new LauncherWindow();
|
||||
window.Run();
|
||||
}
|
||||
|
||||
static string missingExeMessage = "Failed to start ClassicalSharp. (classicalsharp.exe was not found)"
|
||||
+ Environment.NewLine + Environment.NewLine +
|
||||
"This application is only the launcher, it is not the actual client. " +
|
||||
"Please place the launcher in the same directory as the client (classicalsharp.exe).";
|
||||
static void UnhandledException( object sender, UnhandledExceptionEventArgs e ) {
|
||||
// So we don't get the normal unhelpful crash dialog on Windows.
|
||||
Exception ex = (Exception)e.ExceptionObject;
|
||||
bool wroteToCrashLog = LogException( ex );
|
||||
string error = wroteToCrashLog ? null :
|
||||
(ex.GetType().FullName + ": " + ex.Message + Environment.NewLine + ex.StackTrace);
|
||||
|
||||
string message = wroteToCrashLog ?
|
||||
"The cause of the crash has been logged to \"crash-launcher.log\". Please consider reporting the crash " +
|
||||
"(and the circumstances that caused it) to github.com/UnknownShadow200/ClassicalSharp/issues" :
|
||||
|
||||
"Failed to write the cause of the crash to \"crash-launcher.log\". Please consider reporting the crash " +
|
||||
"(and the circumstances that caused it) to github.com/UnknownShadow200/ClassicalSharp/issues" +
|
||||
Environment.NewLine + Environment.NewLine + error;
|
||||
|
||||
MessageBox.Show( "Oh dear. ClassicalSharp has crashed." + Environment.NewLine + Environment.NewLine + message, "ClassicalSharp has crashed" );
|
||||
Environment.Exit( 1 );
|
||||
}
|
||||
|
||||
public static bool StartClient( string args ) {
|
||||
Process process = null;
|
||||
|
||||
if( !File.Exists( "ClassicalSharp.exe" ) ) {
|
||||
// TODO: show message popup
|
||||
internal static bool LogException( Exception ex ) {
|
||||
string error = ex.GetType().FullName + ": " + ex.Message + Environment.NewLine + ex.StackTrace;
|
||||
try {
|
||||
using( StreamWriter writer = new StreamWriter( "crash_launcher.log", true ) ) {
|
||||
writer.WriteLine( "Crash time: " + DateTime.Now.ToString() );
|
||||
writer.WriteLine( error );
|
||||
writer.WriteLine();
|
||||
}
|
||||
} catch( Exception ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if( Type.GetType( "Mono.Runtime" ) != null ) {
|
||||
process = Process.Start( "mono", "\"ClassicalSharp.exe\" " + args );
|
||||
} else {
|
||||
process = Process.Start( "ClassicalSharp.exe", args );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
52
Launcher2/Secure.cs
Normal file
52
Launcher2/Secure.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public static class Secure {
|
||||
|
||||
public static string Encode( string decoded, string key ) {
|
||||
if( String.IsNullOrEmpty( decoded ) || String.IsNullOrEmpty( key ) ) return "";
|
||||
|
||||
byte[] data = new byte[decoded.Length];
|
||||
for( int i = 0; i < decoded.Length; i++ )
|
||||
data[i] = (byte)decoded[i];
|
||||
|
||||
try {
|
||||
byte[] v2 = ProtectedData.Protect( data, null, DataProtectionScope.CurrentUser );
|
||||
return Convert.ToBase64String( v2 );
|
||||
} catch {
|
||||
// XORs data. *NOT* very secure, only designed to prevent reading from options.txt.
|
||||
for( int i = 0; i < data.Length; i++ )
|
||||
data[i] = (byte)(data[i] ^ key[i % key.Length] ^ 0x43);
|
||||
return Convert.ToBase64String( data );
|
||||
}
|
||||
}
|
||||
|
||||
public static string Decode( string encoded, string key ) {
|
||||
if( String.IsNullOrEmpty( encoded ) || String.IsNullOrEmpty( key ) ) return null;
|
||||
|
||||
byte[] data;
|
||||
try {
|
||||
data = Convert.FromBase64String( encoded );
|
||||
} catch( FormatException ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
data = ProtectedData.Unprotect( data, null, DataProtectionScope.CurrentUser );
|
||||
char[] c = new char[data.Length];
|
||||
for( int i = 0; i < c.Length; i++ )
|
||||
c[i] = (char)data[i];
|
||||
return new String( c );
|
||||
} catch {
|
||||
if( encoded.Length > 64 || data.Length > 64 ) return null;
|
||||
|
||||
char[] c = new char[data.Length];
|
||||
for( int i = 0; i < c.Length; i++ )
|
||||
c[i] = (char)(data[i] ^ key[i % key.Length] ^ 0x43);
|
||||
return new String( c );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user