mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-23 09:34:35 -05:00
Treat .zip as texture packs in EnvMapAppearance packets, use builds.json for determing latest builds.
This commit is contained in:
parent
3a15ef9024
commit
59d0b2da74
7 changed files with 85 additions and 80 deletions
|
@ -82,10 +82,11 @@ namespace ClassicalSharp {
|
|||
}
|
||||
|
||||
void MakeSelectionTexture() {
|
||||
int size = (int)selBlockSize;
|
||||
int y = game.Height - size;
|
||||
int hSize = (int)selBlockSize;
|
||||
int vSize = (int)Math.Floor( 23 * 2 * game.GuiScale );
|
||||
int y = game.Height - vSize;
|
||||
TextureRec rec = new TextureRec( 0, 22/256f, 24/256f, 24/256f );
|
||||
selTex = new Texture( game.GuiTexId, 0, y, size, size, rec );
|
||||
selTex = new Texture( game.GuiTexId, 0, y, hSize, vSize, rec );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -322,7 +322,9 @@ namespace ClassicalSharp {
|
|||
if( !game.AcceptedUrls.HasAccepted( url ) )
|
||||
game.AcceptedUrls.AddAccepted( url );
|
||||
|
||||
if( usingTexturePack )
|
||||
// NOTE: This is entirely against the original CPE specification, but we
|
||||
// do it here as a convenience until EnvMapAppearance v2 is more widely adopted.
|
||||
if( usingTexturePack || url.EndsWith( ".zip" ) )
|
||||
game.AsyncDownloader.DownloadData( url, true, "texturePack", lastModified );
|
||||
else
|
||||
game.AsyncDownloader.DownloadImage( url, true, "terrain", lastModified );
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Launcher2 {
|
|||
titleFont = new Font( "Arial", 16, FontStyle.Bold );
|
||||
infoFont = new Font( "Arial", 14, FontStyle.Regular );
|
||||
buttonFont = titleFont;
|
||||
widgets = new LauncherWidget[16];
|
||||
widgets = new LauncherWidget[17];
|
||||
}
|
||||
|
||||
UpdateCheckTask checkTask;
|
||||
|
@ -28,18 +28,20 @@ namespace Launcher2 {
|
|||
Resize();
|
||||
}
|
||||
|
||||
|
||||
Build dev, stable;
|
||||
public override void Tick() {
|
||||
if( checkTask != null && !checkTask.Working ) {
|
||||
if( checkTask.Exception != null ) {
|
||||
updateCheckFailed = true;
|
||||
} else {
|
||||
lastStable = DateTime.Parse( checkTask.LatestStableDate,
|
||||
null, DateTimeStyles.AssumeUniversal );
|
||||
lastDev = DateTime.Parse( checkTask.LatestDevDate,
|
||||
null, DateTimeStyles.AssumeUniversal );
|
||||
dev = checkTask.LatestDev;
|
||||
lastDev = dev.TimeBuilt;
|
||||
validDev = dev.DirectXSize > 50000 && dev.OpenGLSize > 50000;
|
||||
|
||||
validStable = Int32.Parse( checkTask.LatestStableSize ) > 50000;
|
||||
validDev = Int32.Parse( checkTask.LatestDevSize ) > 50000;
|
||||
stable = checkTask.LatestStable;
|
||||
lastStable = stable.TimeBuilt;
|
||||
validStable = stable.DirectXSize > 50000 && stable.OpenGLSize > 50000;
|
||||
}
|
||||
checkTask = null;
|
||||
game.MakeBackground();
|
||||
|
@ -64,22 +66,24 @@ namespace Launcher2 {
|
|||
widgetIndex = 0;
|
||||
|
||||
MakeLabelAt( "Your build:", titleFont, Anchor.Centre, Anchor.Centre, -55, -120 );
|
||||
string yourBuild = File.GetLastWriteTimeUtc( "ClassicalSharp.exe" ).ToString( dateFormat );
|
||||
string yourBuild = File.GetLastWriteTime( "ClassicalSharp.exe" ).ToString( dateFormat );
|
||||
MakeLabelAt( yourBuild, infoFont, Anchor.Centre, Anchor.Centre, 100, -120 );
|
||||
|
||||
MakeLabelAt( "Latest stable:", titleFont, Anchor.Centre, Anchor.Centre, -70, -80 );
|
||||
string latestStable = GetDateString( lastStable, validStable );
|
||||
MakeLabelAt( latestStable, infoFont, Anchor.Centre, Anchor.Centre, 100, -80 );
|
||||
MakeButtonAt( "Update to stable", 180, 30, titleFont, Anchor.Centre, 0, -40,
|
||||
(x, y) => UpdateBuild( lastStable, validStable, "latest.Release.zip" ) );
|
||||
MakeButtonAt( "Update to D3D9 stable", 260, 30, titleFont, Anchor.Centre, 0, -40,
|
||||
(x, y) => UpdateBuild( lastStable, validStable, true, true ) );
|
||||
MakeButtonAt( "Update to OpenGL stable", 260, 30, titleFont, Anchor.Centre, 0, 0,
|
||||
(x, y) => UpdateBuild( lastStable, validStable, true, false ) );
|
||||
|
||||
MakeLabelAt( "Latest dev:", titleFont, Anchor.Centre, Anchor.Centre, -60, 40 );
|
||||
string latestDev = GetDateString( lastDev, validDev );
|
||||
MakeLabelAt( latestDev, infoFont, Anchor.Centre, Anchor.Centre, 100, 40 );
|
||||
MakeButtonAt( "Update to OpenGL dev", 240, 30, titleFont, Anchor.Centre, 0, 80,
|
||||
(x, y) => UpdateBuild( lastDev, validDev, "latest.zip" ) );
|
||||
MakeButtonAt( "Update to D3D9 dev", 240, 30, titleFont, Anchor.Centre, 0, 120,
|
||||
(x, y) => UpdateBuild( lastDev, validDev, "latest.DirectX.zip" ) );
|
||||
MakeButtonAt( "Update to D3D9 dev", 240, 30, titleFont, Anchor.Centre, 0, 80,
|
||||
(x, y) => UpdateBuild( lastDev, validDev, false, true ) );
|
||||
MakeButtonAt( "Update to OpenGL dev", 240, 30, titleFont, Anchor.Centre, 0, 120,
|
||||
(x, y) => UpdateBuild( lastDev, validDev, false, false ) );
|
||||
|
||||
MakeButtonAt( "Back", 80, 35, titleFont, Anchor.Centre,
|
||||
0, 200, (x, y) => game.SetScreen( new MainScreen( game ) ) );
|
||||
|
@ -90,11 +94,15 @@ namespace Launcher2 {
|
|||
if( !valid ) return "Build corrupted";
|
||||
if( last == DateTime.MinValue ) return "Checking..";
|
||||
|
||||
return last.ToUniversalTime().ToString( dateFormat );
|
||||
return last.ToString( dateFormat );
|
||||
}
|
||||
|
||||
void UpdateBuild( DateTime last, bool valid, string dir ) {
|
||||
void UpdateBuild( DateTime last, bool valid, bool release, bool dx ) {
|
||||
if( last == DateTime.MinValue || !valid ) return;
|
||||
|
||||
Build build = release ? stable : dev;
|
||||
string dir = dx ? build.DirectXPath : build.OpenGLPath;
|
||||
Console.WriteLine( "FETCH! " + dir );
|
||||
Patcher.Update( dir );
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
|
||||
<StartAction>Project</StartAction>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="SharpWave">
|
||||
|
|
|
@ -162,7 +162,7 @@ namespace Launcher2 {
|
|||
static int GetLastIndexOfNumber( string json, int index ) {
|
||||
int lastIndex = index;
|
||||
for( ; lastIndex < json.Length; lastIndex++ ) {
|
||||
if( "0123456789+-".IndexOf( json[lastIndex] ) == -1 )
|
||||
if( "0123456789+-.".IndexOf( json[lastIndex] ) == -1 )
|
||||
break;
|
||||
}
|
||||
return lastIndex - 1;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using JsonObject = System.Collections.Generic.Dictionary<string, object>;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
|
@ -56,8 +57,7 @@ namespace Launcher2 {
|
|||
var swGet = System.Diagnostics.Stopwatch.StartNew();
|
||||
string getResponse = GetHtmlAll( loginUri, classicubeNetUri );
|
||||
int index = 0; bool success = true;
|
||||
Dictionary<string, object> data =
|
||||
(Dictionary<string, object>)Json.ParseValue( getResponse, ref index, ref success );
|
||||
JsonObject data = (JsonObject)Json.ParseValue( getResponse, ref index, ref success );
|
||||
string token = (string)data["token"];
|
||||
|
||||
// Step 2: POST to login page with csrf token.
|
||||
|
@ -72,7 +72,7 @@ namespace Launcher2 {
|
|||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
string response = PostHtmlAll( loginUri, loginUri, loginData );
|
||||
index = 0; success = true;
|
||||
data = (Dictionary<string, object>)Json.ParseValue( response, ref index, ref success );
|
||||
data = (JsonObject)Json.ParseValue( response, ref index, ref success );
|
||||
|
||||
List<object> errors = (List<object>)data["errors"];
|
||||
if( errors.Count > 0 || (data.ContainsKey( "username" ) && data["username"] == null) )
|
||||
|
@ -88,13 +88,12 @@ namespace Launcher2 {
|
|||
string response = GetHtmlAll( uri, classicubeNetUri );
|
||||
|
||||
int index = 0; bool success = true;
|
||||
Dictionary<string, object> root =
|
||||
(Dictionary<string, object>)Json.ParseValue( response, ref index, ref success );
|
||||
JsonObject root = (JsonObject)Json.ParseValue( response, ref index, ref success );
|
||||
List<object> list = (List<object>)root["servers"];
|
||||
|
||||
Dictionary<string, object> pairs = (Dictionary<string, object>)list[0];
|
||||
return new ClientStartData( Username, (string)pairs["mppass"],
|
||||
(string)pairs["ip"], (string)pairs["port"] );
|
||||
JsonObject obj = (JsonObject)list[0];
|
||||
return new ClientStartData( Username, (string)obj["mppass"],
|
||||
(string)obj["ip"], (string)obj["port"] );
|
||||
}
|
||||
|
||||
public List<ServerListEntry> GetPublicServers() {
|
||||
|
@ -102,17 +101,16 @@ namespace Launcher2 {
|
|||
List<ServerListEntry> servers = new List<ServerListEntry>();
|
||||
string response = GetHtmlAll( publicServersUri, classicubeNetUri );
|
||||
int index = 0; bool success = true;
|
||||
Dictionary<string, object> root =
|
||||
(Dictionary<string, object>)Json.ParseValue( response, ref index, ref success );
|
||||
JsonObject root = (JsonObject)Json.ParseValue( response, ref index, ref success );
|
||||
List<object> list = (List<object>)root["servers"];
|
||||
|
||||
foreach( object server in list ) {
|
||||
Dictionary<string, object> pairs = (Dictionary<string, object>)server;
|
||||
JsonObject obj = (JsonObject)server;
|
||||
servers.Add( new ServerListEntry(
|
||||
(string)pairs["hash"], (string)pairs["name"],
|
||||
(string)pairs["players"], (string)pairs["maxplayers"],
|
||||
(string)pairs["uptime"], (string)pairs["mppass"],
|
||||
(string)pairs["ip"], (string)pairs["port"] ) );
|
||||
(string)obj["hash"], (string)obj["name"],
|
||||
(string)obj["players"], (string)obj["maxplayers"],
|
||||
(string)obj["uptime"], (string)obj["mppass"],
|
||||
(string)obj["ip"], (string)obj["port"] ) );
|
||||
}
|
||||
Log( "cc servers took " + sw.ElapsedMilliseconds );
|
||||
sw.Stop();
|
||||
|
|
|
@ -1,22 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using JsonObject = System.Collections.Generic.Dictionary<string, object>;
|
||||
|
||||
namespace Launcher2 {
|
||||
|
||||
public class Build {
|
||||
public DateTime TimeBuilt;
|
||||
public string DirectXPath, OpenGLPath;
|
||||
public int DirectXSize, OpenGLSize;
|
||||
}
|
||||
|
||||
public sealed class UpdateCheckTask : IWebTask {
|
||||
|
||||
public const string UpdatesUri = "http://cs.classicube.net/";
|
||||
StringComparison ordinal = StringComparison.Ordinal;
|
||||
|
||||
public string LatestStableDate, LatestStableSize;
|
||||
public string LatestDevDate, LatestDevSize;
|
||||
public const string BuildsUri = "http://cs.classicube.net/builds.json";
|
||||
public Build LatestDev, LatestStable;
|
||||
|
||||
public void CheckForUpdatesAsync() {
|
||||
Working = true;
|
||||
Exception = null;
|
||||
LatestStableDate = null; LatestStableSize = null;
|
||||
LatestDevDate = null; LatestDevSize = null;
|
||||
LatestDev = null;
|
||||
LatestStable = null;
|
||||
|
||||
Thread thread = new Thread( UpdateWorker, 256 * 1024 );
|
||||
thread.Name = "Launcher.UpdateCheck";
|
||||
|
@ -33,46 +39,35 @@ namespace Launcher2 {
|
|||
}
|
||||
|
||||
void CheckUpdates() {
|
||||
var response = GetHtml( UpdatesUri, UpdatesUri );
|
||||
foreach( string line in response ) {
|
||||
if( line.StartsWith( @"<a href=""latest.", ordinal ) ) {
|
||||
int index = 0;
|
||||
string text = line.Substring( @"<a href=""".Length );
|
||||
|
||||
string buildName = ReadToken( text, ref index );
|
||||
string date = ReadToken( text, ref index );
|
||||
string time = ReadToken( text, ref index );
|
||||
string buildSize = ReadToken( text, ref index );
|
||||
|
||||
if( buildName.Contains( "latest.zip" ) ) {
|
||||
LatestDevDate = date + " " + time;
|
||||
LatestDevSize = buildSize;
|
||||
} else if( buildName.Contains( "latest.Release.zip" ) ) {
|
||||
LatestStableDate = date + " " + time;
|
||||
LatestStableSize = buildSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
string response = GetHtmlAll( BuildsUri, UpdatesUri );
|
||||
int index = 0; bool success = true;
|
||||
JsonObject data = (JsonObject)Json.ParseValue( response, ref index, ref success );
|
||||
|
||||
JsonObject devBuild = (JsonObject)data["latest"];
|
||||
JsonObject releaseBuilds = (JsonObject)data["releases"];
|
||||
LatestDev = MakeBuild( devBuild, false );
|
||||
Build[] stableBuilds = new Build[releaseBuilds.Count];
|
||||
|
||||
int i = 0;
|
||||
foreach( KeyValuePair<string, object> pair in releaseBuilds )
|
||||
stableBuilds[i++] = MakeBuild( (JsonObject)pair.Value, true );
|
||||
Array.Sort<Build>( stableBuilds,
|
||||
(a, b) => b.TimeBuilt.CompareTo( a.TimeBuilt ) );
|
||||
LatestStable = stableBuilds[0];
|
||||
}
|
||||
|
||||
string ReadToken( string value, ref int index ) {
|
||||
int start = index;
|
||||
int wordEnd = -1;
|
||||
for( ; index < value.Length; index++ ) {
|
||||
if( value[index] == ' ' ) {
|
||||
// found end of this word
|
||||
if( wordEnd == -1 )
|
||||
wordEnd = index;
|
||||
} else {
|
||||
// found start of next word
|
||||
if( wordEnd != -1 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
static readonly DateTime epoch = new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc );
|
||||
Build MakeBuild( JsonObject obj, bool release ) {
|
||||
Build build = new Build();
|
||||
string timeKey = release ? "release_ts" : "ts";
|
||||
double rawTime = Double.Parse( (string)obj[timeKey] );
|
||||
build.TimeBuilt = epoch.AddSeconds( rawTime ).ToLocalTime();
|
||||
|
||||
if( wordEnd == -1 )
|
||||
wordEnd = value.Length;
|
||||
return value.Substring( start, wordEnd - start );
|
||||
}
|
||||
build.DirectXSize = Int32.Parse( (string)obj["dx_size"] );
|
||||
build.DirectXPath = (string)obj["dx_file"];
|
||||
build.OpenGLSize = Int32.Parse( (string)obj["ogl_size"] );
|
||||
build.OpenGLPath = (string)obj["ogl_file"];
|
||||
return build;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue