mirror of
				https://github.com/ClassiCube/ClassiCube.git
				synced 2025-11-04 03:27:49 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			158 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
// Part of fCraft | Copyright (c) 2009-2014 Matvei Stefarov <me@matvei.org> | BSD-3 | See LICENSE.txt
 | 
						|
using System;
 | 
						|
using System.IO;
 | 
						|
using System.IO.Compression;
 | 
						|
using System.Text;
 | 
						|
 | 
						|
namespace ClassicalSharp {
 | 
						|
 | 
						|
	public sealed class MapFcm3 {
 | 
						|
		const uint Identifier = 0x0FC2AF40;
 | 
						|
		const byte Revision = 13;
 | 
						|
 | 
						|
		public static byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {
 | 
						|
			BinaryReader reader = new BinaryReader( stream );
 | 
						|
			if( reader.ReadInt32() != Identifier || reader.ReadByte() != Revision ) {
 | 
						|
				throw new InvalidDataException( "Unexpected constant in .fcm file" );
 | 
						|
			}
 | 
						|
 | 
						|
			width = reader.ReadInt16();
 | 
						|
			height = reader.ReadInt16();
 | 
						|
			length = reader.ReadInt16();
 | 
						|
 | 
						|
			int posX = reader.ReadInt32();
 | 
						|
			int posY = reader.ReadInt32();
 | 
						|
			int posZ = reader.ReadInt32();
 | 
						|
			byte yaw = reader.ReadByte();
 | 
						|
			byte pitch = reader.ReadByte();
 | 
						|
 | 
						|
			reader.ReadUInt32(); // date modified
 | 
						|
			reader.ReadUInt32(); // date created
 | 
						|
			reader.ReadBytes( 16 ); // guid
 | 
						|
			reader.ReadBytes( 26 ); // layer index
 | 
						|
			int metaSize = reader.ReadInt32();
 | 
						|
 | 
						|
			using( DeflateStream ds = new DeflateStream( stream, CompressionMode.Decompress ) ) {
 | 
						|
				reader = new BinaryReader( ds );
 | 
						|
				for( int i = 0; i < metaSize; i++ ) {
 | 
						|
					string group = ReadString( reader );
 | 
						|
					string key = ReadString( reader );
 | 
						|
					string value = ReadString( reader );
 | 
						|
					if( group == "CS_Client" ) {
 | 
						|
						int valueInt = Int32.Parse( value );
 | 
						|
						switch( key ) {
 | 
						|
							case "SkyCol":
 | 
						|
								game.Map.SetSkyColour( new FastColour( valueInt ) ); break;
 | 
						|
							case "CloudsCol":
 | 
						|
								game.Map.SetCloudsColour( new FastColour( valueInt ) ); break;	
 | 
						|
							case "FogCol":
 | 
						|
								game.Map.SetFogColour( new FastColour( valueInt ) ); break;	
 | 
						|
								
 | 
						|
							case "ClickDist":
 | 
						|
								game.LocalPlayer.ReachDistance = valueInt / 32f; break;
 | 
						|
							case "SunLight":
 | 
						|
								game.Map.SetSunlight( new FastColour( valueInt ) ); break;
 | 
						|
							case "ShadowLight":
 | 
						|
								game.Map.SetShadowlight( new FastColour( valueInt ) ); break;
 | 
						|
								
 | 
						|
							case "Weather":
 | 
						|
								game.Map.SetWeather( (Weather)valueInt ); break;
 | 
						|
							case "SidesBlock":
 | 
						|
								game.Map.SetSidesBlock( (Block)valueInt ); break;
 | 
						|
							case "EdgeBlock":
 | 
						|
								game.Map.SetEdgeBlock( (Block)valueInt ); break;
 | 
						|
						}
 | 
						|
					}
 | 
						|
					Console.WriteLine( group + "," + key + "," + value );
 | 
						|
				}
 | 
						|
				byte[] blocks = new byte[width * height * length];
 | 
						|
				int read = ds.Read( blocks, 0, blocks.Length );
 | 
						|
				return blocks;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public static void Save( Stream stream, Game game ) {
 | 
						|
			BinaryWriter writer = new BinaryWriter( stream );
 | 
						|
			LocalPlayer p = game.LocalPlayer;
 | 
						|
			Map map = game.Map;
 | 
						|
			
 | 
						|
			writer.Write( Identifier );
 | 
						|
			writer.Write( Revision );
 | 
						|
 | 
						|
			writer.Write( (short)map.Width );
 | 
						|
			writer.Write( (short)map.Height );
 | 
						|
			writer.Write( (short)map.Length );
 | 
						|
 | 
						|
			writer.Write( (int)( p.SpawnPoint.X * 32 ) );
 | 
						|
			writer.Write( (int)( p.SpawnPoint.Y * 32 ) );
 | 
						|
			writer.Write( (int)( p.SpawnPoint.Z * 32 ) );
 | 
						|
 | 
						|
			writer.Write( (byte)0 ); // spawn R
 | 
						|
			writer.Write( (byte)0 ); // spawn L
 | 
						|
 | 
						|
			writer.Write( (uint)0 ); // date modified
 | 
						|
			writer.Write( (uint)0 ); // date created
 | 
						|
 | 
						|
			writer.Write( new byte[16] ); // map guid
 | 
						|
			writer.Write( (byte)1 ); // layer count
 | 
						|
 | 
						|
			long indexOffset = stream.Position;
 | 
						|
			writer.Seek( 25, SeekOrigin.Current );
 | 
						|
			writer.Write( 9 ); // meta count
 | 
						|
 | 
						|
			int compressedLength;
 | 
						|
			long offset;
 | 
						|
			using( DeflateStream ds = new DeflateStream( stream, CompressionMode.Compress, true ) ) {
 | 
						|
				WriteMetadata( ds, game );
 | 
						|
				offset = stream.Position;
 | 
						|
				
 | 
						|
				ds.Write( map.mapData, 0, map.mapData.Length );
 | 
						|
				compressedLength = (int)( stream.Position - offset );
 | 
						|
			}
 | 
						|
 | 
						|
			writer.BaseStream.Seek( indexOffset, SeekOrigin.Begin );
 | 
						|
			writer.Write( (byte)0 );
 | 
						|
			writer.Write( offset );
 | 
						|
			writer.Write( compressedLength );
 | 
						|
			writer.Write( 0 );
 | 
						|
			writer.Write( 1 );
 | 
						|
			writer.Write( map.mapData.Length );
 | 
						|
		}
 | 
						|
		
 | 
						|
		static void WriteMetadata( Stream stream, Game game ) {
 | 
						|
			BinaryWriter writer = new BinaryWriter( stream );
 | 
						|
			LocalPlayer p = game.LocalPlayer;
 | 
						|
			Map map = game.Map;
 | 
						|
			
 | 
						|
			WriteMetadataEntry( writer, "SkyCol", map.SkyCol.ToArgb() );
 | 
						|
			WriteMetadataEntry( writer, "CloudsCol", map.CloudsCol.ToArgb() );
 | 
						|
			WriteMetadataEntry( writer, "FogCol", map.FogCol.ToArgb() );
 | 
						|
			
 | 
						|
			WriteMetadataEntry( writer, "ClickDist", (int)( p.ReachDistance * 32 ) );
 | 
						|
			WriteMetadataEntry( writer, "SunLight", map.Sunlight.ToArgb() );
 | 
						|
			WriteMetadataEntry( writer, "ShadowLight", map.Shadowlight.ToArgb() );
 | 
						|
			
 | 
						|
			WriteMetadataEntry( writer, "Weather", (int)map.Weather );
 | 
						|
			WriteMetadataEntry( writer, "SidesBlock", (int)map.SidesBlock );
 | 
						|
			WriteMetadataEntry( writer, "EdgeBlock", (int)map.EdgeBlock );
 | 
						|
		}
 | 
						|
 | 
						|
		static string ReadString( BinaryReader reader ) {
 | 
						|
			int length = reader.ReadUInt16();
 | 
						|
			byte[] data = reader.ReadBytes( length );
 | 
						|
			return Encoding.ASCII.GetString( data );
 | 
						|
		}
 | 
						|
 | 
						|
		static void WriteString( BinaryWriter writer, string str ) {
 | 
						|
			byte[] data = Encoding.ASCII.GetBytes( str );
 | 
						|
			writer.Write( (ushort)data.Length );
 | 
						|
			writer.Write( data );
 | 
						|
		}
 | 
						|
 | 
						|
		static void WriteMetadataEntry( BinaryWriter writer, string key, int value ) {
 | 
						|
			WriteString( writer, "CS_Client" );
 | 
						|
			WriteString( writer, key );
 | 
						|
			WriteString( writer, value.ToString() );
 | 
						|
		}
 | 
						|
	}
 | 
						|
} |