mysimulation/server/tso.files/Tuning.cs

148 lines
4 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using FSO.Files.FAR3;
using System.Globalization;
namespace FSO.Files
{
public struct TuningEntry
{
public string EntryName;
public uint KeyValueCount;
public Dictionary<string, string> KeyValues;
public override string ToString()
{
return EntryName;
}
public float GetNum(string key)
{
CultureInfo floatParse = CultureInfo.InvariantCulture;
return float.Parse(KeyValues[key], floatParse);
}
public static TuningEntry DEFAULT = new TuningEntry
{
EntryName = "",
KeyValueCount = 0,
KeyValues = new Dictionary<string, string>()
};
}
//NOTE: important tuning variables:
//28: object wear repair - important because this stuff doen't run in simantics anymore
//36: sim motive decay
//24: object deprecation
//21: "motivesTunning": regen motives when not online, dead makes motives drain faster...
//17: motive score weights for different lot types
/// <summary>
/// Loader/parser for tuning.dat.
/// </summary>
public class Tuning
{
private BinaryReader m_Reader;
public uint EntryCount = 0;
public Dictionary<string, TuningEntry> EntriesByName = new Dictionary<string, TuningEntry>();
public Tuning(byte[] Data)
{
m_Reader = new BinaryReader(new MemoryStream(Data));
Create(m_Reader);
}
public Tuning(string Path)
{
try
{
m_Reader = new BinaryReader(File.OpenRead(Path));
}
catch(Exception)
{
throw new Exception("Tuning.cs: Invalid path: "+Path);
}
Create(m_Reader);
}
private void Create(BinaryReader Reader)
{
byte BodyType = m_Reader.ReadByte();
if (BodyType != 0x01 && BodyType != 0x03)
throw (new Exception("Tuning.cs: Unknown Persist BodyType!"));
uint DecompressedSize = m_Reader.ReadUInt32();
uint CompressedSize = m_Reader.ReadUInt32();
uint StreamBodySize = m_Reader.ReadUInt32(); //same as compressed size for all current examples
//Note: wiki.niotso.org says this is actually one byte Compressor and four bytes CompressionParameters.
ushort CompressionID = m_Reader.ReadUInt16();
if (CompressionID != 0xFB10)
throw (new Exception("Tuning.cs: Unknown CompressionID!"));
byte[] Dummy = m_Reader.ReadBytes(3);
uint DecompressedSize2 = (uint)((Dummy[0] << 0x10) | (Dummy[1] << 0x08) | +Dummy[2]);
Decompresser Dec = new Decompresser();
Dec.CompressedSize = CompressedSize;
Dec.DecompressedSize = DecompressedSize;
var decompressedData = Dec.Decompress(m_Reader.ReadBytes((int)CompressedSize));
if (decompressedData == null)
throw (new Exception("Tuning.cs: Decompression failed!"));
m_Reader = new BinaryReader(new MemoryStream(decompressedData));
EntryCount = m_Reader.ReadUInt32();
for (int i = 0; i < EntryCount; i++)
{
TuningEntry Entry = new TuningEntry();
Entry.EntryName = DecodeString(m_Reader);
Entry.KeyValueCount = m_Reader.ReadUInt32();
Entry.KeyValues = new Dictionary<string, string>();
for (int j = 0; j < Entry.KeyValueCount; j++)
{
string Key = DecodeString(m_Reader);
string Val = DecodeString(m_Reader);
Entry.KeyValues.Add(Key, Val);
}
EntriesByName.Add(Entry.EntryName.ToLowerInvariant(), Entry);
}
}
/// <summary>
/// Reads a variable-length pascal string offset by 13 characters.
/// </summary>
/// <returns>A decoded string.</returns>
private string DecodeString(BinaryReader reader)
{
int length = 0;
byte last = reader.ReadByte();
byte j = 0;
while ((last & 0x80) > 0)
{
length |= (last&0x7F) << ((j++) * 7);
last = reader.ReadByte();
}
length |= last << ((j++) * 7);
byte[] Chars = reader.ReadBytes(length);
for(int i = 0; i < Chars.Length; i++)
Chars[i] = (byte)(Chars[i] - 13);
return Encoding.ASCII.GetString(Chars);
}
}
}