mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 11:06:06 -04:00
Simplify and modularise AsyncDownloader, remove duplicate entity spwaning code, remove EntityInfoChange event (broken, as it didn't change the in game entity display name)
This commit is contained in:
parent
12bcf5d335
commit
714f03e893
@ -43,7 +43,6 @@ namespace ClassicalSharp {
|
||||
SortPlayerInfo();
|
||||
Window.EntityAdded += PlayerSpawned;
|
||||
Window.EntityRemoved += PlayerDespawned;
|
||||
Window.EntityInfoChanged += PlayerInfoChanged;
|
||||
}
|
||||
|
||||
public override void Render( double delta ) {
|
||||
@ -62,7 +61,6 @@ namespace ClassicalSharp {
|
||||
}
|
||||
Window.EntityAdded -= PlayerSpawned;
|
||||
Window.EntityRemoved -= PlayerDespawned;
|
||||
Window.EntityInfoChanged -= PlayerInfoChanged;
|
||||
}
|
||||
|
||||
void PlayerSpawned( object sender, IdEventArgs e ) {
|
||||
@ -84,18 +82,6 @@ namespace ClassicalSharp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerInfoChanged( object sender, IdEventArgs e ) {
|
||||
for( int i = 0; i < info.Count; i++ ) {
|
||||
PlayerInfo pInfo = info[i];
|
||||
if( pInfo.PlayerId == e.Id ) {
|
||||
GraphicsApi.DeleteTexture( ref pInfo.Texture );
|
||||
info[i] = new PlayerInfo( GraphicsApi, Window.NetPlayers[e.Id], font );
|
||||
SortPlayerInfo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateInitialPlayerInfo() {
|
||||
for( int i = 0; i < Window.NetPlayers.Length; i++ ) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenTK;
|
||||
using ClassicalSharp.Network;
|
||||
using ClassicalSharp.Model;
|
||||
using ClassicalSharp.Renderers;
|
||||
|
||||
@ -105,9 +106,10 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
protected void CheckSkin() {
|
||||
Bitmap bmp;
|
||||
Window.AsyncDownloader.TryGetImage( "skin_" + SkinName, out bmp );
|
||||
if( bmp != null ) {
|
||||
DownloadedItem item;
|
||||
Window.AsyncDownloader.TryGetItem( "skin_" + SkinName, out item );
|
||||
if( item != null && item.Bmp != null ) {
|
||||
Bitmap bmp = item.Bmp;
|
||||
Window.Graphics.DeleteTexture( renderer.TextureId );
|
||||
renderer.TextureId = Window.Graphics.LoadTexture( bmp );
|
||||
SkinType = Utils.GetSkinType( bmp );
|
||||
|
@ -9,10 +9,6 @@ namespace ClassicalSharp {
|
||||
/// <summary> Raised when a player is spawned in the current world. </summary>
|
||||
public event EventHandler<IdEventArgs> EntityAdded;
|
||||
|
||||
/// <summary> Raised when information(display name and/or skin name) is changed about a player. </summary>
|
||||
/// <remarks> Note this event is only raised when using the CPE player list extension. </remarks>
|
||||
public event EventHandler<IdEventArgs> EntityInfoChanged;
|
||||
|
||||
/// <summary> Raised when a player is despawned from the current world. </summary>
|
||||
public event EventHandler<IdEventArgs> EntityRemoved;
|
||||
|
||||
@ -55,11 +51,6 @@ namespace ClassicalSharp {
|
||||
RaiseEvent( EntityAdded, e );
|
||||
}
|
||||
|
||||
internal void RaiseEntityInfoChange( byte id ) {
|
||||
IdEventArgs e = new IdEventArgs( id );
|
||||
RaiseEvent( EntityInfoChanged, e );
|
||||
}
|
||||
|
||||
internal void RaiseEntityRemoved( byte id ) {
|
||||
IdEventArgs e = new IdEventArgs( id );
|
||||
RaiseEvent( EntityRemoved, e );
|
||||
|
@ -15,76 +15,38 @@ namespace ClassicalSharp.Network {
|
||||
readonly object requestLocker = new object();
|
||||
List<DownloadRequest> requests = new List<DownloadRequest>();
|
||||
readonly object downloadedLocker = new object();
|
||||
Dictionary<string, DownloadedRequest> downloaded = new Dictionary<string, DownloadedRequest>();
|
||||
Dictionary<string, DownloadedItem> downloaded = new Dictionary<string, DownloadedItem>();
|
||||
string skinServer = null;
|
||||
|
||||
public AsyncDownloader( string skinServer ) {
|
||||
this.skinServer = skinServer;
|
||||
client = new WebClient();
|
||||
client.Proxy = null;
|
||||
|
||||
worker = new Thread( DownloadThreadWorker );
|
||||
worker.Name = "ClassicalSharp.ImageDownloader";
|
||||
worker.IsBackground = true;
|
||||
worker.Start();
|
||||
}
|
||||
|
||||
class DownloadedRequest {
|
||||
|
||||
public Bitmap Bmp;
|
||||
public string Page;
|
||||
public DateTime Timestamp;
|
||||
|
||||
public DownloadedRequest( Bitmap bmp, string page ) {
|
||||
Bmp = bmp;
|
||||
Page = page;
|
||||
Timestamp = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
class DownloadRequest {
|
||||
|
||||
public string Url;
|
||||
public string Identifier;
|
||||
public bool IsImage;
|
||||
|
||||
public DownloadRequest( string url, string identifier, bool isImage ) {
|
||||
Url = url;
|
||||
Identifier = identifier;
|
||||
IsImage = isImage;
|
||||
}
|
||||
}
|
||||
|
||||
public void DownloadSkin( string skinName ) {
|
||||
string strippedSkinName = Utils.StripColours( skinName );
|
||||
string url = skinServer + strippedSkinName + ".png";
|
||||
DownloadImage( url, false, "skin_" + strippedSkinName );
|
||||
string url = Utils.IsUrl( skinName ) ? skinName :
|
||||
skinServer + strippedSkinName + ".png";
|
||||
AddRequestToQueue( url, true, "skin_" + strippedSkinName, true );
|
||||
}
|
||||
|
||||
/// <summary> Downloads an image, asynchronously, from the specified url. </summary>
|
||||
/// <param name="url"> URL the image is located at. </param>
|
||||
/// <param name="priority"> If this is true, the request is added straight to the
|
||||
/// start of the requests queue. (otherwise added to the end)</param>
|
||||
/// <param name="identifier"> Unique identifier for the image. (e.g. skin_test)</param>
|
||||
public void DownloadImage( string url, bool priority, string identifier ) {
|
||||
lock( requestLocker ) {
|
||||
DownloadRequest request = new DownloadRequest( url, identifier, true );
|
||||
if( priority ) {
|
||||
requests.Insert( 0, request );
|
||||
} else {
|
||||
requests.Add( request );
|
||||
}
|
||||
}
|
||||
handle.Set();
|
||||
AddRequestToQueue( url, priority, identifier, true );
|
||||
}
|
||||
|
||||
/// <summary> Downloads a page, asynchronously, from the specified url. </summary>
|
||||
/// <param name="url"> URL the image is located at. </param>
|
||||
/// <param name="priority"> If this is true, the request is added straight to the
|
||||
/// start of the requests queue. (otherwise added to the end)</param>
|
||||
/// <param name="identifier"> Unique identifier for the image. (e.g. skin_test)</param>
|
||||
public void DownloadPage( string url, bool priority, string identifier ) {
|
||||
AddRequestToQueue( url, priority, identifier, false );
|
||||
}
|
||||
|
||||
void AddRequestToQueue( string url, bool priority, string identifier, bool image ) {
|
||||
lock( requestLocker ) {
|
||||
DownloadRequest request = new DownloadRequest( url, identifier, false );
|
||||
DownloadRequest request = new DownloadRequest( url, identifier, image );
|
||||
if( priority ) {
|
||||
requests.Insert( 0, request );
|
||||
} else {
|
||||
@ -105,54 +67,35 @@ namespace ClassicalSharp.Network {
|
||||
client.Dispose();
|
||||
}
|
||||
|
||||
/// <summary> Removes all entries from the downloaded images queue that are
|
||||
/// older (relative to the current time) than the given number of seconds. </summary>
|
||||
public void PurgeOldEntries( int seconds ) {
|
||||
lock( downloadedLocker ) {
|
||||
DateTime now = DateTime.UtcNow;
|
||||
List<string> requestsToRemove = new List<string>( downloaded.Count );
|
||||
List<string> itemsToRemove = new List<string>( downloaded.Count );
|
||||
|
||||
foreach( var item in downloaded ) {
|
||||
DateTime timestamp = item.Value.Timestamp;
|
||||
DateTime timestamp = item.Value.TimeDownloaded;
|
||||
if( ( now - timestamp ).TotalSeconds > seconds ) {
|
||||
requestsToRemove.Add( item.Key );
|
||||
itemsToRemove.Add( item.Key );
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = 0; i < requestsToRemove.Count; i++ ) {
|
||||
string key = requestsToRemove[i];
|
||||
DownloadedRequest req;
|
||||
downloaded.TryGetValue( key, out req );
|
||||
for( int i = 0; i < itemsToRemove.Count; i++ ) {
|
||||
string key = itemsToRemove[i];
|
||||
DownloadedItem item;
|
||||
downloaded.TryGetValue( key, out item );
|
||||
downloaded.Remove( key );
|
||||
if( req.Bmp != null ) {
|
||||
req.Bmp.Dispose();
|
||||
if( item.Bmp != null ) {
|
||||
item.Bmp.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetImage( string identifier, out Bitmap bmp ) {
|
||||
public bool TryGetItem( string identifier, out DownloadedItem item ) {
|
||||
bool success = false;
|
||||
bmp = null;
|
||||
DownloadedRequest req;
|
||||
lock( downloadedLocker ) {
|
||||
success = downloaded.TryGetValue( identifier, out req );
|
||||
success = downloaded.TryGetValue( identifier, out item );
|
||||
if( success ) {
|
||||
bmp = req.Bmp;
|
||||
downloaded.Remove( identifier );
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public bool TryGetPage( string identifier, out string page ) {
|
||||
bool success = false;
|
||||
page = null;
|
||||
DownloadedRequest req;
|
||||
lock( downloadedLocker ) {
|
||||
success = downloaded.TryGetValue( identifier, out req );
|
||||
if( success ) {
|
||||
page = req.Page;
|
||||
downloaded.Remove( identifier );
|
||||
}
|
||||
}
|
||||
@ -167,53 +110,85 @@ namespace ClassicalSharp.Network {
|
||||
if( requests.Count > 0 ) {
|
||||
request = requests[0];
|
||||
requests.RemoveAt( 0 );
|
||||
if( request == null ) return;
|
||||
if( request == null )
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( request != null ) {
|
||||
string url = request.Url;
|
||||
bool isImage = request.IsImage;
|
||||
Utils.LogDebug( "Downloading " + ( isImage ? "image" : "page" ) + " from: " + url );
|
||||
Bitmap bmp = null;
|
||||
string page = null;
|
||||
|
||||
try {
|
||||
if( isImage ) {
|
||||
bmp = DownloadImage( request.Url, client );
|
||||
} else {
|
||||
page = DownloadPage( request.Url, client );
|
||||
}
|
||||
Utils.LogDebug( "Downloaded from: " + request.Url );
|
||||
} catch( Exception ex ) {
|
||||
if( !( ex is WebException || ex is ArgumentException ) ) throw;
|
||||
bmp = null;
|
||||
page = null;
|
||||
Utils.LogDebug( "Failed to download from: " + request.Url );
|
||||
}
|
||||
|
||||
lock( downloadedLocker ) {
|
||||
DownloadedRequest old;
|
||||
if( downloaded.TryGetValue( request.Identifier, out old ) ) {
|
||||
Utils.LogDebug( "{0} is already in the queue, replacing it..", request.Identifier );
|
||||
if( old.Bmp != null ) old.Bmp.Dispose();
|
||||
}
|
||||
downloaded[request.Identifier] = new DownloadedRequest( bmp, page );
|
||||
}
|
||||
DownloadItem( request );
|
||||
} else {
|
||||
handle.WaitOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Bitmap DownloadImage( string uri, WebClient client ) {
|
||||
byte[] data = client.DownloadData( uri );
|
||||
using( MemoryStream stream = new MemoryStream( data ) ) {
|
||||
return new Bitmap( stream );
|
||||
void DownloadItem( DownloadRequest request ) {
|
||||
string url = request.Url;
|
||||
bool isImage = request.IsImage;
|
||||
Utils.LogDebug( "Downloading " + ( isImage ? "image" : "page" ) + " from: " + url );
|
||||
Bitmap bmp = null;
|
||||
string page = null;
|
||||
|
||||
try {
|
||||
if( isImage ) {
|
||||
byte[] data = client.DownloadData( url );
|
||||
using( MemoryStream stream = new MemoryStream( data ) ) {
|
||||
bmp = new Bitmap( stream );
|
||||
}
|
||||
} else {
|
||||
page = client.DownloadString( url );
|
||||
}
|
||||
Utils.LogDebug( "Downloaded from: " + request.Url );
|
||||
} catch( Exception ex ) {
|
||||
if( !( ex is WebException || ex is ArgumentException ) ) throw;
|
||||
Utils.LogDebug( "Failed to download from: " + request.Url );
|
||||
}
|
||||
|
||||
lock( downloadedLocker ) {
|
||||
DownloadedItem oldItem;
|
||||
DownloadedItem newItem = new DownloadedItem( bmp, page, request.TimeAdded );
|
||||
|
||||
if( downloaded.TryGetValue( request.Identifier, out oldItem ) ) {
|
||||
if( oldItem.TimeAdded > newItem.TimeAdded ) {
|
||||
DownloadedItem old = oldItem;
|
||||
oldItem = newItem;
|
||||
newItem = old;
|
||||
}
|
||||
|
||||
if( oldItem.Bmp != null )
|
||||
oldItem.Bmp.Dispose();
|
||||
}
|
||||
downloaded[request.Identifier] = newItem;
|
||||
}
|
||||
}
|
||||
|
||||
static string DownloadPage( string uri, WebClient client ) {
|
||||
return client.DownloadString( uri );
|
||||
class DownloadRequest {
|
||||
|
||||
public string Url;
|
||||
public string Identifier;
|
||||
public bool IsImage;
|
||||
public DateTime TimeAdded;
|
||||
|
||||
public DownloadRequest( string url, string identifier, bool isImage ) {
|
||||
Url = url;
|
||||
Identifier = identifier;
|
||||
IsImage = isImage;
|
||||
TimeAdded = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DownloadedItem {
|
||||
|
||||
public Bitmap Bmp;
|
||||
public string Page;
|
||||
public DateTime TimeAdded, TimeDownloaded;
|
||||
|
||||
public DownloadedItem( Bitmap bmp, string page, DateTime timeAdded ) {
|
||||
Bmp = bmp;
|
||||
Page = page;
|
||||
TimeAdded = timeAdded;
|
||||
TimeDownloaded = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using ClassicalSharp.Network;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
@ -65,10 +66,10 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
void CheckForNewTerrainAtlas() {
|
||||
Bitmap bmp;
|
||||
Window.AsyncDownloader.TryGetImage( "terrain", out bmp );
|
||||
if( bmp != null ) {
|
||||
Window.ChangeTerrainAtlas( bmp );
|
||||
DownloadedItem item;
|
||||
Window.AsyncDownloader.TryGetItem( "terrain", out item );
|
||||
if( item != null && item.Bmp != null ) {
|
||||
Window.ChangeTerrainAtlas( item.Bmp );
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,7 +354,7 @@ namespace ClassicalSharp {
|
||||
{
|
||||
byte entityId = reader.ReadUInt8();
|
||||
string name = reader.ReadString();
|
||||
AddEntity( entityId, name, name );
|
||||
AddEntity( entityId, name, name, true );
|
||||
} break;
|
||||
|
||||
case PacketId.EntityTeleport:
|
||||
@ -494,18 +495,7 @@ namespace ClassicalSharp {
|
||||
byte entityId = reader.ReadUInt8();
|
||||
string displayName = reader.ReadString();
|
||||
string skinName = reader.ReadString();
|
||||
if( entityId != 0xFF ) {
|
||||
Window.AsyncDownloader.DownloadSkin( skinName );
|
||||
Player oldPlayer = Window.NetPlayers[entityId];
|
||||
if( oldPlayer != null ) {
|
||||
oldPlayer.DisplayName = displayName;
|
||||
oldPlayer.SkinName = skinName;
|
||||
Window.RaiseEntityInfoChange( entityId );
|
||||
} else {
|
||||
Window.NetPlayers[entityId] = new NetPlayer( entityId, displayName, skinName, Window );
|
||||
Window.RaiseEntityAdded( entityId );
|
||||
}
|
||||
}
|
||||
AddEntity( entityId, displayName, skinName, false );
|
||||
} break;
|
||||
|
||||
case PacketId.CpeExtRemovePlayerName:
|
||||
@ -631,7 +621,7 @@ namespace ClassicalSharp {
|
||||
byte entityId = reader.ReadUInt8();
|
||||
string displayName = reader.ReadString();
|
||||
string skinName = reader.ReadString();
|
||||
AddEntity( entityId, displayName, skinName );
|
||||
AddEntity( entityId, displayName, skinName, true );
|
||||
} break;
|
||||
|
||||
default:
|
||||
@ -639,7 +629,7 @@ namespace ClassicalSharp {
|
||||
}
|
||||
}
|
||||
|
||||
void AddEntity( byte entityId, string displayName, string skinName ) {
|
||||
void AddEntity( byte entityId, string displayName, string skinName, bool readPosition ) {
|
||||
if( entityId != 0xFF ) {
|
||||
Window.AsyncDownloader.DownloadSkin( skinName );
|
||||
// This shouldn't usually happen, but just in case..
|
||||
@ -651,9 +641,11 @@ namespace ClassicalSharp {
|
||||
Window.NetPlayers[entityId] = new NetPlayer( entityId, displayName, skinName, Window );
|
||||
Window.RaiseEntityAdded( entityId );
|
||||
}
|
||||
ReadAbsoluteLocation( entityId, false );
|
||||
if( entityId == 0xFF ) {
|
||||
Window.LocalPlayer.SpawnPoint = Window.LocalPlayer.Position;
|
||||
if( readPosition ) {
|
||||
ReadAbsoluteLocation( entityId, false );
|
||||
if( entityId == 0xFF ) {
|
||||
Window.LocalPlayer.SpawnPoint = Window.LocalPlayer.Position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using ClassicalSharp.Network;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
@ -9,19 +10,15 @@ namespace ClassicalSharp {
|
||||
|
||||
string womEnvIdentifier = "womenv_0", womTerrainIdentifier = "womterrain_0";
|
||||
void CheckForWomEnvironment() {
|
||||
string page;
|
||||
Window.AsyncDownloader.TryGetPage( womEnvIdentifier, out page );
|
||||
if( page != null ) {
|
||||
ParseWomConfig( page );
|
||||
DownloadedItem item;
|
||||
Window.AsyncDownloader.TryGetItem( womEnvIdentifier, out item );
|
||||
if( item != null && item.Page != null ) {
|
||||
ParseWomConfig( item.Page );
|
||||
}
|
||||
CheckWomBitmaps();
|
||||
}
|
||||
|
||||
void CheckWomBitmaps() {
|
||||
Bitmap terrainBmp;
|
||||
Window.AsyncDownloader.TryGetImage( womTerrainIdentifier, out terrainBmp );
|
||||
if( terrainBmp != null ) {
|
||||
Window.ChangeTerrainAtlas( terrainBmp );
|
||||
|
||||
Window.AsyncDownloader.TryGetItem( womTerrainIdentifier, out item );
|
||||
if( item != null && item.Bmp != null ) {
|
||||
Window.ChangeTerrainAtlas( item.Bmp );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,10 @@ namespace ClassicalSharp {
|
||||
return next;
|
||||
}
|
||||
|
||||
public static bool IsUrl( string value ) {
|
||||
return value.StartsWith( "http://" ) || value.StartsWith( "https://" );
|
||||
}
|
||||
|
||||
public static string StripColours( string value ) {
|
||||
if( value.IndexOf( '&' ) == -1 ) {
|
||||
return value;
|
||||
|
Loading…
x
Reference in New Issue
Block a user