mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-17 02:33:58 -04:00
167 lines
5.6 KiB
C#
167 lines
5.6 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Net;
|
|
using System.Text;
|
|
using OpenTK;
|
|
|
|
namespace ClassicalSharp {
|
|
|
|
public sealed partial class MapCw : IMapFileFormat {
|
|
|
|
public override bool SupportsSaving {
|
|
get { return true; }
|
|
}
|
|
|
|
BinaryWriter writer;
|
|
public override void Save( Stream stream, Game game ) {
|
|
using( GZipStream wrapper = new GZipStream( stream, CompressionMode.Compress ) ) {
|
|
writer = new BinaryWriter( wrapper );
|
|
this.game = game;
|
|
map = game.Map;
|
|
|
|
WriteTag( NbtTagType.Compound ); WriteString( "ClassicWorld" );
|
|
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "FormatVersion" ); WriteInt8( 1 );
|
|
|
|
WriteTag( NbtTagType.Int8Array );
|
|
WriteString( "UUID" ); WriteInt32( 16 );
|
|
WriteBytes( map.Uuid.ToByteArray() );
|
|
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "X" ); WriteInt16( (short)map.Width );
|
|
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "Y" ); WriteInt16( (short)map.Height );
|
|
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "Z" ); WriteInt16( (short)map.Length );
|
|
|
|
WriteSpawnCompoundTag();
|
|
|
|
WriteTag( NbtTagType.Int8Array );
|
|
WriteString( "BlockArray" ); WriteInt32( map.mapData.Length );
|
|
WriteBytes( map.mapData );
|
|
|
|
WriteMetadata();
|
|
|
|
WriteTag( NbtTagType.End );
|
|
}
|
|
}
|
|
|
|
void WriteSpawnCompoundTag() {
|
|
WriteTag( NbtTagType.Compound ); WriteString( "Spawn" );
|
|
LocalPlayer p = game.LocalPlayer;
|
|
Vector3 spawn = p.Position; // TODO: Maybe also keep real spawn too?
|
|
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "X" ); WriteInt16( (short)spawn.X );
|
|
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "Y" ); WriteInt16( (short)spawn.Y );
|
|
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "Z" ); WriteInt16( (short)spawn.Z );
|
|
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "H" );
|
|
WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnYaw, 256 ) );
|
|
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "P" );
|
|
WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnPitch, 256 ) );
|
|
|
|
WriteTag( NbtTagType.End );
|
|
}
|
|
|
|
void WriteMetadata() {
|
|
WriteTag( NbtTagType.Compound ); WriteString( "Metadata" );
|
|
WriteTag( NbtTagType.Compound ); WriteString( "CPE" );
|
|
LocalPlayer p = game.LocalPlayer;
|
|
|
|
WriteCpeExtCompound( "ClickDistance", 1 );
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "Distance" ); WriteInt16( (short)(p.ReachDistance * 32) );
|
|
WriteTag( NbtTagType.End );
|
|
|
|
WriteCpeExtCompound( "EnvWeatherType", 1 );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "WeatherType" ); WriteInt8( (sbyte)((byte)map.Weather) );
|
|
WriteTag( NbtTagType.End );
|
|
|
|
WriteCpeExtCompound( "EnvColors", 1 );
|
|
WriteColourCompound( "Sky", map.SkyCol );
|
|
WriteColourCompound( "Cloud", map.CloudsCol );
|
|
WriteColourCompound( "Fog", map.FogCol );
|
|
WriteColourCompound( "Ambient", map.Shadowlight );
|
|
WriteColourCompound( "Sunlight", map.Sunlight );
|
|
WriteTag( NbtTagType.End );
|
|
|
|
WriteTag( NbtTagType.End );
|
|
WriteTag( NbtTagType.End );
|
|
}
|
|
|
|
void WriteCpeExtCompound( string name, int version ) {
|
|
WriteTag( NbtTagType.Compound ); WriteString( name );
|
|
|
|
WriteTag( NbtTagType.Int32 );
|
|
WriteString( "ExtensionVersion" ); WriteInt32( 1 );
|
|
}
|
|
|
|
void WriteColourCompound( string name, FastColour col ) {
|
|
WriteTag( NbtTagType.Compound ); WriteString( name );
|
|
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "R" ); WriteInt16( col.R );
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "G" ); WriteInt16( col.G );
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "B" ); WriteInt16( col.B );
|
|
|
|
WriteTag( NbtTagType.End );
|
|
}
|
|
|
|
unsafe void WriteCustomBlocksCompound( BlockInfo info, byte id ) {
|
|
WriteTag( NbtTagType.Compound ); WriteString( "CustomBlock" );
|
|
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "ID" ); WriteUInt8( id );
|
|
WriteTag( NbtTagType.String );
|
|
WriteString( "Name" ); WriteString( info.Name[id] );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "CollideType" ); WriteUInt8( (byte)info.CollideType[id] );
|
|
|
|
float speed = info.SpeedMultiplier[id];
|
|
WriteTag( NbtTagType.Real32 );
|
|
WriteString( "Speed" ); WriteInt32( *((int*)&speed) );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "Top" ); WriteUInt8( (byte)info.GetTextureLoc( id, TileSide.Top ) );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "Bottom" ); WriteUInt8( (byte)info.GetTextureLoc( id, TileSide.Bottom ) );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "Left" ); WriteUInt8( (byte)info.GetTextureLoc( id, TileSide.Left ) );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "Right" ); WriteUInt8( (byte)info.GetTextureLoc( id, TileSide.Right ) );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "Front" ); WriteUInt8( (byte)info.GetTextureLoc( id, TileSide.Front ) );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "Back" ); WriteUInt8( (byte)info.GetTextureLoc( id, TileSide.Back ) );
|
|
}
|
|
|
|
void WriteTag( NbtTagType v ) { writer.Write( (byte)v ); }
|
|
void WriteInt64( long v ) { writer.Write( IPAddress.HostToNetworkOrder( v ) ); }
|
|
void WriteInt32( int v ) { writer.Write( IPAddress.HostToNetworkOrder( v ) ); }
|
|
void WriteInt16( short v ) { writer.Write( IPAddress.HostToNetworkOrder( v ) ); }
|
|
void WriteInt8( sbyte v ) { writer.Write( (byte)v ); }
|
|
void WriteUInt8( byte v ) { writer.Write( v ); }
|
|
void WriteBytes( byte[] v ) { writer.Write( v ); }
|
|
|
|
void WriteString( string value ) {
|
|
ushort len = (ushort)value.Length;
|
|
byte[] data = Encoding.UTF8.GetBytes( value );
|
|
WriteInt16( (short)len );
|
|
writer.Write( data );
|
|
}
|
|
}
|
|
} |