Add support for EnvMapApperance v2 packets, other various cleanup.

This commit is contained in:
UnknownShadow200 2015-09-23 19:53:12 +10:00
parent 82d4f8b93a
commit a119b2bddf
23 changed files with 172 additions and 137 deletions

View file

@ -7,7 +7,7 @@ namespace ClassicalSharp {
public class BlockSelectScreen : Screen {
public BlockSelectScreen( Game window ) : base( window ) {
public BlockSelectScreen( Game game ) : base( game ) {
font = new Font( "Arial", 13 );
}

View file

@ -7,7 +7,7 @@ namespace ClassicalSharp {
public class ChatScreen : Screen {
public ChatScreen( Game window ) : base( window ) {
public ChatScreen( Game game ) : base( game ) {
}
public int ChatInputYOffset, ChatLogYOffset;

View file

@ -9,7 +9,7 @@ namespace ClassicalSharp {
readonly Font titleFont, messageFont;
TextWidget titleWidget, messageWidget;
public ErrorScreen( Game window, string title, string message ) : base( window ) {
public ErrorScreen( Game game, string title, string message ) : base( game ) {
this.title = title;
this.message = message;
titleFont = new Font( "Arial", 16, FontStyle.Bold );

View file

@ -7,7 +7,7 @@ namespace ClassicalSharp {
readonly Font font;
StringBuffer text;
public FpsScreen( Game window ) : base( window ) {
public FpsScreen( Game game ) : base( game ) {
font = new Font( "Arial", 13 );
text = new StringBuffer( 96 );
}

View file

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public class LoadingMapScreen : Screen {
readonly Font font;
public LoadingMapScreen( Game window, string name, string motd ) : base( window ) {
public LoadingMapScreen( Game game, string name, string motd ) : base( game ) {
serverName = name;
serverMotd = motd;
font = new Font( "Arial", 14 );

View file

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public class NormalScreen : Screen {
public NormalScreen( Game window ) : base( window ) {
public NormalScreen( Game game ) : base( game ) {
}
ChatScreen chat;

View file

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public class PauseScreen : Screen {
public PauseScreen( Game window ) : base( window ) {
public PauseScreen( Game game ) : base( game ) {
}
TextWidget controlsWidget, gameWidget, exitWidget, keyStatusWidget;

View file

@ -6,10 +6,10 @@ namespace ClassicalSharp {
public sealed class BlockHotbarWidget : Widget {
public BlockHotbarWidget( Game window ) : base( window ) {
public BlockHotbarWidget( Game game ) : base( game ) {
HorizontalDocking = Docking.Centre;
VerticalDocking = Docking.BottomOrRight;
window.HeldBlockChanged += HeldBlockChanged;
game.HeldBlockChanged += HeldBlockChanged;
}
Texture[] barTextures = new Texture[9];

View file

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public class ExtPlayerListWidget : PlayerListWidget {
public ExtPlayerListWidget( Game window, Font font ) : base( window, font ) {
public ExtPlayerListWidget( Game game, Font font ) : base( game, font ) {
}
PlayerInfo[] info = new PlayerInfo[256];

View file

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public sealed class NormalPlayerListWidget : PlayerListWidget {
public NormalPlayerListWidget( Game window, Font font ) : base( window, font ) {
public NormalPlayerListWidget( Game game, Font font ) : base( game, font ) {
}
PlayerInfo[] info = new PlayerInfo[256];

View file

@ -7,7 +7,7 @@ namespace ClassicalSharp {
public abstract class PlayerListWidget : Widget {
protected readonly Font font;
public PlayerListWidget( Game window, Font font ) : base( window ) {
public PlayerListWidget( Game game, Font font ) : base( game ) {
HorizontalDocking = Docking.Centre;
VerticalDocking = Docking.Centre;
this.font = font;

View file

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public sealed class TextGroupWidget : Widget {
public TextGroupWidget( Game window, int elementsCount, Font font ) : base( window ) {
public TextGroupWidget( Game game, int elementsCount, Font font ) : base( game ) {
ElementsCount = elementsCount;
this.font = font;
}

View file

@ -7,7 +7,7 @@ namespace ClassicalSharp {
public sealed class TextInputWidget : Widget {
public TextInputWidget( Game window, Font font, Font boldFont ) : base( window ) {
public TextInputWidget( Game game, Font font, Font boldFont ) : base( game ) {
HorizontalDocking = Docking.LeftOrTop;
VerticalDocking = Docking.BottomOrRight;
handlers[0] = new InputHandler( BackspaceKey, Key.BackSpace, 10 );
@ -131,10 +131,10 @@ namespace ClassicalSharp {
return true;
}
public void KeyTick( Game window ) {
public void KeyTick( Game game ) {
if( LastDown == DateTime.MinValue ) return;
if( window.IsKeyDown( AssociatedKey ) &&
( DateTime.UtcNow - LastDown ).TotalSeconds >= period ) {
if( game.IsKeyDown( AssociatedKey ) &&
(DateTime.UtcNow - LastDown).TotalSeconds >= period ) {
KeyFunction();
}
}

View file

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public sealed class TextWidget : Widget {
public TextWidget( Game window, Font font ) : base( window ) {
public TextWidget( Game game, Font font ) : base( game ) {
this.font = font;
}

View file

@ -21,7 +21,7 @@ namespace ClassicalSharp {
}
}
}
// Leaves should show faces with their neighbours (matches Classic)
for( int i = 0; i < TileSide.Sides; i++ ) {
SetHidden( (byte)Block.Leaves, (byte)Block.Leaves, i, false );
}

View file

@ -7,7 +7,7 @@ namespace ClassicalSharp {
public class NetPlayer : Player {
int tickCount;
public NetPlayer( string displayName, string skinName, Game window ) : base( window ) {
public NetPlayer( string displayName, string skinName, Game game ) : base( game ) {
DisplayName = displayName;
SkinName = Utils.StripColours( skinName );
InitRenderingData();

View file

@ -16,8 +16,8 @@ namespace ClassicalSharp.Particles {
public abstract void Dispose();
public Particle( Game window, Vector3 pos, Vector3 velocity, double lifetime, TextureRectangle rec ) {
game = window;
public Particle( Game game, Vector3 pos, Vector3 velocity, double lifetime, TextureRectangle rec ) {
this.game = game;
Position = lastPos = nextPos = pos;
Velocity = velocity;
Lifetime = (float)lifetime;

View file

@ -88,8 +88,8 @@ namespace ClassicalSharp {
protected void CheckSkin() {
DownloadedItem item;
game.AsyncDownloader.TryGetItem( "skin_" + SkinName, out item );
if( item != null && item.Bmp != null ) {
Bitmap bmp = item.Bmp;
if( item != null && item.Data != null ) {
Bitmap bmp = (Bitmap)item.Data;
game.Graphics.DeleteTexture( ref PlayerTextureId );
try {

View file

@ -226,25 +226,8 @@ namespace ClassicalSharp {
SetNewScreen( new PauseScreen( this ) );
}
if( imageCheckAccumulator > imageCheckPeriod ) {
imageCheckAccumulator -= imageCheckPeriod;
AsyncDownloader.PurgeOldEntries( 10 );
}
base.OnRenderFrame( e );
int ticksThisFrame = 0;
while( ticksAccumulator >= ticksPeriod ) {
Network.Tick( ticksPeriod );
Players.Tick( ticksPeriod );
Camera.Tick( ticksPeriod );
ParticleManager.Tick( ticksPeriod );
Animations.Tick( ticksPeriod );
ticksThisFrame++;
ticksAccumulator -= ticksPeriod;
}
if( ticksThisFrame > ticksFrequency / 3 ) {
Utils.LogWarning( "Falling behind (did {0} ticks this frame)", ticksThisFrame );
}
CheckScheduledTasks();
float t = (float)( ticksAccumulator / ticksPeriod );
LocalPlayer.SetInterpPosition( t );
@ -281,47 +264,41 @@ namespace ClassicalSharp {
}
Graphics.Mode3D();
if( screenshotRequested ) {
if( !Directory.Exists( "screenshots" ) ) {
Directory.CreateDirectory( "screenshots" );
}
string timestamp = DateTime.Now.ToString( "dd-MM-yyyy-HH-mm-ss" );
string path = Path.Combine( "screenshots", "screenshot_" + timestamp + ".png" );
Graphics.TakeScreenshot( path, ClientSize );
screenshotRequested = false;
}
if( screenshotRequested )
TakeScreenshot();
Graphics.EndFrame( this );
}
public override void Dispose() {
MapRenderer.Dispose();
MapEnvRenderer.Dispose();
EnvRenderer.Dispose();
WeatherRenderer.Dispose();
SetNewScreen( null );
fpsScreen.Dispose();
SelectionManager.Dispose();
TerrainAtlas.Dispose();
TerrainAtlas1D.Dispose();
ModelCache.Dispose();
Picking.Dispose();
ParticleManager.Dispose();
Players.Dispose();
AsyncDownloader.Dispose();
if( writer != null ) {
writer.Close();
void CheckScheduledTasks() {
if( imageCheckAccumulator > imageCheckPeriod ) {
imageCheckAccumulator -= imageCheckPeriod;
AsyncDownloader.PurgeOldEntries( 10 );
}
if( activeScreen != null ) {
activeScreen.Dispose();
int ticksThisFrame = 0;
while( ticksAccumulator >= ticksPeriod ) {
Network.Tick( ticksPeriod );
Players.Tick( ticksPeriod );
Camera.Tick( ticksPeriod );
ParticleManager.Tick( ticksPeriod );
Animations.Tick( ticksPeriod );
ticksThisFrame++;
ticksAccumulator -= ticksPeriod;
}
Graphics.DeleteIb( defaultIb );
Graphics.Dispose();
Utils2D.Dispose();
Animations.Dispose();
Graphics.DeleteTexture( ref CloudsTextureId );
Graphics.DeleteTexture( ref RainTextureId );
Graphics.DeleteTexture( ref SnowTextureId );
base.Dispose();
if( ticksThisFrame > ticksFrequency / 3 ) {
Utils.LogWarning( "Falling behind (did {0} ticks this frame)", ticksThisFrame );
}
}
void TakeScreenshot() {
if( !Directory.Exists( "screenshots" ) ) {
Directory.CreateDirectory( "screenshots" );
}
string timestamp = DateTime.Now.ToString( "dd-MM-yyyy-HH-mm-ss" );
string path = Path.Combine( "screenshots", "screenshot_" + timestamp + ".png" );
Graphics.TakeScreenshot( path, ClientSize );
screenshotRequested = false;
}
public void UpdateProjection() {
@ -387,6 +364,37 @@ namespace ClassicalSharp {
int newHeight = Map.GetLightHeight( x, z );
MapRenderer.RedrawBlock( x, y, z, block, oldHeight, newHeight );
}
public override void Dispose() {
MapRenderer.Dispose();
MapEnvRenderer.Dispose();
EnvRenderer.Dispose();
WeatherRenderer.Dispose();
SetNewScreen( null );
fpsScreen.Dispose();
SelectionManager.Dispose();
TerrainAtlas.Dispose();
TerrainAtlas1D.Dispose();
ModelCache.Dispose();
Picking.Dispose();
ParticleManager.Dispose();
Players.Dispose();
AsyncDownloader.Dispose();
if( writer != null ) {
writer.Close();
}
if( activeScreen != null ) {
activeScreen.Dispose();
}
Graphics.DeleteIb( defaultIb );
Graphics.Dispose();
Utils2D.Dispose();
Animations.Dispose();
Graphics.DeleteTexture( ref CloudsTextureId );
Graphics.DeleteTexture( ref RainTextureId );
Graphics.DeleteTexture( ref SnowTextureId );
base.Dispose();
}
}
public sealed class CpeListInfo {

View file

@ -31,6 +31,7 @@ namespace ClassicalSharp {
bool sendHeldBlock;
bool useMessageTypes;
bool useBlockPermissions;
bool usingTexturePack;
bool receivedFirstPosition;
public override void Connect( IPAddress address, int port ) {
@ -83,8 +84,13 @@ namespace ClassicalSharp {
void CheckForNewTerrainAtlas() {
DownloadedItem item;
game.AsyncDownloader.TryGetItem( "terrain", out item );
if( item != null && item.Bmp != null ) {
game.ChangeTerrainAtlas( item.Bmp );
if( item != null && item.Data != null ) {
game.ChangeTerrainAtlas( (Bitmap)item.Data );
}
game.AsyncDownloader.TryGetItem( "texturePack", out item );
if( item != null && item.Data != null ) {
TexturePackExtractor extractor = new TexturePackExtractor();
extractor.Extract( (byte[])item.Data, game );
}
}
@ -425,27 +431,31 @@ namespace ClassicalSharp {
case PacketId.CpeExtEntry:
{
string extensionName = reader.ReadAsciiString();
int extensionVersion = reader.ReadInt32();
Utils.LogDebug( "cpe ext: " + extensionName + "," + extensionVersion );
if( extensionName == "HeldBlock" ) {
string extName = reader.ReadAsciiString();
int extVersion = reader.ReadInt32();
Utils.LogDebug( "cpe ext: " + extName + " , " + extVersion );
if( extName == "HeldBlock" ) {
sendHeldBlock = true;
} else if( extensionName == "MessageTypes" ) {
} else if( extName == "MessageTypes" ) {
useMessageTypes = true;
} else if( extensionName == "ExtPlayerList" ) {
} else if( extName == "ExtPlayerList" ) {
UsingExtPlayerList = true;
} else if( extensionName == "BlockPermissions" ) {
} else if( extName == "BlockPermissions" ) {
useBlockPermissions = true;
} else if( extensionName == "PlayerClick" ) {
} else if( extName == "PlayerClick" ) {
UsingPlayerClick = true;
} else if( extName == "EnvMapAppearance" && extVersion == 2 ) {
usingTexturePack = true;
}
cpeServerExtensionsCount--;
if( cpeServerExtensionsCount == 0 ) {
MakeExtInfo( Utils.AppName, clientExtensions.Length );
SendPacket();
for( int i = 0; i < clientExtensions.Length; i++ ) {
string extName = clientExtensions[i];
MakeExtEntry( extName, extName == "ExtPlayerList" ? 2 : 1 );
string name = clientExtensions[i];
int version = (name == "ExtPlayerList" || name == "EnvMapApperance") ? 2 : 1;
MakeExtEntry( name, version );
SendPacket();
}
}
@ -611,7 +621,11 @@ namespace ClassicalSharp {
extractor.Extract( game.defaultTexPack, game );
} else {
game.Animations.Dispose();
game.AsyncDownloader.DownloadImage( url, true, "terrain" );
if( usingTexturePack )
game.AsyncDownloader.DownloadData( url, true, "texturePack" );
else
game.AsyncDownloader.DownloadImage( url, true, "terrain" );
}
Utils.LogDebug( "Image url: " + url );
} break;

View file

@ -21,7 +21,7 @@ namespace ClassicalSharp.Network {
public AsyncDownloader( string skinServer ) {
this.skinServer = skinServer;
WebRequest.DefaultWebProxy = null;
client = new WebClient();
client = new WebClient();
worker = new Thread( DownloadThreadWorker, 256 * 1024 );
worker.Name = "ClassicalSharp.ImageDownloader";
@ -33,20 +33,24 @@ namespace ClassicalSharp.Network {
string strippedSkinName = Utils.StripColours( skinName );
string url = Utils.IsUrl( skinName ) ? skinName :
skinServer + strippedSkinName + ".png";
AddRequestToQueue( url, true, "skin_" + strippedSkinName, true );
AddRequest( url, true, "skin_" + strippedSkinName, 0 );
}
public void DownloadImage( string url, bool priority, string identifier ) {
AddRequestToQueue( url, priority, identifier, true );
AddRequest( url, priority, identifier, 0 );
}
public void DownloadPage( string url, bool priority, string identifier ) {
AddRequestToQueue( url, priority, identifier, false );
AddRequest( url, priority, identifier, 1 );
}
void AddRequestToQueue( string url, bool priority, string identifier, bool image ) {
public void DownloadData( string url, bool priority, string identifier ) {
AddRequest( url, priority, identifier, 2 );
}
void AddRequest( string url, bool priority, string identifier, byte type ) {
lock( requestLocker ) {
DownloadRequest request = new DownloadRequest( url, identifier, image );
DownloadRequest request = new DownloadRequest( url, identifier, type );
if( priority ) {
requests.Insert( 0, request );
} else {
@ -74,7 +78,7 @@ namespace ClassicalSharp.Network {
foreach( var item in downloaded ) {
DateTime timestamp = item.Value.TimeDownloaded;
if( ( now - timestamp ).TotalSeconds > seconds ) {
if( (now - timestamp).TotalSeconds > seconds ) {
itemsToRemove.Add( item.Key );
}
}
@ -84,9 +88,9 @@ namespace ClassicalSharp.Network {
DownloadedItem item;
downloaded.TryGetValue( key, out item );
downloaded.Remove( key );
if( item.Bmp != null ) {
item.Bmp.Dispose();
}
Bitmap bmp = item.Data as Bitmap;
if( bmp != null )
bmp.Dispose();
}
}
}
@ -124,29 +128,30 @@ namespace ClassicalSharp.Network {
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;
byte type = request.Type;
string dataType = type == 0 ? "image" : (type == 1 ? "string" : "raw");
Utils.LogDebug( "Downloading " + dataType + " from: " + url );
object value = null;
try {
if( isImage ) {
if( type == 0 ) {
byte[] data = client.DownloadData( url );
using( MemoryStream stream = new MemoryStream( data ) ) {
bmp = new Bitmap( stream );
}
} else {
page = client.DownloadString( url );
using( MemoryStream stream = new MemoryStream( data ) )
value = new Bitmap( stream );
} else if( type == 1 ) {
value = client.DownloadString( url );
} else if( type == 2 ) {
value = client.DownloadData( url );
}
Utils.LogDebug( "Downloaded from: " + request.Url );
Utils.LogDebug( "Downloaded from: " + url );
} catch( Exception ex ) {
if( !( ex is WebException || ex is ArgumentException ) ) throw;
Utils.LogDebug( "Failed to download from: " + request.Url );
Utils.LogDebug( "Failed to download from: " + url );
}
lock( downloadedLocker ) {
DownloadedItem oldItem;
DownloadedItem newItem = new DownloadedItem( bmp, page, request.TimeAdded, request.Url );
DownloadedItem newItem = new DownloadedItem( value, request.TimeAdded, url );
if( downloaded.TryGetValue( request.Identifier, out oldItem ) ) {
if( oldItem.TimeAdded > newItem.TimeAdded ) {
@ -155,8 +160,9 @@ namespace ClassicalSharp.Network {
newItem = old;
}
if( oldItem.Bmp != null )
oldItem.Bmp.Dispose();
Bitmap oldBmp = oldItem.Data as Bitmap;
if( oldBmp != null )
oldBmp.Dispose();
}
downloaded[request.Identifier] = newItem;
}
@ -166,13 +172,13 @@ namespace ClassicalSharp.Network {
public string Url;
public string Identifier;
public bool IsImage;
public byte Type; // 0 = bitmap, 1 = string, 2 = byte[]
public DateTime TimeAdded;
public DownloadRequest( string url, string identifier, bool isImage ) {
public DownloadRequest( string url, string identifier, byte type ) {
Url = url;
Identifier = identifier;
IsImage = isImage;
Type = type;
TimeAdded = DateTime.UtcNow;
}
}
@ -180,14 +186,12 @@ namespace ClassicalSharp.Network {
public class DownloadedItem {
public Bitmap Bmp;
public string Page;
public object Data;
public DateTime TimeAdded, TimeDownloaded;
public string Url;
public DownloadedItem( Bitmap bmp, string page, DateTime timeAdded, string url ) {
Bmp = bmp;
Page = page;
public DownloadedItem( object data, DateTime timeAdded, string url ) {
Data = data;
TimeAdded = timeAdded;
TimeDownloaded = DateTime.UtcNow;
Url = url;

View file

@ -1,5 +1,6 @@
// This class was partially based on information from http://files.worldofminecraft.com/texturing/
using System;
using System.Drawing;
using System.IO;
using ClassicalSharp.Network;
@ -13,13 +14,13 @@ namespace ClassicalSharp {
void CheckForWomEnvironment() {
DownloadedItem item;
game.AsyncDownloader.TryGetItem( womEnvIdentifier, out item );
if( item != null && item.Page != null ) {
ParseWomConfig( item.Page );
if( item != null && item.Data != null ) {
ParseWomConfig( (string)item.Data );
}
game.AsyncDownloader.TryGetItem( womTerrainIdentifier, out item );
if( item != null && item.Bmp != null ) {
game.ChangeTerrainAtlas( item.Bmp );
if( item != null && item.Data != null ) {
game.ChangeTerrainAtlas( (Bitmap)item.Data );
}
}

View file

@ -10,17 +10,25 @@ namespace ClassicalSharp.TexturePack {
Game game;
public void Extract( string path, Game game ) {
this.game = game;
game.Animations.Dispose();
using( FileStream fs = new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read ) ) {
ZipReader reader = new ZipReader();
reader.ShouldProcessZipEntry = ShouldProcessZipEntry;
reader.ProcessZipEntry = ProcessZipEntry;
reader.Extract( fs );
}
using( Stream fs = new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read ) )
Extract( fs, game );
}
bool ShouldProcessZipEntry( string filename ) {
public void Extract( byte[] data, Game game ) {
using( Stream fs = new MemoryStream( data ) )
Extract( fs, game );
}
void Extract( Stream stream, Game game ) {
this.game = game;
game.Animations.Dispose();
ZipReader reader = new ZipReader();
reader.ShouldProcessZipEntry = ShouldProcessZipEntry;
reader.ProcessZipEntry = ProcessZipEntry;
reader.Extract( stream );
}
bool ShouldProcessZipEntry( string filename ) {
return true;
}