diff --git a/ClassicalSharp/Blocks/BlockInfo.cs b/ClassicalSharp/Blocks/BlockInfo.cs index 537fc1b74..9effc243f 100644 --- a/ClassicalSharp/Blocks/BlockInfo.cs +++ b/ClassicalSharp/Blocks/BlockInfo.cs @@ -51,9 +51,9 @@ namespace ClassicalSharp { SetBlockHeight( Block.Snow, 2/16f ); MarkTranslucent( Block.StillWater ); MarkTranslucent( Block.Water ); MarkTranslucent( Block.Ice ); - MarkTransparent( Block.Glass ); MarkTransparent( Block.Leaves ); - MarkTransparent( Block.Slab ); MarkTransparent( Block.Snow ); - MarkTransparent( Block.CobblestoneSlab ); + MarkTransparent( Block.Glass, false ); MarkTransparent( Block.Leaves, false ); + MarkTransparent( Block.Slab, true ); MarkTransparent( Block.Snow, true ); + MarkTransparent( Block.CobblestoneSlab, true ); MarkSprite( Block.Rose ); MarkSprite( Block.Sapling ); MarkSprite( Block.Dandelion ); MarkSprite( Block.BrownMushroom ); MarkSprite( Block.RedMushroom ); MarkSprite( Block.Rope ); @@ -83,9 +83,9 @@ namespace ClassicalSharp { canDelete[(int)Block.StillLava] = false; } - void MarkTransparent( Block id ) { + void MarkTransparent( Block id, bool blocks ) { isTransparent[(int)id] = true; - blocksLight[(int)id] = false; + blocksLight[(int)id] = blocks; isOpaque[(int)id] = false; } diff --git a/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs b/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs index b68ba9c8d..1807676be 100644 --- a/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs +++ b/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs @@ -235,7 +235,7 @@ namespace ClassicalSharp { int texId = info.GetTextureLoc( tile, TileSide.Bottom ); int i; TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); - FastColour col = Y > 0 ? ( emitsLight || (Y - 1) > map.heightmap[( Z * width ) + X] ? map.SunlightYBottom : map.ShadowlightYBottom ) + FastColour col = Y > 0 ? ( emitsLight || Y > map.heightmap[( Z * width ) + X] ? map.SunlightYBottom : map.ShadowlightYBottom ) : map.SunlightYBottom; DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i]; @@ -249,7 +249,7 @@ namespace ClassicalSharp { int texId = info.GetTextureLoc( tile, TileSide.Top ); int i; TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); - FastColour col = Y < maxY ? ( emitsLight || (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight ) + FastColour col = Y < maxY ? ( emitsLight || Y > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight ) : map.Sunlight; DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i]; diff --git a/ClassicalSharp/TexturePack/Animations.cs b/ClassicalSharp/TexturePack/Animations.cs index 7dbafc5de..ee61e84c7 100644 --- a/ClassicalSharp/TexturePack/Animations.cs +++ b/ClassicalSharp/TexturePack/Animations.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.IO; using ClassicalSharp.GraphicsAPI; namespace ClassicalSharp.TexturePack { @@ -22,8 +23,6 @@ namespace ClassicalSharp.TexturePack { Dispose(); this.bmp = bmp; fastBmp = new FastBitmap( bmp, true ); - //DefineAnimation( 14, 0, 0, 0, 16, 32, 5 ); // water - //DefineAnimation( 14, 1, 0, 16, 16, 20, 5 ); // lava } public void Dispose() { @@ -41,12 +40,43 @@ namespace ClassicalSharp.TexturePack { } } - public void DefineAnimation( int tileX, int tileY, int animX, int animY, int animSize, + public void ReadAnimationsDescription( StreamReader reader ) { + string line; + while( ( line = reader.ReadLine() ) != null ) { + if( line.Length == 0 || line[0] == '#' ) continue; + + string[] parts = line.Split( ' ' ); + if( parts.Length < 7 ) { + Utils.LogWarning( "Not enough arguments for animation: " + line ); continue; + } + byte tileX, tileY; + if( !Byte.TryParse( parts[0], out tileX ) || !Byte.TryParse( parts[1], out tileY ) + || tileX >= 16 || tileY >= 16 ) { + Utils.LogWarning( "Invalid animation tile coordinates: " + line ); continue; + } + + int frameX, frameY; + if( !Int32.TryParse( parts[2], out frameX ) || !Int32.TryParse( parts[3], out frameY ) + || frameX < 0 || frameY < 0 ) { + Utils.LogWarning( "Invalid animation coordinates: " + line ); continue; + } + + int frameSize, statesCount, tickDelay; + if( !Int32.TryParse( parts[4], out frameSize ) || !Int32.TryParse( parts[5], out statesCount ) || + !Int32.TryParse( parts[6], out tickDelay ) || frameSize < 0 || statesCount < 0 || tickDelay < 0 ) { + Utils.LogWarning( "Invalid animation: " + line ); continue; + } + + DefineAnimation( tileX, tileY, frameX, frameY, frameSize, statesCount, tickDelay ); + } + } + + public void DefineAnimation( int tileX, int tileY, int frameX, int frameY, int frameSize, int statesNum, int tickDelay ) { AnimationData data = new AnimationData(); data.TileX = tileX; data.TileY = tileY; - data.AnimX = animX; data.AnimY = animY; - data.AnimSize = animSize; data.StatesCount = statesNum; + data.FrameX = frameX; data.FrameY = frameY; + data.FrameSize = frameSize; data.StatesCount = statesNum; data.TickDelay = tickDelay; animations.Add( data ); } @@ -54,7 +84,6 @@ namespace ClassicalSharp.TexturePack { unsafe void ApplyAnimation( AnimationData data ) { data.Tick--; if( data.Tick >= 0 ) return; - Console.WriteLine( "tick" ); data.CurrentState++; data.CurrentState %= data.StatesCount; data.Tick = data.TickDelay; @@ -64,16 +93,16 @@ namespace ClassicalSharp.TexturePack { int index = atlas.Get1DIndex( texId ); int rowNum = atlas.Get1DRowId( texId ); - int size = data.AnimSize; + int size = data.FrameSize; byte* temp = stackalloc byte[size * size * 4]; FastBitmap part = new FastBitmap( size, size, size * 4, (IntPtr)temp ); - FastBitmap.MovePortion( data.AnimX + data.CurrentState * size, data.AnimY, 0, 0, fastBmp, part, size ); + FastBitmap.MovePortion( data.FrameX + data.CurrentState * size, data.FrameY, 0, 0, fastBmp, part, size ); api.UpdateTexturePart( atlas.TexIds[index], 0, rowNum * game.TerrainAtlas.elementSize, part ); } class AnimationData { public int TileX, TileY; - public int AnimX, AnimY, AnimSize; + public int FrameX, FrameY, FrameSize; public int CurrentState; public int StatesCount; public int Tick, TickDelay; diff --git a/ClassicalSharp/TexturePack/TexturePackExtractor.cs b/ClassicalSharp/TexturePack/TexturePackExtractor.cs index acf0f05fe..707f9182a 100644 --- a/ClassicalSharp/TexturePack/TexturePackExtractor.cs +++ b/ClassicalSharp/TexturePack/TexturePackExtractor.cs @@ -56,9 +56,6 @@ namespace ClassicalSharp.TexturePack { UpdateTexture( ref cache.SheepFurTexId, stream, false ); break; case "char.png": UpdateTexture( ref cache.HumanoidTexId, stream, true ); break; - case "animations.png": - case "animation.png": - game.Animations.SetAtlas( new Bitmap( stream ) ); break; case "clouds.png": case "cloud.png": UpdateTexture( ref game.CloudsTextureId, stream, false ); break; @@ -66,6 +63,14 @@ namespace ClassicalSharp.TexturePack { UpdateTexture( ref game.RainTextureId, stream, false ); break; case "snow.png": UpdateTexture( ref game.SnowTextureId, stream, false ); break; + case "animations.png": + case "animation.png": + game.Animations.SetAtlas( new Bitmap( stream ) ); break; + case "animations.txt": + case "animation.txt": + StreamReader reader = new StreamReader( stream ); + game.Animations.ReadAnimationsDescription( reader ); + break; } } diff --git a/Launcher/Launcher.csproj b/Launcher/Launcher.csproj index 395e9449c..a9cf5e4aa 100644 --- a/Launcher/Launcher.csproj +++ b/Launcher/Launcher.csproj @@ -85,6 +85,7 @@ + diff --git a/Launcher/Patcher/Animations.cs b/Launcher/Patcher/Animations.cs new file mode 100644 index 000000000..88fe92b00 --- /dev/null +++ b/Launcher/Patcher/Animations.cs @@ -0,0 +1,50 @@ +using System; +using System.Drawing; +using System.IO; + +namespace Launcher { + + public partial class ResourceFetcher { + + const string animationsTxt = @"# This file defines the animations used in a texture pack for ClassicCube. +# Each line is in the format: +# - TileX and TileY indicate the coordinates of the tile in terrain.png that +# will be replaced by the animation frames. These range from 0 to 15. (inclusive of 15) +# - FrameX and FrameY indicates the pixel coordinates of the first animation frame in animations.png. +# - Frame Size indicates the size in pixels of an animation frame. +# - Frames count indicates the number of used frames. The first frame is located at +# (FrameX, FrameY), the second one at (FrameX + FrameSize, FrameY) and so on. +# - Tick delay is the number of ticks a frame doesn't change. For instance, a value of 0 +# means that the frame would be changed every tick, while a value of 2 would mean +# 'replace with frame 1, don't change frame, don't change frame, replace with frame 2'. + +# still water +14 0 0 0 16 32 2 +# still lava +14 1 0 16 16 39 2 +# fire +6 2 0 32 16 32 0"; + + unsafe void PatchDefault( byte[] data, int y ) { + // Sadly files in modern are 24 rgb, so we can't use fastbitmap here + using( Bitmap bmp = new Bitmap( new MemoryStream( data ) ) ) { + for( int tile = 0; tile < bmp.Height; tile += 16 ) { + CopyTile( tile, tile, y, bmp ); + } + } + } + + unsafe void PatchCycle( byte[] data, int y ) { + using( Bitmap bmp = new Bitmap( new MemoryStream( data ) ) ) { + int dst = 0; + for( int tile = 0; tile < bmp.Height; tile += 16, dst += 16 ) { + CopyTile( tile, dst, y, bmp ); + } + // Cycle back to first frame. + for( int tile = bmp.Height - 32; tile >= 0; tile -= 16, dst += 16 ) { + CopyTile( tile, dst, y, bmp ); + } + } + } + } +} diff --git a/Launcher/Patcher/ResourceFetcher.cs b/Launcher/Patcher/ResourceFetcher.cs index 786c5dd24..fa696e389 100644 --- a/Launcher/Patcher/ResourceFetcher.cs +++ b/Launcher/Patcher/ResourceFetcher.cs @@ -9,7 +9,7 @@ using ClassicalSharp.TexturePack; namespace Launcher { - public class ResourceFetcher { + public partial class ResourceFetcher { const string classicJarUri = "http://s3.amazonaws.com/Minecraft.Download/versions/c0.30_01c/c0.30_01c.jar"; const string modernJarUri = "http://s3.amazonaws.com/Minecraft.Download/versions/1.6.2/1.6.2.jar"; @@ -36,11 +36,12 @@ namespace Launcher { reader.Extract( srcClassic ); // Grab animations and snow - animBitmap = new Bitmap( 512, 32, PixelFormat.Format32bppArgb ); + animBitmap = new Bitmap( 1024, 64, PixelFormat.Format32bppArgb ); reader.ShouldProcessZipEntry = ShouldProcessZipEntry_Modern; reader.ProcessZipEntry = ProcessZipEntry_Modern; reader.Extract( srcModern ); writer.WriteNewImage( animBitmap, "animations.png" ); + writer.WriteNewString( animationsTxt, "animations.txt" ); animBitmap.Dispose(); writer.WriteCentralDirectoryRecords(); } @@ -76,7 +77,8 @@ namespace Launcher { ( filename == "assets/minecraft/textures/environment/snow.png" || filename == "assets/minecraft/textures/blocks/water_still.png" || filename == "assets/minecraft/textures/blocks/lava_still.png" || - filename == "assets/minecraft/textures/entity/chicken.png" ); + filename == "assets/minecraft/textures/blocks/fire_layer_1.png" || + filename == "assets/minecraft/textures/entity/chicken.png" ); } void ProcessZipEntry_Modern( string filename, byte[] data, ZipEntry entry ) { @@ -90,10 +92,13 @@ namespace Launcher { writer.WriteZipEntry( entry, data ); break; case "assets/minecraft/textures/blocks/water_still.png": - PatchAnimation( data, 0 ); + PatchDefault( data, 0 ); break; case "assets/minecraft/textures/blocks/lava_still.png": - PatchAnimation( data, 16 ); + PatchCycle( data, 16 ); + break; + case "assets/minecraft/textures/blocks/fire_layer_1.png": + PatchDefault( data, 32 ); break; } } @@ -114,16 +119,11 @@ namespace Launcher { } } - unsafe void PatchAnimation( byte[] data, int y ) { - // Sadly files in modern are 24 rgb, so we can't use fastbitmap here - using( Bitmap bmp = new Bitmap( new MemoryStream( data ) ) ) { - for( int tile = 0; tile < bmp.Height; tile += 16 ) { - for( int yy = 0; yy < 16; yy++ ) { - for( int xx = 0; xx < 16; xx++ ) { - animBitmap.SetPixel( tile + xx, y + yy, - bmp.GetPixel( xx, tile + yy ) ); - } - } + void CopyTile( int src, int dst, int y, Bitmap bmp ) { + for( int yy = 0; yy < 16; yy++ ) { + for( int xx = 0; xx < 16; xx++ ) { + animBitmap.SetPixel( dst + xx, y + yy, + bmp.GetPixel( xx, src + yy ) ); } } } diff --git a/Launcher/Patcher/ZipWriter.cs b/Launcher/Patcher/ZipWriter.cs index c57febec3..3640fb532 100644 --- a/Launcher/Patcher/ZipWriter.cs +++ b/Launcher/Patcher/ZipWriter.cs @@ -2,6 +2,7 @@ using System.Drawing; using System.Drawing.Imaging; using System.IO; +using System.Text; using ClassicalSharp.TexturePack; namespace Launcher { @@ -22,22 +23,31 @@ namespace Launcher { entry.CompressedDataSize = (int)entry.UncompressedDataSize; entry.LocalHeaderOffset = (int)stream.Position; entries[entriesCount++] = entry; - WriteLocalFileHeader( entry, data, data.Length ); + WriteLocalFileEntry( entry, data, data.Length ); } public void WriteNewImage( Bitmap bmp, string filename ) { MemoryStream data = new MemoryStream(); bmp.Save( data, ImageFormat.Png ); byte[] buffer = data.GetBuffer(); - + WriteNewEntry( filename, buffer, (int)data.Length ); + } + + public void WriteNewString( string text, string filename ) { + byte[] data = Encoding.ASCII.GetBytes( text ); + WriteNewEntry( filename, data, data.Length ); + } + + public void WriteNewEntry( string filename, byte[] data, int dataLength ) { ZipEntry entry = new ZipEntry(); - entry.UncompressedDataSize = (int)data.Length; - entry.Crc32 = CRC32( buffer, entry.UncompressedDataSize ); - entry.CompressedDataSize = entry.UncompressedDataSize; + entry.UncompressedDataSize = dataLength; + entry.Crc32 = CRC32( data, dataLength ); + entry.CompressedDataSize = dataLength; entry.LocalHeaderOffset = (int)stream.Position; + entry.Filename = filename; entries[entriesCount++] = entry; - WriteLocalFileHeader( entry, buffer, entry.UncompressedDataSize ); + WriteLocalFileEntry( entry, data, dataLength ); } public void WriteCentralDirectoryRecords() { @@ -49,7 +59,7 @@ namespace Launcher { WriteEndOfCentralDirectoryRecord( (ushort)entriesCount, dirSize, dirOffset ); } - void WriteLocalFileHeader( ZipEntry entry, byte[] data, int length ) { + void WriteLocalFileEntry( ZipEntry entry, byte[] data, int length ) { writer.Write( 0x04034b50 ); // signature writer.Write( (ushort)20 ); // version needed writer.Write( (ushort)8 ); // bitflags