mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-10-16 10:03:34 -04:00
Added FSO.Files for use with the API server
Don't ask me. FreeSO is the prime example of dependency hell.
This commit is contained in:
parent
4b5e584eeb
commit
8fec258215
104 changed files with 14653 additions and 163 deletions
128
server/tso.files/Utils/BCFReadProxy.cs
Executable file
128
server/tso.files/Utils/BCFReadProxy.cs
Executable file
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
public interface BCFReadProxy : IDisposable
|
||||
{
|
||||
byte ReadByte();
|
||||
ushort ReadUInt16();
|
||||
short ReadInt16();
|
||||
int ReadInt32();
|
||||
uint ReadUInt32();
|
||||
float ReadFloat();
|
||||
string ReadPascalString();
|
||||
string ReadLongPascalString();
|
||||
}
|
||||
|
||||
public interface BCFWriteProxy : IDisposable
|
||||
{
|
||||
void WriteByte(byte data);
|
||||
void WriteUInt16(ushort data);
|
||||
void WriteInt16(short data);
|
||||
void WriteInt32(int data);
|
||||
void WriteUInt32(uint data);
|
||||
void WriteFloat(float data);
|
||||
void WritePascalString(string data);
|
||||
void WriteLongPascalString(string data);
|
||||
|
||||
void SetGrouping(int groupSize);
|
||||
}
|
||||
|
||||
public class BCFReadString : BCFReadProxy
|
||||
{
|
||||
private StreamReader Reader;
|
||||
public int Version;
|
||||
private string[] NumBuf = new string[0];
|
||||
private int NumInd = 1;
|
||||
|
||||
public BCFReadString(Stream input, bool version)
|
||||
{
|
||||
Reader = new StreamReader(input);
|
||||
|
||||
if (!version) return;
|
||||
//skip to version
|
||||
var line = "";
|
||||
while (!line.StartsWith("version "))
|
||||
line = Reader.ReadLine();
|
||||
Version = int.Parse(line.Substring(8));
|
||||
}
|
||||
|
||||
private string ReadNum()
|
||||
{
|
||||
//contrary to popular belief, this function that returns a string does indeed read a number
|
||||
if (NumInd >= NumBuf.Length)
|
||||
{
|
||||
NumBuf = Reader.ReadLine().Trim().Split(' ').ToArray();
|
||||
NumInd = 0;
|
||||
}
|
||||
return NumBuf[NumInd++];
|
||||
}
|
||||
|
||||
public byte ReadByte() { return byte.Parse(ReadNum()); }
|
||||
public ushort ReadUInt16() { return ushort.Parse(ReadNum()); }
|
||||
public short ReadInt16() { return short.Parse(ReadNum()); }
|
||||
public int ReadInt32() { return int.Parse(ReadNum()); }
|
||||
public uint ReadUInt32() { return uint.Parse(ReadNum()); }
|
||||
public float ReadFloat() { return float.Parse(ReadNum(), CultureInfo.InvariantCulture); }
|
||||
public string ReadPascalString() { return Reader.ReadLine(); }
|
||||
public string ReadLongPascalString() { return Reader.ReadLine(); }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Reader.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public class BCFWriteString : BCFWriteProxy
|
||||
{
|
||||
private StreamWriter Writer;
|
||||
public int Version;
|
||||
private int GroupSize = 1;
|
||||
private int GroupInd;
|
||||
|
||||
public BCFWriteString(Stream input, bool version)
|
||||
{
|
||||
Writer = new StreamWriter(input);
|
||||
|
||||
if (!version) return;
|
||||
//write out default version
|
||||
Writer.WriteLine("version 300");
|
||||
}
|
||||
|
||||
public void SetGrouping(int groupSize)
|
||||
{
|
||||
if (GroupInd > 0) Writer.WriteLine();
|
||||
GroupInd = 0;
|
||||
GroupSize = groupSize;
|
||||
}
|
||||
|
||||
private void WriteNum(string num)
|
||||
{
|
||||
if (GroupSize-1 >= GroupInd)
|
||||
{
|
||||
Writer.WriteLine(num);
|
||||
GroupInd = 0;
|
||||
} else
|
||||
{
|
||||
Writer.Write(num + " ");
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteByte(byte data) { WriteNum(data.ToString()); }
|
||||
public void WriteUInt16(ushort data) { WriteNum(data.ToString()); }
|
||||
public void WriteInt16(short data) { WriteNum(data.ToString()); }
|
||||
public void WriteInt32(int data) { WriteNum(data.ToString()); }
|
||||
public void WriteUInt32(uint data) { WriteNum(data.ToString()); }
|
||||
public void WriteFloat(float data) { WriteNum(data.ToString(CultureInfo.InvariantCulture)); }
|
||||
public void WritePascalString(string data) { WriteNum(data); }
|
||||
public void WriteLongPascalString(string data) { WriteNum(data); }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Writer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
74
server/tso.files/Utils/CurLoader.cs
Executable file
74
server/tso.files/Utils/CurLoader.cs
Executable file
|
@ -0,0 +1,74 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
public static class CurLoader
|
||||
{
|
||||
public static MouseCursor LoadMonoCursor(GraphicsDevice gd, Stream stream)
|
||||
{
|
||||
var cur = LoadCursor(gd, stream);
|
||||
return MouseCursor.FromTexture2D(cur.Item1, cur.Item2.X, cur.Item2.Y);
|
||||
}
|
||||
|
||||
public static Tuple<Texture2D, Point> LoadCursor(GraphicsDevice gd, Stream stream)
|
||||
{
|
||||
using (var io = new BinaryReader(stream))
|
||||
{
|
||||
//little endian
|
||||
var tempbmp = new MemoryStream();
|
||||
var outIO = new BinaryWriter(tempbmp);
|
||||
|
||||
var reserved = io.ReadInt16();
|
||||
var type = io.ReadInt16();
|
||||
if (type != 2) throw new Exception("Not a cursor!");
|
||||
var images = io.ReadInt16(); //currently discard extra images...
|
||||
|
||||
//read first image
|
||||
var width = io.ReadByte();
|
||||
var height = io.ReadByte();
|
||||
var colors = io.ReadByte();
|
||||
var reserved2 = io.ReadByte();
|
||||
var xOffset = io.ReadInt16();
|
||||
var yOffset = io.ReadInt16();
|
||||
var size = io.ReadInt32();
|
||||
var offset = io.ReadInt32();
|
||||
stream.Seek(offset - 22, SeekOrigin.Current);
|
||||
|
||||
//ok... now write the bitmap data to a fake bitmap
|
||||
outIO.Write(new char[] { 'B', 'M' });
|
||||
outIO.Write(size + 14); //size, plus header
|
||||
outIO.Write(0);
|
||||
outIO.Write(14);
|
||||
var data = new byte[size];
|
||||
stream.Read(data, 0, size);
|
||||
outIO.Write(data);
|
||||
|
||||
tempbmp.Seek(0, SeekOrigin.Begin);
|
||||
var tex = ImageLoader.FromStream(gd, tempbmp);
|
||||
|
||||
//our mask is on top. the image is on bottom.
|
||||
var odata = new byte[tex.Width * tex.Height * 4];
|
||||
tex.GetData(odata);
|
||||
var ndata = new byte[tex.Width * tex.Height * 2];
|
||||
var limit = ndata.Length;
|
||||
for (int i=0; i< limit; i+=4)
|
||||
{
|
||||
var j = i + limit;
|
||||
ndata[i] = (byte)((~odata[i]) & odata[j]);
|
||||
ndata[i+1] = ndata[i];
|
||||
ndata[i+2] = ndata[i];
|
||||
ndata[i+3] = (byte)(~odata[i]);
|
||||
}
|
||||
var oTex = new Texture2D(gd, width, height);
|
||||
oTex.SetData(ndata);
|
||||
tex.Dispose();
|
||||
|
||||
return new Tuple<Texture2D, Point>(oTex, new Point(xOffset, yOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
130
server/tso.files/Utils/DiffGenerator.cs
Executable file
130
server/tso.files/Utils/DiffGenerator.cs
Executable file
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using xxHashSharp;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
public class DiffGenerator
|
||||
{
|
||||
public HashSet<string> SourceFiles; //aka before
|
||||
public HashSet<string> DestFiles; //aka after
|
||||
|
||||
public HashSet<string> AddFiles;
|
||||
public HashSet<string> RemovedFiles;
|
||||
public HashSet<string> SameFiles;
|
||||
|
||||
public string SourcePath;
|
||||
public string DestPath;
|
||||
|
||||
public static List<FileDiff> GetDiffs(string sourcePath, string destPath)
|
||||
{
|
||||
var sourceFiles = new HashSet<string>();
|
||||
RecursiveDirectoryScan(sourcePath, sourceFiles, sourcePath);
|
||||
|
||||
var destFiles = new HashSet<string>();
|
||||
RecursiveDirectoryScan(destPath, destFiles, destPath);
|
||||
|
||||
var addFiles = new HashSet<string>(destFiles);
|
||||
addFiles.ExceptWith(sourceFiles);
|
||||
|
||||
var removedFiles = new HashSet<string>(sourceFiles);
|
||||
removedFiles.ExceptWith(destFiles);
|
||||
|
||||
var sameFiles = new HashSet<string>(sourceFiles);
|
||||
sameFiles.IntersectWith(destFiles);
|
||||
|
||||
var diffs = new List<FileDiff>();
|
||||
|
||||
foreach (var removed in removedFiles)
|
||||
{
|
||||
var bytes = GetFileBytes(Path.Combine(sourcePath, removed));
|
||||
var hash = xxHash.CalculateHash(bytes).ToString("x8");
|
||||
diffs.Add(new FileDiff(FileDiffType.Remove, removed, hash, null));
|
||||
}
|
||||
|
||||
foreach (var added in addFiles)
|
||||
{
|
||||
var bytes = GetFileBytes(Path.Combine(destPath, added));
|
||||
var hash = xxHash.CalculateHash(bytes).ToString("x8");
|
||||
diffs.Add(new FileDiff(FileDiffType.Add, added, null, hash));
|
||||
}
|
||||
|
||||
foreach (var same in sameFiles)
|
||||
{
|
||||
var bytesBefore = GetFileBytes(Path.Combine(sourcePath, same));
|
||||
var bytesAfter = GetFileBytes(Path.Combine(destPath, same));
|
||||
var hashBefore = xxHash.CalculateHash(bytesBefore).ToString("x8");
|
||||
var hashAfter = xxHash.CalculateHash(bytesAfter).ToString("x8");
|
||||
diffs.Add(new FileDiff(
|
||||
(hashBefore == hashAfter) ? FileDiffType.Unchanged : FileDiffType.Modify,
|
||||
same, hashBefore, hashAfter));
|
||||
}
|
||||
|
||||
return diffs;
|
||||
}
|
||||
|
||||
private static byte[] GetFileBytes(string path)
|
||||
{
|
||||
using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
var memory = new MemoryStream();
|
||||
stream.CopyTo(memory);
|
||||
var bytes = memory.ToArray();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RecursiveDirectoryScan(string folder, HashSet<string> fileNames, string basePath)
|
||||
{
|
||||
var files = Directory.GetFiles(folder);
|
||||
foreach (var file in files)
|
||||
{
|
||||
fileNames.Add(GetRelativePath(basePath, file));
|
||||
}
|
||||
|
||||
var dirs = Directory.GetDirectories(folder);
|
||||
foreach (var dir in dirs)
|
||||
{
|
||||
RecursiveDirectoryScan(dir, fileNames, basePath);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetRelativePath(string relativeTo, string path)
|
||||
{
|
||||
if (!(relativeTo.EndsWith("/") || relativeTo.EndsWith("\\"))) relativeTo += "/";
|
||||
var uri = new Uri(relativeTo);
|
||||
|
||||
var rel = Uri.UnescapeDataString(uri.MakeRelativeUri(new Uri(path)).ToString()).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
if (rel.Contains(Path.DirectorySeparatorChar.ToString()) == false)
|
||||
{
|
||||
rel = $".{ Path.DirectorySeparatorChar }{ rel }";
|
||||
}
|
||||
return rel;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileDiff
|
||||
{
|
||||
public FileDiffType DiffType;
|
||||
public string Path;
|
||||
public string BeforeHash;
|
||||
public string AfterHash;
|
||||
|
||||
public FileDiff(FileDiffType type, string path, string beforeHash, string afterHash)
|
||||
{
|
||||
DiffType = type;
|
||||
Path = path;
|
||||
BeforeHash = beforeHash;
|
||||
AfterHash = afterHash;
|
||||
}
|
||||
}
|
||||
|
||||
public enum FileDiffType
|
||||
{
|
||||
Add, //after hash only
|
||||
Modify,
|
||||
Remove, //before hash only
|
||||
Unchanged
|
||||
}
|
||||
}
|
7
server/tso.files/Utils/IFileInfoUtilizer.cs
Executable file
7
server/tso.files/Utils/IFileInfoUtilizer.cs
Executable file
|
@ -0,0 +1,7 @@
|
|||
namespace FSO.Files.Utils
|
||||
{
|
||||
public interface IFileInfoUtilizer
|
||||
{
|
||||
void SetFilename(string filename);
|
||||
}
|
||||
}
|
9
server/tso.files/Utils/ITextureProvider.cs
Executable file
9
server/tso.files/Utils/ITextureProvider.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
public interface ITextureProvider
|
||||
{
|
||||
Texture2D GetTexture(GraphicsDevice device);
|
||||
}
|
||||
}
|
9
server/tso.files/Utils/IWorldTextureProvider.cs
Executable file
9
server/tso.files/Utils/IWorldTextureProvider.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
public interface IWorldTextureProvider
|
||||
{
|
||||
WorldTexture GetWorldTexture(GraphicsDevice device);
|
||||
}
|
||||
}
|
357
server/tso.files/Utils/IoBuffer.cs
Executable file
357
server/tso.files/Utils/IoBuffer.cs
Executable file
|
@ -0,0 +1,357 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// The order to read bytes in.
|
||||
/// </summary>
|
||||
public enum ByteOrder
|
||||
{
|
||||
BIG_ENDIAN,
|
||||
LITTLE_ENDIAN
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IOBuffer is a very basic wrapper over System.BinaryReader that inherits from IDisposable.
|
||||
/// </summary>
|
||||
public class IoBuffer : IDisposable, BCFReadProxy
|
||||
{
|
||||
private Stream Stream;
|
||||
private BinaryReader Reader;
|
||||
public ByteOrder ByteOrder = ByteOrder.BIG_ENDIAN;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
public IoBuffer(Stream stream)
|
||||
{
|
||||
this.Stream = stream;
|
||||
this.Reader = new BinaryReader(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// More to read in this stream?
|
||||
/// </summary>
|
||||
public bool HasMore
|
||||
{
|
||||
get
|
||||
{
|
||||
return Stream.Position < Stream.Length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skips a number of bytes in the current stream, starting from the current position.
|
||||
/// </summary>
|
||||
/// <param name="numBytes">Number of bytes to skip.</param>
|
||||
public void Skip(long numBytes)
|
||||
{
|
||||
Reader.BaseStream.Seek(numBytes, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks in the current stream.
|
||||
/// </summary>
|
||||
/// <param name="origin">Where to start from.</param>
|
||||
/// <param name="offset">The offset to seek to.</param>
|
||||
public void Seek(SeekOrigin origin, long offset)
|
||||
{
|
||||
Reader.BaseStream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public long Position => Stream.Position;
|
||||
|
||||
/// <summary>
|
||||
/// Reads a variable length unsigned integer from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A uint.</returns>
|
||||
public uint ReadVarLen()
|
||||
{
|
||||
uint result = 0;
|
||||
int shift = 0;
|
||||
byte read = 0x80;
|
||||
while ((read&0x80) > 0)
|
||||
{
|
||||
read = ReadByte();
|
||||
result |= (uint)((read & 0x7F) << shift);
|
||||
shift += 7;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an unsigned 16bit integer from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A ushort.</returns>
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
var value = Reader.ReadUInt16();
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapUInt16(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 16bit integer from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A short.</returns>
|
||||
public short ReadInt16()
|
||||
{
|
||||
var value = Reader.ReadInt16();
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapInt16(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 32bit integer from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>An int.</returns>
|
||||
public int ReadInt32()
|
||||
{
|
||||
var value = Reader.ReadInt32();
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapInt32(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 64bit integer from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>An int.</returns>
|
||||
public long ReadInt64()
|
||||
{
|
||||
var value = Reader.ReadInt64();
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapInt64(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an unsigned 32bit integer from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A uint.</returns>
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
var value = Reader.ReadUInt32();
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapUInt32(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a number of ASCII characters from the current stream.
|
||||
/// </summary>
|
||||
/// <param name="num">The number of characters to read.</param>
|
||||
/// <returns>A string, INCLUDING the trailing 0.</returns>
|
||||
public string ReadCString(int num)
|
||||
{
|
||||
return ReadCString(num, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a number of ASCII characters from the current stream.
|
||||
/// </summary>
|
||||
/// <param name="num">The number of characters to read.</param>
|
||||
/// <param name="trimNull">Trim the trailing 0?</param>
|
||||
/// <returns>A string, with or without the trailing 0.</returns>
|
||||
public string ReadCString(int num, bool trimNull)
|
||||
{
|
||||
var result = ASCIIEncoding.ASCII.GetString(Reader.ReadBytes(num));
|
||||
if (trimNull)
|
||||
{
|
||||
/** Trim on \0 **/
|
||||
var io = result.IndexOf('\0');
|
||||
if (io != -1)
|
||||
{
|
||||
result = result.Substring(0, io);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A byte.</returns>
|
||||
public byte ReadByte()
|
||||
{
|
||||
return Reader.ReadByte();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a number of bytes from the current stream.
|
||||
/// </summary>
|
||||
/// <param name="num">Number of bytes to read.</param>
|
||||
/// <returns>An byte array.</returns>
|
||||
public byte[] ReadBytes(uint num)
|
||||
{
|
||||
return Reader.ReadBytes((int)num);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a number of bytes from the current stream.
|
||||
/// </summary>
|
||||
/// <param name="num">Number of bytes to read.</param>
|
||||
/// <returns>An byte array.</returns>
|
||||
public byte[] ReadBytes(int num)
|
||||
{
|
||||
return Reader.ReadBytes(num);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a pascal string from the current stream, which is prefixed by a 16bit short.
|
||||
/// </summary>
|
||||
/// <returns>A string.</returns>
|
||||
public string ReadLongPascalString()
|
||||
{
|
||||
var length = ReadInt16();
|
||||
return Encoding.ASCII.GetString(Reader.ReadBytes(length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a C string from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A string.</returns>
|
||||
public string ReadNullTerminatedString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
while (true){
|
||||
char ch = (char)Reader.ReadByte();
|
||||
if (ch == '\0'){
|
||||
break;
|
||||
}
|
||||
sb.Append(ch);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ReadNullTerminatedUTF8()
|
||||
{
|
||||
var sb = new List<byte>();
|
||||
while (true)
|
||||
{
|
||||
var b = Reader.ReadByte();
|
||||
if (b == 0) break;
|
||||
sb.Add(b);
|
||||
}
|
||||
return Encoding.UTF8.GetString(sb.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a pascal string from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A string.</returns>
|
||||
public string ReadVariableLengthPascalString()
|
||||
{
|
||||
return Reader.ReadString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a pascal string from the current stream, prefixed by a byte.
|
||||
/// </summary>
|
||||
/// <returns>A string.</returns>
|
||||
public string ReadPascalString()
|
||||
{
|
||||
var length = ReadByte();
|
||||
return Encoding.ASCII.GetString(Reader.ReadBytes(length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a float from the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A float.</returns>
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public virtual unsafe float ReadFloat()
|
||||
{
|
||||
return Reader.ReadSingle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a mark at the current position in the stream.
|
||||
/// </summary>
|
||||
private long _Mark;
|
||||
public void Mark()
|
||||
{
|
||||
_Mark = Reader.BaseStream.Position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks in the current stream from the current mark plus the number of bytes.
|
||||
/// </summary>
|
||||
/// <param name="numBytes">The number of bytes to add to the offset (mark).</param>
|
||||
public void SeekFromMark(long numBytes)
|
||||
{
|
||||
Reader.BaseStream.Seek(_Mark + numBytes, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream.</param>
|
||||
/// <returns>A new IOBuffer instance.</returns>
|
||||
public static IoBuffer FromStream(Stream stream)
|
||||
{
|
||||
return new IoBuffer(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a stream, using a specified byte order.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream.</param>
|
||||
/// <param name="order">Byte order to use.</param>
|
||||
/// <returns>A new IOBuffer instance.</returns>
|
||||
public static IoBuffer FromStream(Stream stream, ByteOrder order)
|
||||
{
|
||||
var item = FromStream(stream);
|
||||
item.ByteOrder = order;
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a byte array.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to use.</param>
|
||||
/// <returns>A new IOBuffer instance.</returns>
|
||||
public static IoBuffer FromBytes(byte[] bytes)
|
||||
{
|
||||
return FromStream(new MemoryStream(bytes));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a byte array, using a specified byte order.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to use.</param>
|
||||
/// <param name="order">Byte order to use.</param>
|
||||
/// <returns>A new IOBuffer instance.</returns>
|
||||
public static IoBuffer FromBytes(byte[] bytes, ByteOrder order)
|
||||
{
|
||||
return FromStream(new MemoryStream(bytes), order);
|
||||
}
|
||||
}
|
||||
}
|
284
server/tso.files/Utils/IoWriter.cs
Executable file
284
server/tso.files/Utils/IoWriter.cs
Executable file
|
@ -0,0 +1,284 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// IOBuffer is a very basic wrapper over System.BinaryReader that inherits from IDisposable.
|
||||
/// </summary>
|
||||
public class IoWriter : IDisposable, BCFWriteProxy
|
||||
{
|
||||
private Stream Stream;
|
||||
private BinaryWriter Writer;
|
||||
private bool FloatSwap = false;
|
||||
public ByteOrder ByteOrder = ByteOrder.BIG_ENDIAN;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
public IoWriter(Stream stream)
|
||||
{
|
||||
this.Stream = stream;
|
||||
this.Writer = new BinaryWriter(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// More to read in this stream?
|
||||
/// </summary>
|
||||
public bool HasMore
|
||||
{
|
||||
get
|
||||
{
|
||||
return Stream.Position < Stream.Length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skips a number of bytes in the current stream, starting from the current position.
|
||||
/// </summary>
|
||||
/// <param name="numBytes">Number of bytes to skip.</param>
|
||||
public void Skip(long numBytes)
|
||||
{
|
||||
Writer.BaseStream.Seek(numBytes, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks in the current stream.
|
||||
/// </summary>
|
||||
/// <param name="origin">Where to start from.</param>
|
||||
/// <param name="offset">The offset to seek to.</param>
|
||||
public void Seek(SeekOrigin origin, long offset)
|
||||
{
|
||||
Writer.BaseStream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a variable length unsigned integer to the current stream
|
||||
/// </summary>
|
||||
/// <param name="value">Value to write.</param>
|
||||
public void WriteVarLen(uint value)
|
||||
{
|
||||
bool first = true;
|
||||
while (value > 0 || first)
|
||||
{
|
||||
WriteByte((byte)(((value > 127)?(uint)128:0) | (value & 127)));
|
||||
value >>= 7;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an unsigned 16bit integer to the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A ushort.</returns>
|
||||
public void WriteUInt16(ushort value)
|
||||
{
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapUInt16(value);
|
||||
}
|
||||
Writer.Write(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 16bit integer to the current stream.
|
||||
/// </summary>
|
||||
/// <returns>A short.</returns>
|
||||
public void WriteInt16(short value)
|
||||
{
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapInt16(value);
|
||||
}
|
||||
Writer.Write(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 32bit integer to the current stream.
|
||||
/// </summary>
|
||||
/// <returns>An int.</returns>
|
||||
public void WriteInt32(int value)
|
||||
{
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapInt32(value);
|
||||
}
|
||||
Writer.Write(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 32bit integer to the current stream.
|
||||
/// </summary>
|
||||
/// <returns>An int.</returns>
|
||||
public void WriteInt64(long value)
|
||||
{
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapInt64(value);
|
||||
}
|
||||
Writer.Write(value);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes an unsigned 32bit integer from to current stream.
|
||||
/// </summary>
|
||||
/// <returns>A uint.</returns>
|
||||
public void WriteUInt32(uint value)
|
||||
{
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN)
|
||||
{
|
||||
value = Endian.SwapUInt32(value);
|
||||
}
|
||||
Writer.Write(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a number of ASCII characters to the current stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to write.</param>
|
||||
/// <param name="num">The number of bytes to write into.</param>
|
||||
public void WriteCString(string value, int num)
|
||||
{
|
||||
value = value.PadRight(num, '\0');
|
||||
Writer.Write(ASCIIEncoding.ASCII.GetBytes(value));
|
||||
}
|
||||
|
||||
public void WriteCString(string value)
|
||||
{
|
||||
WriteCString(value, value.Length + 1);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes a byte to the current stream.
|
||||
/// </summary>
|
||||
public void WriteByte(byte value)
|
||||
{
|
||||
Writer.Write(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a number of bytes to the current stream.
|
||||
/// </summary>
|
||||
/// <param name="bytes">Bytes to write out.</param>
|
||||
public void WriteBytes(byte[] bytes)
|
||||
{
|
||||
Writer.Write(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a pascal string to the current stream, which is prefixed by a 16bit short.
|
||||
/// </summary>
|
||||
public void WriteLongPascalString(string value)
|
||||
{
|
||||
WriteInt16((short)value.Length);
|
||||
WriteBytes(Encoding.ASCII.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a C string to the current stream.
|
||||
/// </summary>
|
||||
public void WriteNullTerminatedString(string value)
|
||||
{
|
||||
if (value != null) WriteBytes(Encoding.ASCII.GetBytes(value));
|
||||
WriteByte(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a pascal string to the current stream.
|
||||
/// </summary>
|
||||
public void WriteVariableLengthPascalString(string value)
|
||||
{
|
||||
Writer.Write((value == null)?"":value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a pascal string to the current stream, prefixed by a byte.
|
||||
/// </summary>
|
||||
public void WritePascalString(string value)
|
||||
{
|
||||
WriteByte((byte)value.Length);
|
||||
WriteBytes(Encoding.ASCII.GetBytes(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a float to the current stream.
|
||||
/// </summary>
|
||||
public void WriteFloat(float value)
|
||||
{
|
||||
var bytes = BitConverter.GetBytes(value);
|
||||
|
||||
if (ByteOrder == ByteOrder.BIG_ENDIAN && FloatSwap)
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
Writer.Write(bytes);
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IoWriter instance from a stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream.</param>
|
||||
/// <returns>A new IoWriter instance.</returns>
|
||||
public static IoWriter FromStream(Stream stream)
|
||||
{
|
||||
return new IoWriter(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IoWriter instance from a stream, using a specified byte order.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream.</param>
|
||||
/// <param name="order">Byte order to use.</param>
|
||||
/// <returns>A new IoWriter instance.</returns>
|
||||
public static IoWriter FromStream(Stream stream, ByteOrder order)
|
||||
{
|
||||
var item = FromStream(stream);
|
||||
item.ByteOrder = order;
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a byte array.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to use.</param>
|
||||
/// <returns>A new IOBuffer instance.</returns>
|
||||
public static IoWriter FromBytes(byte[] bytes)
|
||||
{
|
||||
return FromStream(new MemoryStream(bytes));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new IOBuffer instance from a byte array, using a specified byte order.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to use.</param>
|
||||
/// <param name="order">Byte order to use.</param>
|
||||
/// <returns>A new IOBuffer instance.</returns>
|
||||
public static IoWriter FromBytes(byte[] bytes, ByteOrder order)
|
||||
{
|
||||
return FromStream(new MemoryStream(bytes), order);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by BCFWriteProxy's string mode, but does not do anything here.
|
||||
/// </summary>
|
||||
/// <param name="groupSize">The size of value groups</param>
|
||||
public void SetGrouping(int groupSize)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
13
server/tso.files/Utils/WorldTexture.cs
Executable file
13
server/tso.files/Utils/WorldTexture.cs
Executable file
|
@ -0,0 +1,13 @@
|
|||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace FSO.Files.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// A texture used in the game world.
|
||||
/// </summary>
|
||||
public class WorldTexture
|
||||
{
|
||||
public Texture2D Pixel;
|
||||
public Texture2D ZBuffer;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue