mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-24 01:52:24 -05:00
Create .lvl and .fcm level exporter.
This commit is contained in:
parent
d74dc198e9
commit
f5878f70a3
8 changed files with 157 additions and 8 deletions
|
@ -174,6 +174,8 @@
|
|||
<Compile Include="Generator\NotchyGenerator.cs" />
|
||||
<Compile Include="Generator\NotchyGenerator.Utils.cs" />
|
||||
<Compile Include="GraphicsAPI\OpenGLESApi.cs" />
|
||||
<Compile Include="Map\Formats\MapFcm3.Exporter.cs" />
|
||||
<Compile Include="Map\Formats\MapLvl.Exporter.cs" />
|
||||
<Compile Include="Map\Formats\MapLvl.Importer.cs" />
|
||||
<Compile Include="Map\Formats\NbtFile.cs" />
|
||||
<Compile Include="Math\RayTracer.cs" />
|
||||
|
@ -208,7 +210,7 @@
|
|||
<Compile Include="Map\ChunkMeshBuilder.cs" />
|
||||
<Compile Include="Map\ChunkMeshBuilder.FloodFill.cs" />
|
||||
<Compile Include="Map\ChunkMeshBuilderTex2Col4.cs" />
|
||||
<Compile Include="Map\Formats\IMapFileFormat.cs" />
|
||||
<Compile Include="Map\Formats\IMapFormat.cs" />
|
||||
<Compile Include="Map\Formats\MapCw.Exporter.cs" />
|
||||
<Compile Include="Map\Formats\MapCw.Importer.cs" />
|
||||
<Compile Include="Map\Formats\MapDat.Importer.cs" />
|
||||
|
|
|
@ -67,11 +67,11 @@ namespace ClassicalSharp.Map {
|
|||
|
||||
nbt.Write( NbtTagType.Int8 );
|
||||
nbt.Write( "H" );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnYaw, 256 ) );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnYaw ) );
|
||||
|
||||
nbt.Write( NbtTagType.Int8 );
|
||||
nbt.Write( "P" );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnPitch, 256 ) );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnPitch ) );
|
||||
|
||||
nbt.Write( NbtTagType.End );
|
||||
}
|
||||
|
|
69
ClassicalSharp/Map/Formats/MapFcm3.Exporter.cs
Normal file
69
ClassicalSharp/Map/Formats/MapFcm3.Exporter.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
// 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;
|
||||
using ClassicalSharp.Entities;
|
||||
|
||||
namespace ClassicalSharp.Map {
|
||||
|
||||
/// <summary> Exports a world to a FCMv3 map file (fCraft server map) </summary>
|
||||
public sealed class MapFcm3Exporter : IMapFormatExporter {
|
||||
|
||||
const uint Identifier = 0x0FC2AF40;
|
||||
const byte Revision = 13;
|
||||
const int chunkSize = 128 * 128 * 128;
|
||||
|
||||
public void Save( Stream stream, Game game ) {
|
||||
World map = game.World;
|
||||
LocalPlayer p = game.LocalPlayer;
|
||||
BinaryWriter writer = new BinaryWriter( stream );
|
||||
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.Spawn.X * 32) );
|
||||
writer.Write( (int)(p.Spawn.Y * 32) );
|
||||
writer.Write( (int)(p.Spawn.Z * 32) );
|
||||
|
||||
writer.Write( Utils.DegreesToPacked( p.SpawnYaw ) );
|
||||
writer.Write( Utils.DegreesToPacked( p.SpawnPitch ) );
|
||||
|
||||
writer.Write( 0 ); // Date modified
|
||||
writer.Write( 0 ); // Date created
|
||||
|
||||
writer.Write( map.Uuid.ToByteArray() );
|
||||
writer.Write( (byte)1 ); // layer count
|
||||
|
||||
// skip over index and metacount
|
||||
long indexOffset = stream.Position;
|
||||
writer.Seek( 29, SeekOrigin.Current );
|
||||
long offset = stream.Position;
|
||||
byte[] blocks = map.mapData;
|
||||
|
||||
using( DeflateStream ds = new DeflateStream( stream, CompressionMode.Compress, true ) ) {
|
||||
for( int i = 0; i < blocks.Length; i += chunkSize ) {
|
||||
int len = Math.Min( chunkSize, blocks.Length - i );
|
||||
ds.Write( blocks, i, len );
|
||||
}
|
||||
}
|
||||
int compressedLength = (int)(stream.Position - offset);
|
||||
|
||||
// come back to write the index
|
||||
writer.BaseStream.Seek( indexOffset, SeekOrigin.Begin );
|
||||
|
||||
writer.Write( (byte)0 ); // data layer type (Blocks)
|
||||
writer.Write( offset ); // offset, in bytes, from start of stream
|
||||
writer.Write( compressedLength ); // compressed length, in bytes
|
||||
writer.Write( 0 ); // general purpose field
|
||||
writer.Write( 1 ); // element size
|
||||
writer.Write( map.mapData.Length ); // element count
|
||||
|
||||
writer.Write( 0 ); // No metadata
|
||||
}
|
||||
}
|
||||
}
|
72
ClassicalSharp/Map/Formats/MapLvl.Exporter.cs
Normal file
72
ClassicalSharp/Map/Formats/MapLvl.Exporter.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using ClassicalSharp.Entities;
|
||||
using ClassicalSharp.Net;
|
||||
|
||||
namespace ClassicalSharp.Map {
|
||||
|
||||
/// <summary> Exports a world to a LVL map file (MCLawl server map) </summary>
|
||||
public sealed class MapLvlExporter : IMapFormatExporter {
|
||||
|
||||
const int Version = 1874;
|
||||
const byte customTile = 163;
|
||||
|
||||
public void Save( Stream stream, Game game ) {
|
||||
World map = game.World;
|
||||
LocalPlayer p = game.LocalPlayer;
|
||||
const int chunkSize = 128 * 128 * 128;
|
||||
|
||||
using( DeflateStream gs = new DeflateStream( stream, CompressionMode.Compress ) ) {
|
||||
BinaryWriter writer = new BinaryWriter( gs );
|
||||
|
||||
writer.Write( (ushort)Version );
|
||||
writer.Write( (ushort)map.Width );
|
||||
writer.Write( (ushort)map.Length );
|
||||
writer.Write( (ushort)map.Height );
|
||||
|
||||
writer.Write( (ushort)p.Spawn.X );
|
||||
writer.Write( (ushort)p.Spawn.Z );
|
||||
writer.Write( (ushort)p.Spawn.Y );
|
||||
writer.Write( Utils.DegreesToPacked( p.SpawnYaw ) );
|
||||
writer.Write( Utils.DegreesToPacked( p.SpawnPitch ) );
|
||||
|
||||
writer.Write( (ushort)0 ); // pervisit and perbuild perms
|
||||
WriteBlocks( map.mapData, writer );
|
||||
|
||||
writer.Write( (byte)0xBD );
|
||||
WriteCustomBlocks( map, writer );
|
||||
}
|
||||
}
|
||||
|
||||
void WriteBlocks( byte[] blocks, BinaryWriter writer ) {
|
||||
const int bufferSize = 64 * 1024;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int bIndex = 0;
|
||||
|
||||
for( int i = 0; i < blocks.Length; i++ ) {
|
||||
byte block = blocks[i];
|
||||
buffer[bIndex] = block >= BlockInfo.CpeBlocksCount ? customTile : block;
|
||||
|
||||
bIndex++;
|
||||
if( bIndex == bufferSize ) {
|
||||
writer.Write( buffer, 0, bufferSize ); bIndex = 0;
|
||||
}
|
||||
}
|
||||
if( bIndex > 0 ) writer.Write( buffer, 0, bIndex );
|
||||
}
|
||||
|
||||
void WriteCustomBlocks( World map, BinaryWriter writer ) {
|
||||
byte[] chunk = new byte[16 * 16 * 16];
|
||||
|
||||
for( int y = 0; y < map.Height; y += 16 )
|
||||
for( int z = 0; z < map.Length; z += 16 )
|
||||
for( int x = 0; x < map.Width; x += 16 )
|
||||
{
|
||||
writer.Write( (byte)0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ namespace ClassicalSharp.Map {
|
|||
public sealed class MapLvlImporter : IMapFormatImporter {
|
||||
|
||||
const int Version = 1874;
|
||||
const byte customTile = 163;
|
||||
|
||||
public byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {
|
||||
GZipHeaderReader gsHeader = new GZipHeaderReader();
|
||||
while( !gsHeader.ReadHeader( stream ) ) { }
|
||||
|
@ -59,7 +61,7 @@ namespace ClassicalSharp.Map {
|
|||
int bx = i & 0xF, by = (i >> 8) & 0xF, bz = (i >> 4) & 0xF;
|
||||
int index = baseIndex + (by * length + bz) * width + bx;
|
||||
|
||||
if( blocks[index] == 163 ) // custom block id
|
||||
if( blocks[index] == customTile )
|
||||
blocks[index] = chunk[i];
|
||||
}
|
||||
}
|
||||
|
@ -82,8 +84,8 @@ namespace ClassicalSharp.Map {
|
|||
34, 35, 36, 22, 20, 49, 45, 1, 4, 0, 9, 11, 4, 19, 5, 17, 10, 49, 20, 1,
|
||||
18, 12, 5, 25, 46, 44, 17, 49, 20, 1, 18, 12, 5, 25, 36, 34, 0, 9, 11, 46,
|
||||
44, 0, 9, 11, 8, 10, 22, 27, 22, 8, 10, 28, 17, 49, 20, 1, 18, 12, 5, 25, 46,
|
||||
44, 11, 9, 0, 9, 11, 163, 0, 0, 9, 11, 0, 0, 0, 0, 0, 0, 0, 28, 22, 21, 11,
|
||||
0, 0, 0, 46, 46, 10, 10, 46, 20, 41, 42, 11, 9, 0, 8, 10, 10, 8, 0, 22, 22,
|
||||
44, 11, 9, 0, 9, 11, customTile, 0, 0, 9, 11, 0, 0, 0, 0, 0, 0, 0, 28, 22, 21,
|
||||
11, 0, 0, 0, 46, 46, 10, 10, 46, 20, 41, 42, 11, 9, 0, 8, 10, 10, 8, 0, 22, 22,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 22, 22, 42, 3, 2, 29,
|
||||
47, 0, 0, 0, 0, 0, 27, 46, 48, 24, 22, 36, 34, 8, 10, 21, 29, 22, 10, 22, 22,
|
||||
41, 19, 35, 21, 29, 49, 34, 16, 41, 0, 22 };
|
||||
|
|
|
@ -57,8 +57,8 @@ namespace ClassicalSharp.Net {
|
|||
writer.WriteInt16( (short)(pos.X * 32) );
|
||||
writer.WriteInt16( (short)((int)(pos.Y * 32) + 51) );
|
||||
writer.WriteInt16( (short)(pos.Z * 32) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( yaw, 256 ) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( pitch, 256 ) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( yaw ) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( pitch ) );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -150,6 +150,10 @@ namespace ClassicalSharp {
|
|||
return (int)(degrees * period / 360.0) % period;
|
||||
}
|
||||
|
||||
public static int DegreesToPacked( double degrees ) {
|
||||
return (int)(degrees * 256 / 360.0) & 0xFF;
|
||||
}
|
||||
|
||||
public static double PackedToDegrees( byte packed ) {
|
||||
return packed * 360.0 / 256.0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue