mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-08 05:27:33 -04:00
196 lines
6.9 KiB
C#
196 lines
6.9 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
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" ); WriteUInt8( (byte)map.Weather );
|
|
WriteTag( NbtTagType.End );
|
|
|
|
WriteCpeExtCompound( "EnvMapAppearance", 1 );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "SideBlock" ); WriteUInt8( (byte)map.SidesBlock );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "EdgeBlock" ); WriteUInt8( (byte)map.EdgeBlock );
|
|
WriteTag( NbtTagType.Int16 );
|
|
WriteString( "SideLevel" ); WriteInt16( (short)map.EdgeHeight );
|
|
WriteTag( NbtTagType.String );
|
|
string url = game.Map.TextureUrl == null ? "" : game.Map.TextureUrl;
|
|
WriteString( "TextureURL" ); WriteString( url );
|
|
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 );
|
|
|
|
WriteCpeExtCompound( "BlockDefinitions", 1 );
|
|
uint[] flags = game.BlockInfo.DefinedCustomBlocks;
|
|
for( int tile = 1; tile < 256; tile++ ) {
|
|
if( (flags[tile >> 5] & (1u << (tile & 0x1F))) != 0 )
|
|
WriteBlockDefinitionCompound( (byte)tile );
|
|
}
|
|
WriteTag( NbtTagType.End );
|
|
|
|
WriteTag( NbtTagType.End );
|
|
WriteTag( NbtTagType.End );
|
|
}
|
|
|
|
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 WriteBlockDefinitionCompound( byte id ) {
|
|
BlockInfo info = game.BlockInfo;
|
|
WriteTag( NbtTagType.Compound ); WriteString( "Block" + id );
|
|
|
|
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.Int8Array );
|
|
WriteString( "Textures" ); WriteInt32( 6 );
|
|
WriteUInt8( info.GetTextureLoc( id, TileSide.Top ) );
|
|
WriteUInt8( info.GetTextureLoc( id, TileSide.Bottom ) );
|
|
WriteUInt8( info.GetTextureLoc( id, TileSide.Left ) );
|
|
WriteUInt8( info.GetTextureLoc( id, TileSide.Right ) );
|
|
WriteUInt8( info.GetTextureLoc( id, TileSide.Front ) );
|
|
WriteUInt8( info.GetTextureLoc( id, TileSide.Back ) );
|
|
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "TransmitsLight" ); WriteUInt8( info.BlocksLight[id] ? 0 : 1 );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "WalkSound" ); WriteUInt8( (byte)info.DigSounds[id] );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "FullBright" ); WriteUInt8( info.FullBright[id] ? 1 : 0 );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "Shape" ); WriteUInt8( GetShape( info, id ) );
|
|
WriteTag( NbtTagType.Int8 );
|
|
WriteString( "BlockDraw" ); WriteUInt8( GetDraw( info, id ) );
|
|
|
|
FastColour col = info.FogColour[id];
|
|
WriteTag( NbtTagType.Int8Array );
|
|
WriteString( "Fog" ); WriteInt32( 4 );
|
|
WriteUInt8( (byte)(128 * info.FogDensity[id] - 1) );
|
|
WriteUInt8( col.R ); WriteUInt8( col.G ); WriteUInt8( col.B );
|
|
|
|
Vector3 min = info.MinBB[id], max = info.MaxBB[id];
|
|
WriteTag( NbtTagType.Int8Array );
|
|
WriteString( "Coords" ); WriteInt32( 6 );
|
|
WriteUInt8( (byte)(min.X * 16) ); WriteUInt8( (byte)(min.Y * 16) );
|
|
WriteUInt8( (byte)(min.Z * 16) ); WriteUInt8( (byte)(max.X * 16) );
|
|
WriteUInt8( (byte)(max.Y * 16) ); WriteUInt8( (byte)(max.Z * 16) );
|
|
WriteTag( NbtTagType.End );
|
|
}
|
|
|
|
int GetShape( BlockInfo info, byte id ) {
|
|
return info.IsSprite[id] ? 0 : (byte)(info.MaxBB[id].Y * 16);
|
|
}
|
|
|
|
int GetDraw( BlockInfo info, byte id) {
|
|
if( info.IsTranslucent[id] ) return 3;
|
|
if( info.IsAir[id] ) return 4;
|
|
if( info.IsTransparent[id] )
|
|
return info.CullWithNeighbours[id] ? 1 : 2;
|
|
return 0;
|
|
}
|
|
}
|
|
} |