ClassiCube/ClassicalSharp/TexturePack/TexturePackExtractor.cs

127 lines
4 KiB
C#
Raw Normal View History

2016-06-11 15:29:45 +10:00
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
using System;
using System.Drawing;
using System.IO;
using ClassicalSharp.GraphicsAPI;
using ClassicalSharp.Model;
using ClassicalSharp.Network;
2016-07-13 22:48:28 +10:00
#if ANDROID
using Android.Graphics;
#endif
using PathIO = System.IO.Path; // Android.Graphics.Path clash otherwise
2016-06-11 15:29:45 +10:00
namespace ClassicalSharp.TexturePack {
/// <summary> Extracts resources from a .zip texture pack. </summary>
public sealed class TexturePackExtractor {
public const string Dir = "texpacks";
Game game;
public void Extract( string path, Game game ) {
path = PathIO.Combine( Dir, path );
path = PathIO.Combine( Program.AppDirectory, path );
using( Stream fs = File.OpenRead( path ) )
2016-06-11 15:29:45 +10:00
Extract( fs, game );
}
public void Extract( Stream stream, Game game ) {
2016-06-11 15:29:45 +10:00
this.game = game;
game.Events.RaiseTexturePackChanged();
ZipReader reader = new ZipReader();
reader.ShouldProcessZipEntry = (f) => true;
reader.ProcessZipEntry = ProcessZipEntry;
reader.Extract( stream );
}
void ProcessZipEntry( string filename, byte[] data, ZipEntry entry ) {
// Ignore directories: convert x/name to name and x\name to name.
string name = Utils.ToLower( filename );
2016-06-11 15:29:45 +10:00
int i = name.LastIndexOf( '\\' );
if( i >= 0 ) name = name.Substring( i + 1, name.Length - 1 - i );
i = name.LastIndexOf( '/' );
if( i >= 0 ) name = name.Substring( i + 1, name.Length - 1 - i );
game.Events.RaiseTextureChanged( name, data );
}
internal static void ExtractTerrainPng( Game game, DownloadedItem item ) {
if( item.Data != null ) {
Bitmap bmp = (Bitmap)item.Data;
game.World.TextureUrl = item.Url;
game.Events.RaiseTexturePackChanged();
if( !Platform.Is32Bpp( bmp ) ) {
Utils.LogDebug( "Converting terrain atlas to 32bpp image" );
game.Drawer2D.ConvertTo32Bpp( ref bmp );
}
if( !game.ChangeTerrainAtlas( bmp, null ) ) { bmp.Dispose(); return; }
TextureCache.Add( item.Url, bmp );
TextureCache.AddETag( item.Url, item.ETag, game.ETags );
TextureCache.AdddLastModified( item.Url, item.LastModified, game.LastModified );
} else {
FileStream data = TextureCache.GetStream( item.Url );
if( data == null ) { // e.g. 404 errors
ExtractDefault( game );
} else if( item.Url != game.World.TextureUrl ) {
Bitmap bmp = GetBitmap( data );
if( bmp == null ) { data.Dispose(); return; }
game.World.TextureUrl = item.Url;
game.Events.RaiseTexturePackChanged();
if( game.ChangeTerrainAtlas( bmp, data ) ) return;
bmp.Dispose();
data.Dispose();
} else {
data.Dispose();
}
}
}
internal static void ExtractTexturePack( Game game, DownloadedItem item ) {
if( item.Data != null ) {
game.World.TextureUrl = item.Url;
byte[] data = (byte[])item.Data;
TexturePackExtractor extractor = new TexturePackExtractor();
using( Stream ms = new MemoryStream( data ) ) {
extractor.Extract( ms, game );
}
TextureCache.Add( item.Url, data );
TextureCache.AddETag( item.Url, item.ETag, game.ETags );
TextureCache.AdddLastModified( item.Url, item.LastModified, game.LastModified );
} else {
FileStream data = TextureCache.GetStream( item.Url );
if( data == null ) { // e.g. 404 errors
ExtractDefault( game );
} else if( item.Url != game.World.TextureUrl ) {
game.World.TextureUrl = item.Url;
TexturePackExtractor extractor = new TexturePackExtractor();
extractor.Extract( data, game );
}
}
}
internal static void ExtractDefault( Game game ) {
TexturePackExtractor extractor = new TexturePackExtractor();
extractor.Extract( game.DefaultTexturePack, game );
game.World.TextureUrl = null;
}
static Bitmap GetBitmap( FileStream fs ) {
try {
return Platform.ReadBmp( fs );
} catch( ArgumentException ex ) {
ErrorHandler.LogError( "Cache.GetBitmap", ex );
return null;
} catch( IOException ex ) {
ErrorHandler.LogError( "Cache.GetBitmap", ex );
return null;
}
2016-06-11 15:29:45 +10:00
}
}
}