mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-23 01:21:57 -05:00
225 lines
6.8 KiB
C#
225 lines
6.8 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Reflection;
|
|
using System.Threading;
|
|
using ClassicalSharp;
|
|
using ClassicalSharp.Network;
|
|
using Launcher.Gui.Screens;
|
|
using Launcher.Patcher;
|
|
using Launcher.Web;
|
|
using OpenTK;
|
|
using OpenTK.Graphics;
|
|
using OpenTK.Input;
|
|
|
|
namespace Launcher {
|
|
|
|
public sealed partial class LauncherWindow {
|
|
|
|
/// <summary> Underlying native window instance. </summary>
|
|
public NativeWindow Window;
|
|
|
|
/// <summary> Platform specific class used to draw 2D elements,
|
|
/// such as text, rounded rectangles and lines. </summary>
|
|
public IDrawer2D Drawer;
|
|
|
|
/// <summary> Currently active screen. </summary>
|
|
public LauncherScreen Screen;
|
|
|
|
/// <summary> Whether the client drawing area needs to be redrawn/presented to the screen. </summary>
|
|
public bool Dirty;
|
|
|
|
/// <summary> Currently active logged in session with classicube.net. </summary>
|
|
public ClassicubeSession Session = new ClassicubeSession();
|
|
|
|
/// <summary> Queue used to download resources asynchronously. </summary>
|
|
public AsyncDownloader Downloader;
|
|
|
|
/// <summary> Returns the width of the client drawing area. </summary>
|
|
public int Width { get { return Window.Width; } }
|
|
|
|
/// <summary> Returns the height of the client drawing area. </summary>
|
|
public int Height { get { return Window.Height; } }
|
|
|
|
/// <summary> Bitmap that contains the entire array of pixels that describe the client drawing area. </summary>
|
|
public Bitmap Framebuffer;
|
|
|
|
/// <summary> Whether at the next tick, the launcher window should proceed to stop displaying frames and subsequently exit. </summary>
|
|
public bool ShouldExit;
|
|
public bool ShouldUpdate;
|
|
|
|
public string FontName = "Arial";
|
|
|
|
public bool Minimised {
|
|
get { return Window.WindowState == WindowState.Minimized || (Width == 1 && Height == 1); }
|
|
}
|
|
|
|
/// <summary> Contains metadata attached for different screen instances,
|
|
/// typically used to save 'last text entered' text when a screen is disposed. </summary>
|
|
public Dictionary<string, Dictionary<string, object>> ScreenMetadata =
|
|
new Dictionary<string, Dictionary<string, object>>();
|
|
|
|
internal ResourceFetcher fetcher;
|
|
internal UpdateCheckTask checkTask;
|
|
|
|
Font logoFont;
|
|
PlatformDrawer platformDrawer;
|
|
public void Init() {
|
|
Window.Resize += Resize;
|
|
Window.FocusedChanged += FocusedChanged;
|
|
Window.WindowStateChanged += Resize;
|
|
Window.Keyboard.KeyDown += KeyDown;
|
|
LoadFont();
|
|
logoFont = new Font( FontName, 32, FontStyle.Regular );
|
|
string path = Assembly.GetExecutingAssembly().Location;
|
|
Window.Icon = Icon.ExtractAssociatedIcon( path );
|
|
//Minimised = Window.WindowState == WindowState.Minimized;
|
|
|
|
if( Configuration.RunningOnWindows )
|
|
platformDrawer = new WinPlatformDrawer();
|
|
else if( Configuration.RunningOnX11 )
|
|
platformDrawer = new X11PlatformDrawer();
|
|
else if( Configuration.RunningOnMacOS )
|
|
platformDrawer = new OSXPlatformDrawer();
|
|
}
|
|
|
|
void LoadFont() {
|
|
Options.Load();
|
|
FontName = Options.Get( "gui-fontname" ) ?? "Arial";
|
|
try {
|
|
using( Font f = new Font( FontName, 16 ) ) { }
|
|
} catch( Exception ) {
|
|
FontName = "Arial";
|
|
Options.Set( "gui-fontname", "Arial" );
|
|
}
|
|
}
|
|
|
|
void FocusedChanged( object sender, EventArgs e ) {
|
|
if( Program.ShowingErrorDialog ) return;
|
|
MakeBackground();
|
|
Screen.Resize();
|
|
}
|
|
|
|
void Resize( object sender, EventArgs e ) {
|
|
platformDrawer.Resize( Window.WindowInfo );
|
|
MakeBackground();
|
|
Screen.Resize();
|
|
}
|
|
|
|
public void SetScreen( LauncherScreen screen ) {
|
|
if( this.Screen != null )
|
|
this.Screen.Dispose();
|
|
|
|
MakeBackground();
|
|
this.Screen = screen;
|
|
screen.Init();
|
|
}
|
|
|
|
public bool ConnectToServer( List<ServerListEntry> publicServers, string hash ) {
|
|
if( String.IsNullOrEmpty( hash ) ) return false;
|
|
|
|
ClientStartData data = null;
|
|
foreach( ServerListEntry entry in publicServers ) {
|
|
if( entry.Hash == hash ) {
|
|
data = new ClientStartData( Session.Username, entry.Mppass,
|
|
entry.IPAddress, entry.Port );
|
|
Client.Start( data, true, ref ShouldExit );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Fallback to private server handling
|
|
try {
|
|
data = Session.GetConnectInfo( hash );
|
|
} catch( WebException ex ) {
|
|
ErrorHandler.LogError( "retrieving server information", ex );
|
|
return false;
|
|
} catch( ArgumentOutOfRangeException ) {
|
|
return false;
|
|
}
|
|
Client.Start( data, true, ref ShouldExit );
|
|
return true;
|
|
}
|
|
|
|
public void Run() {
|
|
Window = new NativeWindow( 640, 400, Program.AppName, 0,
|
|
GraphicsMode.Default, DisplayDevice.Default );
|
|
Window.Visible = true;
|
|
Drawer = new GdiPlusDrawer2D( null );
|
|
Init();
|
|
TryLoadTexturePack();
|
|
platformDrawer.Init( Window.WindowInfo );
|
|
|
|
string audioPath = Path.Combine( Program.AppDirectory, "audio" );
|
|
BinUnpacker.Unpack( audioPath, "dig" );
|
|
BinUnpacker.Unpack( audioPath, "step" );
|
|
|
|
fetcher = new ResourceFetcher();
|
|
fetcher.CheckResourceExistence();
|
|
checkTask = new UpdateCheckTask();
|
|
checkTask.CheckForUpdatesAsync();
|
|
if( !fetcher.AllResourcesExist )
|
|
SetScreen( new ResourcesScreen( this ) );
|
|
else
|
|
SetScreen( new MainScreen( this ) );
|
|
|
|
while( true ) {
|
|
Window.ProcessEvents();
|
|
if( !Window.Exists ) break;
|
|
if( ShouldExit ) {
|
|
if( Screen != null )
|
|
Screen.Dispose();
|
|
break;
|
|
}
|
|
|
|
Screen.Tick();
|
|
if( Dirty || Screen.Dirty )
|
|
Display();
|
|
Thread.Sleep( 1 );
|
|
}
|
|
|
|
if( Options.Load() ) {
|
|
LauncherSkin.SaveToOptions();
|
|
Options.Save();
|
|
}
|
|
|
|
if( ShouldUpdate )
|
|
Updater.Applier.ApplyUpdate();
|
|
if( Window.Exists )
|
|
Window.Close();
|
|
}
|
|
|
|
void Display() {
|
|
Screen.OnDisplay();
|
|
Dirty = false;
|
|
Screen.Dirty = false;
|
|
platformDrawer.Display( Window.WindowInfo, Framebuffer );
|
|
}
|
|
|
|
Key lastKey;
|
|
void KeyDown( object sender, KeyboardKeyEventArgs e ) {
|
|
if( IsShutdown( e.Key ) )
|
|
ShouldExit = true;
|
|
lastKey = e.Key;
|
|
}
|
|
|
|
public void Dispose() {
|
|
Window.Resize -= Resize;
|
|
Window.FocusedChanged -= FocusedChanged;
|
|
Window.WindowStateChanged -= Resize;
|
|
Window.Keyboard.KeyDown -= KeyDown;
|
|
logoFont.Dispose();
|
|
}
|
|
|
|
bool IsShutdown( Key key ) {
|
|
if( key == Key.F4 && (lastKey == Key.AltLeft || lastKey == Key.AltRight) )
|
|
return true;
|
|
// On OSX, Cmd+Q should also terminate the process.
|
|
if( !OpenTK.Configuration.RunningOnMacOS ) return false;
|
|
return key == Key.Q && (lastKey == Key.WinLeft || lastKey == Key.WinRight);
|
|
}
|
|
}
|
|
}
|