Modular Database Upgrade

CultCache API can now be configured with multiple interchangeable backing stores. Will be using plain JSON in repository from now on.
This commit is contained in:
Reinier Vens 2021-06-23 04:25:23 +01:00
commit 85483319fe
158 changed files with 658 additions and 290 deletions

View file

@ -59,12 +59,12 @@ Material:
- _AlphaFloor: 0.01
- _DepthBlend: 512
- _DepthCeiling: 4096
- _Exposure: 2
- _Exposure: 10
- _FlowAmplitude: 512
- _FlowScale: 1024
- _FlowScroll: 0
- _FlowSpeed: 1
- _Gamma: 0.5
- _Gamma: 0.3
- _GridCeilingBlend: -300
- _GridCeilingDensity: 0.01
- _GridCeilingFollow: 0
@ -91,7 +91,7 @@ Material:
- _ScatteringDistExponent: 1.5
- _ScatteringMinDist: 10
- _StepExponent: 2
- _TintExponent: 1.2
- _TintExponent: 2
- _TurbulenceAmplitude: 20
- _TurbulenceScale: 60
m_Colors:

View file

@ -86,7 +86,7 @@ Material:
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Scale: 1.6688799
- _Scale: 12.242577
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

View file

@ -23731,12 +23731,12 @@ PrefabInstance:
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchorMax.y
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchorMin.y
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
@ -23751,12 +23751,12 @@ PrefabInstance:
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 55.675
value: 0
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchoredPosition.y
value: -16
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1713457305180270767, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
@ -24943,12 +24943,12 @@ PrefabInstance:
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchorMax.y
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchorMin.y
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
@ -24963,12 +24963,12 @@ PrefabInstance:
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 60.98
value: 0
objectReference: {fileID: 0}
- target: {fileID: 878382121558056004, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}
propertyPath: m_AnchoredPosition.y
value: -16
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1713457305180270767, guid: 2758dfa2744d7ad4d8877545189d116e,
type: 3}

View file

@ -18,7 +18,7 @@ public class AetheriaDatabaseView : DatabaseListView
protected override string DatabaseName => "Aetheria";
protected override string FilePath => Path.Combine(new DirectoryInfo(Application.dataPath).Parent.CreateSubdirectory("GameData").FullName, "AetherDB.msgpack");
protected override string FilePath => new DirectoryInfo(Application.dataPath).Parent.CreateSubdirectory("GameData").FullName;
protected override DatabaseEntryGroup[] Groupers => new DatabaseEntryGroup[]
{

View file

@ -44,8 +44,7 @@ public class DatabaseInspector : EditorWindow
void OnEnable()
{
_instance = this;
CultCache.OnDataUpdateLocal += _ => Repaint();
CultCache.OnDataUpdateRemote += _ => EditorDispatcher.Dispatch(Repaint);
CultCache.OnUpdate += (_,__) => EditorDispatcher.Dispatch(Repaint);
wantsMouseMove = true;
_warning = new GUIStyle(EditorStyles.boldLabel);
_warning.normal.textColor = Color.red;

View file

@ -96,6 +96,8 @@ public abstract class DatabaseListView : EditorWindow
public Color LabelColor => EditorGUIUtility.isProSkin ? Color.white : Color.black;
private bool _listItemStyle;
private SingleFileMessagePackBackingStore _msgPackStore;
private MultiFileJsonBackingStore _jsonStore;
public GUIStyle ListItemStyle => (_listItemStyle = !_listItemStyle) ? ListStyleEven : ListStyleOdd;
void OnEnable()
@ -110,16 +112,16 @@ public abstract class DatabaseListView : EditorWindow
normal = {background = EditorGUIUtility.isProSkin ? Color.Lerp(XKCDColors.DarkGrey,Color.black,.5f).ToTexture() : Color.Lerp(XKCDColors.LightGrey,Color.white,.5f).ToTexture()},
margin = new RectOffset(0, 0, 0, 0)
};
cultCache = new CultCache(FilePath);
cultCache.OnDataUpdateLocal += _ => Repaint();
cultCache.OnDataInsertLocal += _ => Repaint();
cultCache.OnDataRemoveLocal += _ => Repaint();
cultCache.OnDataUpdateRemote += _ => EditorDispatcher.Dispatch(Repaint);
cultCache.OnDataInsertRemote += _ => EditorDispatcher.Dispatch(Repaint);
cultCache.OnDataRemoveRemote += _ => EditorDispatcher.Dispatch(Repaint);
_jsonStore = new MultiFileJsonBackingStore(FilePath);
_msgPackStore = new SingleFileMessagePackBackingStore(Path.Combine(FilePath, "AetherDB.msgpack"));
cultCache = new CultCache();
cultCache.AddBackingStore(_jsonStore);
cultCache.AddBackingStore(_msgPackStore);
cultCache.AddBackingStore(new MultiFileMessagePackBackingStore(FilePath), typeof(NameFile));
cultCache.PullAllBackingStores();
cultCache.OnUpdate += (_,__) => EditorDispatcher.Dispatch(Repaint);
DatabaseInspector.CultCache = cultCache;
_inspector = DatabaseInspector.Instance;
_inspector.Show();
@ -128,8 +130,7 @@ public abstract class DatabaseListView : EditorWindow
.Where(t => t.GetCustomAttribute<InspectableAttribute>() != null && t.GetCustomAttribute<GlobalSettingsAttribute>() != null).ToArray();
_tables = typeof(DatabaseEntry).GetAllChildClasses()
.Where(t => t.GetCustomAttribute<InspectableAttribute>() != null && t.GetCustomAttribute<GlobalSettingsAttribute>() == null)
.GroupBy(t=>t.GetCustomAttribute<RethinkTableAttribute>()?.TableName ??
(t.GetCustomAttribute<ExternalEntryAttribute>() != null ? "External" : "Default"))
.GroupBy(t=>t.GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? "Default")
.ToDictionary(group=>group.Key, group=> (false, group.Select(t=>(t, false)).ToArray()));
if (EditorPrefs.HasKey("RethinkDB.URL"))
@ -170,17 +171,18 @@ public abstract class DatabaseListView : EditorWindow
}
using (new HorizontalScope())
{
GUILayout.Label("Export");
//_fileName = TextField(_fileName);
if (GUILayout.Button("Save"))
if (GUILayout.Button("JSON"))
{
cultCache.Save();
Debug.Log("Local DB Cache Saved!");
_jsonStore.PushAll();
Debug.Log("Exported DB to JSON!");
}
if (GUILayout.Button("Load"))
if (GUILayout.Button("MsgPack"))
{
cultCache.Load();
Debug.Log("Loaded DB From Local Cache!");
_msgPackStore.PushAll();
Debug.Log("Exported DB to MessagePack!");
}
}

View file

@ -84,8 +84,13 @@ public class ActionGameManager : MonoBehaviour
{
if (_cultCache != null) return _cultCache;
_cultCache = new CultCache(Path.Combine(GameDataDirectory.FullName, "AetherDB.msgpack"));
_cultCache.Load();
_cultCache = new CultCache();
_cultCache.AddBackingStore(new MultiFileJsonBackingStore(GameDataDirectory.FullName));
_cultCache.AddBackingStore(
new SingleFileMessagePackBackingStore(Path.Combine(GameDataDirectory.FullName, "AetherDB.msgpack")));
// _cultCache.AddBackingStore(
// new MultiFileMessagePackBackingStore(GameDataDirectory.FullName), typeof(NameFile));
_cultCache.PullAllBackingStores();
return _cultCache;
}

View file

@ -64,7 +64,7 @@ public class Faction : DatabaseEntry, INamedEntry
}
}
[Inspectable, MessagePackObject, ExternalEntry]
[Inspectable, MessagePackObject]
public class NameFile : DatabaseEntry, INamedEntry
{
[Key(1)] public string Name;

View file

@ -3,8 +3,8 @@ using System;
[AttributeUsage(AttributeTargets.Class)]
public class GlobalSettingsAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Class)]
public class ExternalEntryAttribute : Attribute { }
// [AttributeUsage(AttributeTargets.Class)]
// public class ExternalEntryAttribute : Attribute { }
[AttributeUsage(AttributeTargets.All, Inherited = false)]
public class InspectableAttribute : Attribute { }

View file

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
public static class CollectionExtensions
{
@ -64,4 +65,12 @@ public static class CollectionExtensions
return maxItem;
}
}
public static class AsyncAwaitExtensions
{
public static async void WrapAwait(this Task task)
{
await task;
}
}

View file

@ -3,85 +3,64 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
using System.Buffers.Text;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using MessagePack;
using Newtonsoft.Json;
using RethinkDb.Driver;
using RethinkDb.Driver.Net;
using UniRx;
public class CultCache
{
public event Action<DatabaseEntry> OnDataInsertLocal;
public event Action<DatabaseEntry> OnDataUpdateLocal;
public event Action<DatabaseEntry> OnDataRemoveLocal;
public event Action<DatabaseEntry> OnDataInsertRemote;
public event Action<DatabaseEntry> OnDataUpdateRemote;
public event Action<DatabaseEntry> OnDataRemoveRemote;
private readonly object addLock = new object();
//public Action<string> Logger = Console.WriteLine;
private string _filePath;
//private string _filePath;
public event Action<DatabaseEntry, DatabaseEntry> OnUpdate;
private List<CacheBackingStore> _backingStores = new List<CacheBackingStore>();
private readonly Dictionary<Type, CacheBackingStore> _typeStores = new Dictionary<Type, CacheBackingStore>();
private readonly Dictionary<CacheBackingStore, Type[]> _storeTypes = new Dictionary<CacheBackingStore, Type[]>();
private readonly Dictionary<Guid, DatabaseEntry> _entries = new Dictionary<Guid, DatabaseEntry>();
private readonly Dictionary<Type, DatabaseEntry> _globals = new Dictionary<Type, DatabaseEntry>();
private readonly Dictionary<Type, HashSet<DatabaseEntry>> _types = new Dictionary<Type, HashSet<DatabaseEntry>>();
private readonly Dictionary<Type, (DirectoryInfo directory, List<Guid> entries)> _externalTypes = new Dictionary<Type, (DirectoryInfo directory, List<Guid> entries)>();
// private readonly Dictionary<Type, (DirectoryInfo directory, List<Guid> entries)> _externalTypes = new Dictionary<Type, (DirectoryInfo directory, List<Guid> entries)>();
private class ExternalEntry
{
public string FilePath;
public DatabaseEntry Entry;
public ExternalEntry(string filePath, DatabaseEntry entry)
{
FilePath = filePath;
Entry = entry;
}
}
private readonly Dictionary<Guid, ExternalEntry> _externalEntries = new Dictionary<Guid, ExternalEntry>();
private readonly Dictionary<Type, FieldInfo[]> _linkFields = new Dictionary<Type, FieldInfo[]>();
// private class ExternalEntry
// {
// public string FilePath;
// public DatabaseEntry Entry;
//
// public ExternalEntry(string filePath, DatabaseEntry entry)
// {
// FilePath = filePath;
// Entry = entry;
// }
// }
// private readonly Dictionary<Guid, ExternalEntry> _externalEntries = new Dictionary<Guid, ExternalEntry>();
public IEnumerable<DatabaseEntry> AllEntries => _entries.Values;
public CultCache(string filePath)
public CultCache()
{
DatabaseLinkBase.Cache = this;
RegisterResolver.Register();
_filePath = filePath;
var fileInfo = new FileInfo(filePath);
var dataDirectory = fileInfo.Directory;
// Entry types can be marked external
// External entries are stored individually and loaded on demand
// This is mainly to accomodate large files like datasets
foreach (var type in typeof(DatabaseEntry).GetAllChildClasses())
{
var linkFields = type.GetFields().Where(f => f.FieldType.IsAssignableToGenericType(typeof(DatabaseLink<>))).ToArray();
if(linkFields.Length > 0)
_linkFields[type] = linkFields;
if (type.GetCustomAttribute<ExternalEntryAttribute>() != null)
{
var typeDirectory = dataDirectory.CreateSubdirectory(type.Name);
_externalTypes[type] = (typeDirectory, new List<Guid>());
// Cache the GUIDs for all available external entries for querying
// Initially set values to null to indicate they haven't been loaded yet
foreach (var file in typeDirectory.EnumerateFiles("*.msgpack"))
{
Guid id;
if (Guid.TryParse(file.Name.Substring(0, file.Name.IndexOf('.')), out id))
{
_externalEntries.Add(id, new ExternalEntry(file.FullName, null));
_externalTypes[type].entries.Add(id);
}
}
}
else _types[type] = new HashSet<DatabaseEntry>();
_types[type] = new HashSet<DatabaseEntry>();
if (type.GetCustomAttribute<GlobalSettingsAttribute>() != null)
{
@ -91,7 +70,42 @@ public class CultCache
}
}
public void Add(DatabaseEntry entry, bool remote = false)
public void AddBackingStore(CacheBackingStore store, params Type[] domain)
{
if (domain.Length > 0)
{
_storeTypes[store] = domain;
foreach (var t in domain) _typeStores[t] = store;
}
else
{
foreach(var existingStore in _backingStores) store.SubscribeTo(existingStore);
_backingStores.Add(store);
}
store.EntryAdded.Subscribe(entry =>
{
Add(entry, store);
OnUpdate?.Invoke(null, entry);
});
store.EntryUpdated.Subscribe(entry =>
{
Add(entry, store);
OnUpdate?.Invoke(entry, entry);
});
store.EntryDeleted.Subscribe(entry =>
{
Remove(entry, store);
OnUpdate?.Invoke(entry, null);
});
}
public void PullAllBackingStores()
{
foreach(var store in _backingStores) store.PullAll();
foreach(var store in _storeTypes.Keys) store.PullAll();
}
public void Add(DatabaseEntry entry, CacheBackingStore source = null)
{
lock(addLock)
{
@ -101,85 +115,49 @@ public class CultCache
var type = entry.GetType();
// If an external entry is added, store it separately
if (_externalTypes.ContainsKey(type))
if (_globals.ContainsKey(type))
{
if (_externalEntries.ContainsKey(entry.ID))
if(_globals[type]!=null)
{
_externalEntries[entry.ID].Entry = entry;
}
else
{
_externalTypes[type].entries.Add(entry.ID);
_externalEntries[entry.ID] = new ExternalEntry(
Path.Combine(_externalTypes[type].directory.FullName, $"{entry.ID.ToString()}.msgpack"),
entry);
Remove(_globals[type]);
exists = true;
}
_globals[type] = entry;
}
if(_typeStores.ContainsKey(type))
_typeStores[type].Push(entry);
else
{
if (_globals.ContainsKey(type))
{
if(_globals[type]!=null)
{
Remove(_globals[type], remote);
exists = true;
}
_globals[type] = entry;
}
_entries[entry.ID] = entry;
_types[type].Add(entry);
foreach (var parentType in type.GetParentTypes())
{
if(_types.ContainsKey(parentType))
_types[parentType].Add(entry);
}
if (remote)
{
if (exists)
OnDataUpdateRemote?.Invoke(entry);
else
OnDataInsertRemote?.Invoke(entry);
}
else
{
if (exists)
OnDataUpdateLocal?.Invoke(entry);
else
OnDataInsertLocal?.Invoke(entry);
}
var masterStore = _backingStores.First();
if(masterStore!=source)
masterStore.Push(entry);
}
_entries[entry.ID] = entry;
_types[type].Add(entry);
foreach (var parentType in type.GetParentTypes())
{
if(_types.ContainsKey(parentType))
_types[parentType].Add(entry);
}
}
}
}
public bool IsExternal(DatabaseEntry entry) => _externalTypes.ContainsKey(entry.GetType());
public bool IsGlobal(DatabaseEntry entry) => _globals.ContainsKey(entry.GetType());
public void AddAll(IEnumerable<DatabaseEntry> entries, bool remote = false)
public void AddAll(IEnumerable<DatabaseEntry> entries)
{
foreach (var entry in entries)
{
Add(entry, remote);
Add(entry);
}
}
public DatabaseEntry Get(Guid guid)
{
if (_externalEntries.ContainsKey(guid))
{
if(_externalEntries[guid].Entry == null)
{
var bytes = File.ReadAllBytes(_externalEntries[guid].FilePath);
var e = MessagePackSerializer.Deserialize<DatabaseEntry>(bytes);
_externalEntries[guid].Entry = e;
}
return _externalEntries[guid].Entry;
}
DatabaseEntry entry;
_entries.TryGetValue(guid, out entry);
return entry;
@ -203,56 +181,394 @@ public class CultCache
public IEnumerable<DatabaseEntry> GetAll(Type type)
{
if (_externalTypes.ContainsKey(type))
{
return _externalTypes[type].entries.Select(Get);
}
return !_types.ContainsKey(type) ? Enumerable.Empty<DatabaseEntry>() : _types[type];
}
public IEnumerable<T> GetAll<T>() where T : DatabaseEntry
{
var type = typeof(T);
if (_externalTypes.ContainsKey(type))
{
return _externalTypes[type].entries.Select(Get<T>);
}
return !_types.ContainsKey(type) ? Enumerable.Empty<T>() : _types[type].Cast<T>();
}
public void Remove(DatabaseEntry entry, bool remote = false)
public void Remove(DatabaseEntry entry, CacheBackingStore source = null)
{
_entries.Remove(entry.ID);
foreach (var parentType in entry.GetType().GetParentTypes())
var type = entry.GetType();
if(_typeStores.ContainsKey(type))
_typeStores[type].Delete(entry);
else foreach(var store in _backingStores)
{
if(store != source)
store.Delete(entry);
}
foreach (var parentType in type.GetParentTypes())
{
if(_types.ContainsKey(parentType))
_types[parentType].Remove(entry);
}
}
}
if (remote)
OnDataRemoveRemote?.Invoke(entry);
else
OnDataRemoveLocal?.Invoke(entry);
public interface RealtimeBackingStore
{
public void ObserveChanges();
}
public abstract class CacheBackingStore
{
protected CacheBackingStore()
{
EntryAdded = new Subject<DatabaseEntry>();
EntryDeleted = new Subject<DatabaseEntry>();
EntryUpdated = new Subject<DatabaseEntry>();
}
public void Load()
{
var bytes = File.ReadAllBytes(_filePath);
var entries = MessagePackSerializer.Deserialize<DatabaseEntry[]>(bytes);
AddAll(entries);
}
public abstract void PullAll();
public abstract void Push(DatabaseEntry entry);
public abstract void Delete(DatabaseEntry entry);
public abstract void PushAll(bool soft = false);
public Subject<DatabaseEntry> EntryAdded { get; }
public Subject<DatabaseEntry> EntryDeleted { get; }
public Subject<DatabaseEntry> EntryUpdated { get; }
public void Save()
protected Dictionary<Guid, DatabaseEntry> Entries = new Dictionary<Guid, DatabaseEntry>();
public void SubscribeTo(CacheBackingStore targetStore)
{
var entries = AllEntries.ToArray();
File.WriteAllBytes(_filePath, MessagePackSerializer.Serialize(entries));
foreach (var external in _externalEntries.Values)
targetStore.EntryAdded.Subscribe(Push);
targetStore.EntryDeleted.Subscribe(Delete);
targetStore.EntryUpdated.Subscribe(Push);
}
}
public abstract class MultiFileBackingStore : CacheBackingStore, RealtimeBackingStore
{
public DirectoryInfo DirectoryInfo { get; }
protected Dictionary<Type, DirectoryInfo> _entryTypeDirectories = new Dictionary<Type, DirectoryInfo>();
public abstract byte[] Serialize(DatabaseEntry entry);
public abstract DatabaseEntry Deserialize(byte[] data);
public abstract string Extension { get; }
public MultiFileBackingStore(string path)
{
DirectoryInfo = new DirectoryInfo(path);
foreach (var type in typeof(DatabaseEntry).GetAllChildClasses())
{
if (external.Entry != null)
_entryTypeDirectories[type] = DirectoryInfo.CreateSubdirectory(type.Name);
}
}
public override void PullAll()
{
if (!DirectoryInfo.Exists) return;
foreach (var directory in _entryTypeDirectories.Values)
{
foreach (var file in directory.EnumerateFiles($"*.{Extension}"))
{
File.WriteAllBytes(external.FilePath, MessagePackSerializer.Serialize(external.Entry));
var entry = Deserialize(File.ReadAllBytes(file.FullName));
Entries[entry.ID] = entry;
EntryAdded.OnNext(entry);
}
}
}
private string GetFileName(DatabaseEntry entry) =>
$"{(entry is INamedEntry namedEntry ? namedEntry.EntryName : entry.ID.ToString())}.{Extension}";
public override void Push(DatabaseEntry entry)
{
var type = entry.GetType();
Entries[entry.ID] = entry;
var directory = _entryTypeDirectories[type];
File.WriteAllBytes(Path.Combine(directory.FullName, GetFileName(entry)), Serialize(entry));
}
public override void Delete(DatabaseEntry entry)
{
if(Entries.ContainsKey(entry.ID))
{
var type = entry.GetType();
Entries.Remove(entry.ID);
var directory = _entryTypeDirectories[type];
var file = new FileInfo(Path.Combine(directory.FullName, GetFileName(entry)));
if (file.Exists)
file.Delete();
}
}
public override void PushAll(bool soft = false)
{
foreach(var entry in Entries.Values.ToArray()) Push(entry);
}
public void ObserveChanges()
{
foreach (var directory in _entryTypeDirectories.Values)
{
var watcher = new FileSystemWatcher(directory.FullName);
watcher.Changed += (sender, args) =>
{
var entry = Deserialize(File.ReadAllBytes(args.FullPath));
Entries[entry.ID] = entry;
EntryUpdated.OnNext(entry);
};
watcher.Created += (sender, args) =>
{
var entry = Deserialize(File.ReadAllBytes(args.FullPath));
Entries[entry.ID] = entry;
EntryAdded.OnNext(entry);
};
watcher.Deleted += (sender, args) =>
{
var entry = Deserialize(File.ReadAllBytes(args.FullPath));
Entries[entry.ID] = entry;
EntryDeleted.OnNext(entry);
};
}
}
}
public class MultiFileJsonBackingStore : MultiFileBackingStore
{
public MultiFileJsonBackingStore(string path) : base(path)
{
RegisterResolver.Register();
}
public override byte[] Serialize(DatabaseEntry entry)
{
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(entry));
}
public override DatabaseEntry Deserialize(byte[] data)
{
return JsonConvert.DeserializeObject<DatabaseEntry>(Encoding.UTF8.GetString(data));
}
public override string Extension => "json";
}
public class MultiFileMessagePackBackingStore : MultiFileBackingStore
{
public MultiFileMessagePackBackingStore(string path) : base(path)
{
RegisterResolver.Register();
}
public override byte[] Serialize(DatabaseEntry entry)
{
return MessagePackSerializer.Serialize(entry);
}
public override DatabaseEntry Deserialize(byte[] data)
{
return MessagePackSerializer.Deserialize<DatabaseEntry>(data);
}
public override string Extension => "msgpack";
}
public abstract class SingleFileBackingStore : CacheBackingStore
{
public FileInfo FileInfo { get; }
public abstract byte[] Serialize(DatabaseEntry[] entries);
public abstract DatabaseEntry[] Deserialize(byte[] data);
public SingleFileBackingStore(string filePath)
{
FileInfo = new FileInfo(filePath);
}
public override void PullAll()
{
if (!FileInfo.Exists) return;
foreach (var entry in Deserialize(File.ReadAllBytes(FileInfo.FullName)))
{
Entries[entry.ID] = entry;
EntryAdded.OnNext(entry);
}
}
public override void Push(DatabaseEntry entry)
{
var type = entry.GetType();
Entries[entry.ID] = entry;
PushAll();
}
public override void Delete(DatabaseEntry entry)
{
if(Entries.ContainsKey(entry.ID))
{
Entries.Remove(entry.ID);
PushAll();
}
}
public override void PushAll(bool soft = false)
{
var entriesArray = Entries.Values.ToArray();
File.WriteAllBytes(FileInfo.FullName, Serialize(entriesArray));
}
}
public class SingleFileMessagePackBackingStore : SingleFileBackingStore
{
public SingleFileMessagePackBackingStore(string filePath) : base(filePath)
{
RegisterResolver.Register();
}
public override byte[] Serialize(DatabaseEntry[] entries)
{
return MessagePackSerializer.Serialize(entries);
}
public override DatabaseEntry[] Deserialize(byte[] data)
{
return MessagePackSerializer.Deserialize<DatabaseEntry[]>(data);
}
}
public class SingleFileJsonBackingStore : SingleFileBackingStore
{
public SingleFileJsonBackingStore(string filePath) : base(filePath)
{
RegisterResolver.Register();
}
public override byte[] Serialize(DatabaseEntry[] entries)
{
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(entries));
}
public override DatabaseEntry[] Deserialize(byte[] data)
{
return JsonConvert.DeserializeObject<DatabaseEntry[]>(Encoding.UTF8.GetString(data));
}
}
public class RethinkBackingStore : CacheBackingStore, RealtimeBackingStore
{
public const string DEFAULT_TABLE = "Default";
public static RethinkDB R = RethinkDB.R;
public string DatabaseName { get; }
public string ConnectionString { get; }
private string[] _syncTables;
private Connection _connection;
private Dictionary<DatabaseEntry, string> _entryHashes = new Dictionary<DatabaseEntry, string>();
public void ObserveChanges()
{
foreach (var table in _syncTables)
{
// Subscribe to changes from RethinkDB
Task.Run(async () =>
{
var result = await R
.Db(DatabaseName)
.Table(table)
.Changes()
.RunChangesAsync<DatabaseEntry>(_connection);
while (await result.MoveNextAsync())
{
var change = result.Current;
if(change.NewValue==null)
EntryDeleted.OnNext(change.OldValue);
else if(change.OldValue==null)
EntryAdded.OnNext(change.NewValue);
else EntryUpdated.OnNext(change.NewValue);
}
}).WrapAwait();
}
}
public RethinkBackingStore(string databaseName, string connectionString)
{
DatabaseName = databaseName;
ConnectionString = connectionString;
RegisterResolver.Register();
var connectionStringDomainLength = connectionString.IndexOf(':');
if (connectionStringDomainLength < 1)
throw new ArgumentException("Illegal Connection String: must include port!");
var portString = connectionString.Substring(connectionStringDomainLength + 1);
if (!int.TryParse(portString, out var port))
throw new ArgumentException($"Illegal connection string! \"{portString}\" is not a valid port number!");
_connection = R.Connection()
.Hostname(connectionString.Substring(0,connectionStringDomainLength))
.Port(port).Timeout(60).Connect();
var tables = R.Db(DatabaseName).TableList().RunAtom<string[]>(_connection);
_syncTables = typeof(DatabaseEntry).GetAllChildClasses()
.Select(t => t.GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? DEFAULT_TABLE).Distinct().ToArray();
foreach (var st in _syncTables.Where(st => !tables.Contains(st)))
R.Db(DatabaseName).TableCreate(st).RunNoReply(_connection);
}
public override void PullAll()
{
foreach (var table in _syncTables)
{
// Get entries from RethinkDB
Task.Run(async () =>
{
var result = await R
.Db(DatabaseName)
.Table(table)
.RunCursorAsync<DatabaseEntry>(_connection);
while (await result.MoveNextAsync())
{
var entry = result.Current;
EntryAdded.OnNext(entry);
}
}).WrapAwait();
}
}
public override async void Push(DatabaseEntry entry)
{
var type = entry.GetType();
//(Entries.ContainsKey(entry.ID) ? EntryUpdated : EntryAdded).OnNext(entry);
var table = type.GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? DEFAULT_TABLE;
var result = await R
.Db(DatabaseName)
.Table(table)
.Get(entry.ID)
.Replace(entry)
.RunAsync(_connection);
}
public override async void Delete(DatabaseEntry entry)
{
if(Entries.ContainsKey(entry.ID))
{
var type = entry.GetType();
var table = type.GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? DEFAULT_TABLE;
var result = await R
.Db(DatabaseName)
.Table(table)
.Get(entry.ID)
.Delete()
.RunAsync(_connection);
}
}
public override void PushAll(bool soft = false)
{
foreach(var entry in Entries.Values)
Push(entry);
}
}

View file

@ -19,126 +19,13 @@ public static class RethinkConnection
public static RethinkQueryStatus RethinkConnect(CultCache cache, string connectionString, string dbName, bool syncLocalChanges = true)
{
// Add Unity.Mathematics serialization support to RethinkDB Driver
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter>
{
new MathJsonConverter(),
Converter.DateTimeConverter,
Converter.BinaryConverter,
Converter.GroupingConverter,
Converter.PocoExprConverter
}
};
var syncTables = typeof(DatabaseEntry).GetAllChildClasses()
.Select(t => t.GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? "Default").Distinct();
var connectionStringDomainLength = connectionString.IndexOf(':');
if (connectionStringDomainLength < 1)
throw new ArgumentException("Illegal Connection String: must include port!");
var portString = connectionString.Substring(connectionStringDomainLength + 1);
if (!int.TryParse(portString, out var port))
throw new ArgumentException($"Illegal connection string! \"{portString}\" is not a valid port number!");
var connection = R.Connection()
.Hostname(connectionString.Substring(0,connectionStringDomainLength))
.Port(port).Timeout(60).Connect();
var tables = R.Db(dbName).TableList().RunAtom<string[]>(connection);
foreach (var st in syncTables.Where(st => !tables.Contains(st)))
R.Db(dbName).TableCreate(st).RunNoReply(connection);
if (syncLocalChanges)
{
// When entries are changed locally, push the changes to RethinkDB
cache.OnDataUpdateLocal += async entry =>
{
var table = entry.GetType().GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? "Other";
var result = await R
.Db(dbName)
.Table(table)
.Get(entry.ID)
.Replace(entry)
.RunAsync(connection);
};
cache.OnDataInsertLocal += async entry =>
{
var table = entry.GetType().GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? "Other";
var result = await R
.Db(dbName)
.Table(table)
.Insert(entry)
.RunAsync(connection);
};
cache.OnDataRemoveLocal += async entry =>
{
var table = entry.GetType().GetCustomAttribute<RethinkTableAttribute>()?.TableName ?? "Other";
var result = await R
.Db(dbName)
.Table(table)
.Get(entry.ID)
.Delete()
.RunAsync(connection);
};
}
var status = new RethinkQueryStatus();
foreach (var table in syncTables)
{
// Get entries from RethinkDB
Task.Run(async () =>
{
status.TotalEntries += R
.Db(dbName)
.Table(table)
.Count().RunAtom<int>(connection);
var result = await R
.Db(dbName)
.Table(table)
.RunCursorAsync<DatabaseEntry>(connection);
while (await result.MoveNextAsync())
{
var entry = result.Current;
cache.Add(entry, true);
status.RetrievedEntries++;
}
}).WrapAwait();
// Subscribe to changes from RethinkDB
Task.Run(async () =>
{
var result = await R
.Db(dbName)
.Table(table)
.Changes()
.RunChangesAsync<DatabaseEntry>(connection);
while (await result.MoveNextAsync())
{
var change = result.Current;
cache.Add(change.NewValue, true);
}
}).WrapAwait();
}
return status;
}
}
public static class AsyncAwaitExtensions
{
public static async void WrapAwait(this Task task)
{
await task;
}
}
public class RethinkQueryStatus
{

View file

@ -3,6 +3,8 @@ using System.Collections.Generic;
using MessagePack;
using MessagePack.ReactivePropertyExtension;
using MessagePack.Resolvers;
using Newtonsoft.Json;
using RethinkDb.Driver.Net;
public static class RegisterResolver
{
@ -22,6 +24,19 @@ public static class RegisterResolver
var options = MessagePackSerializerOptions.Standard.WithResolver(resolver);
MessagePackSerializer.DefaultOptions = options;
// Add Unity.Mathematics serialization support to Newtonsoft JSON
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter>
{
new MathJsonConverter(),
Converter.DateTimeConverter,
Converter.BinaryConverter,
Converter.GroupingConverter,
Converter.PocoExprConverter
}
};
registered = true;
}
}

View file

@ -1294,6 +1294,8 @@ public class EquippedItem
var scaleModifier = 1.0f;
var scaleModifiers = stat.GetScaleModifiers(Entity).Values;
var a = float3(0, 0, 1);
var b = dot(a, float3(0, 0, 1));
foreach (var value in scaleModifiers) scaleModifier *= value;
float constantModifier = 0;

View file

@ -55,7 +55,11 @@ public class StoryProcessor : IZoneResolver, IFactionResolver
public void ProcessStories()
{
var locationFiles = _locationsPath.EnumerateFiles("*.ink");
foreach(var inkFile in locationFiles) ProcessLocation(GetStory(inkFile), inkFile);
foreach(var inkFile in locationFiles)
{
Log($"Processing story file at {inkFile.FullName}");
ProcessLocation(GetStory(inkFile), inkFile);
}
var questFiles = _questsPath.EnumerateFiles("*ink");
foreach(var inkFile in questFiles) ProcessQuest(GetStory(inkFile), inkFile);

BIN
GameData/AetherDB.msgpack (Stored with Git LFS)

Binary file not shown.

View file

@ -0,0 +1 @@
{"interiorShape":{"name":[[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true]]},"schematic":"","behaviors":[],"durability":550.0,"minTemp":175.0,"maxTemp":600.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"SafeStuff II","description":"Your stuff is safe stuffed in the new, bigger SafeStuff","creator":"adfb9b08-aabc-45c6-9586-915698a9c4b0","mass":700.0,"shape":{"name":[[true,true,true],[true,true,true],[true,true,true]]},"specificHeat":0.75,"conductivity":1.0,"price":450000,"id":"03740fd6-158d-43e9-b070-9a40e0b9bc45","$type":"CargoBayData"}

View file

@ -0,0 +1 @@
{"interiorShape":{"name":[[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true,true,true,true,true]]},"schematic":"","behaviors":[],"durability":1000.0,"minTemp":175.0,"maxTemp":600.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Store-All Enterprise Edition","description":"A large amount of storage","creator":"2f74e6b4-d268-48a9-b2a8-24591c680e84","mass":800.0,"shape":{"name":[[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true],[true,true,true,true,true,true]]},"specificHeat":0.75,"conductivity":1.0,"price":700000,"id":"46b66f9a-5c72-4e7a-ac9b-4dd7904cc4a1","$type":"CargoBayData"}

View file

@ -0,0 +1 @@
{"interiorShape":{"name":[[true,true],[true,true]]},"schematic":"","behaviors":[],"durability":125.0,"minTemp":175.0,"maxTemp":600.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Store-All Plus Mini","description":"Take some of your cargo wherever your shipgo","creator":"2f74e6b4-d268-48a9-b2a8-24591c680e84","mass":50.0,"shape":{"name":[[true]]},"specificHeat":0.75,"conductivity":1.0,"price":50000,"id":"ae05f4cb-0dd5-4f37-af96-cc61c9d61e1f","$type":"CargoBayData"}

View file

@ -0,0 +1 @@
{"interiorShape":{"name":[[true,true,true,true],[true,true,true,true],[true,true,true,true],[true,true,true,true]]},"schematic":"","behaviors":[],"durability":250.0,"minTemp":175.0,"maxTemp":600.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Store-All Plus","description":"Take your cargo wherever your shipgo","creator":"2f74e6b4-d268-48a9-b2a8-24591c680e84","mass":200.0,"shape":{"name":[[true,true],[true,true]]},"specificHeat":0.75,"conductivity":1.0,"price":150000,"id":"49b4c15a-c10b-49c0-9dad-31dfb9b3a9b9","$type":"CargoBayData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"AI Pilot","description":"Place your valuable life and even more valuable cargo in the relentlessly logical hands of your AI copilot*. *Personalities may vary. Any neuroticism or homicidal madness in an artificial intelligence is not our responsibility. ","creator":"00000000-0000-0000-0000-000000000000","mass":0.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"11d9fd0c-c0dd-482f-8e2a-f7c289ed6a3d","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":3,"name":"All-Surface Stylus","description":"Draw and write on anything! Even lava!","creator":"00000000-0000-0000-0000-000000000000","mass":0.7,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"20376ecd-77fa-4ffe-9be6-185158ee1bfc","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Antireflective Coating","description":"Spray this stuff on your hull to make it invisible to radar.","creator":"00000000-0000-0000-0000-000000000000","mass":5.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"4810a43b-bbb9-447d-b62e-b723e4d88afc","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Ballistic Powder","description":"Used in the creation of ballistic weapons. \r\n","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"0b449ae1-7eab-47e8-ac3c-2b6f6ff01f00","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Big Red Button","description":"No one knows what it does, but everyone know it's critical to modern spaceship design. Just don't press it.","creator":"00000000-0000-0000-0000-000000000000","mass":3.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"5e2950d6-02df-461e-a35e-a4123c6a5639","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":5,"name":"Cargo Pod","description":"Cargo space? No, cargo road, but also, cargo pod.","creator":"00000000-0000-0000-0000-000000000000","mass":20.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"17032840-c285-4f33-82ae-6b03f1e1e56b","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Circuit Board","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":3.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"3c8b2b3d-ca1a-405f-966f-c64662a64418","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":5,"name":"Cockpit","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":25.0,"shape":null,"specificHeat":1.5,"conductivity":1.0,"price":0,"id":"6d20c298-281e-46fc-be33-dbcc575d49d7","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Construction Rebar","description":"Helps your building stay up.","creator":"00000000-0000-0000-0000-000000000000","mass":65.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"2aa99b2d-80ed-4640-9350-9affcfe6d8cd","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"Crash Test Dummy","description":"Your best friend and co pilot","creator":"00000000-0000-0000-0000-000000000000","mass":7.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"4b3fc716-d362-4379-8c65-f2c471647ed1","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"Daily Feed Ad Slot (5ms)","description":"A 5 ms slot on the most widely viewed news feed in the multiverse","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"601a345d-6f0b-4bdb-8171-be4befaf9a33","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"Dashboard Ornament","description":"Add personality to your ship dashboard! *Not responsible for accidental death due to inertia from sudden deceleration","creator":"00000000-0000-0000-0000-000000000000","mass":0.5,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"03ff4335-fa65-4a89-8cea-68f70de01d60","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Dials","description":"Small dials for your control panel. Do they do anything? We don't know, but they sure look important.","creator":"00000000-0000-0000-0000-000000000000","mass":0.5,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"6d4c9e32-7ffd-45f6-8e08-86d544793774","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Diamond","description":"Used to harden a material. \r\n","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"8776c2fd-45f6-4ca6-8ef0-5214be830182","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":5,"name":"Emergency Personal Life Support System","description":"The sole survivor's best friend.","creator":"00000000-0000-0000-0000-000000000000","mass":16.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"35f02735-1993-4467-b3de-028c2d6e2276","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Fuel","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":3.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"6821495a-4875-4350-a8e8-e813c3576aa8","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":3,"name":"Geiger Counter","description":"It's rad. You shouldn't be.","creator":"00000000-0000-0000-0000-000000000000","mass":6.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"1ea0df17-aba1-45bc-8d6e-a430c110e38d","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Hat","description":"A hat. Goes on your head. OR: It keeps the rain off your head. ","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"5383d6b6-083b-4721-8f6b-426dba0beaeb","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Heat Sink Tile","description":"It's getting hot in here, so drain off all your heat before your systems overload","creator":"00000000-0000-0000-0000-000000000000","mass":7.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"0d6a518d-24e9-40bf-9861-301de17b5161","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Helmet","description":"Goes on your head. But better.","creator":"00000000-0000-0000-0000-000000000000","mass":5.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"8b026aea-1d79-49a0-b843-abdfcca31bab","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{"2103d2d5-bf5c-4dd9-9381-c90f1e39496f":0.25,"3f608054-8e4a-43fb-926c-261da4cc92d9":0.85},"category":3,"name":"Holo-desk","description":"A totally not ripped off version of Star Trek's Holodeck, now in desk size. An upgraded part of the Virtual Reality Experience","creator":"00000000-0000-0000-0000-000000000000","mass":4.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"2055f611-ef5d-4791-b1ad-f1757c081a99","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Inertial Compensating Seatbelt","description":"because humans are squishy.","creator":"00000000-0000-0000-0000-000000000000","mass":3.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"32934bf0-d7e9-432f-8863-e07c092b67f6","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Insulation","description":"Keeps hot things hot and cold things cold.","creator":"00000000-0000-0000-0000-000000000000","mass":2.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"4c82acfa-b8e4-4601-9465-2fad107b1eff","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Joystick","description":"Manual ship control","creator":"00000000-0000-0000-0000-000000000000","mass":2.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"63abe46b-ad99-4ac9-b5e4-d83a40465065","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":3,"name":"Knife","description":"for slicing, stabbing, and sauteing","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"5449f7d3-b250-41cd-9e7e-ab2a7037cacb","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"Local Newscast","description":"Has all the local dirt, available for download upon entry to a territory.","creator":"00000000-0000-0000-0000-000000000000","mass":0.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"5bcddae5-10fe-4316-9dca-6dc5d53c899e","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Magnetic EVA Boots","description":"Keeps you from being flung into the abyss. Also gives you some daaamn nice calves. Leg day? Every day.","creator":"00000000-0000-0000-0000-000000000000","mass":3.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"3987140a-19c3-4b0b-8fa5-528f43a83afb","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"Memory Download","description":"Moments of human life distilled into electrical impulses and available for download.","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"6f0ed812-01b0-4767-90c5-0b6857bc2e29","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Mining Rights","description":"legal right to a particular location","creator":"00000000-0000-0000-0000-000000000000","mass":0.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"51e4dc3b-0107-4ab5-a2c6-02d34a1035b2","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":3,"name":"Moo-ed Lighting","description":"The best cow-based lighting system in the galaxy","creator":"00000000-0000-0000-0000-000000000000","mass":43.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"86d11f6a-9ddd-478d-8192-f047d38a7c6a","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{"8e5a2064-9603-4205-baf7-4d037ebfda90":0.1,"d6506d2d-3699-4c8c-8e90-5e4b8f2f43b9":0.75},"category":1,"name":"Mouth Adapting Gummy Molars","description":"i’s amazing mouth adaptive gummy candy, now you can!eding to be brushed and stopping me from living out my dreams of biting directly into ice cream. I wish I could eat them.”? No? Well, thanks to Miss Terri’s amazing mouth adaptive gummy candy, now you can!","creator":"00000000-0000-0000-0000-000000000000","mass":2.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"3ddbbb28-c166-4ab3-8a0b-c7b77c372f32","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{"3f608054-8e4a-43fb-926c-261da4cc92d9":0.9,"d6506d2d-3699-4c8c-8e90-5e4b8f2f43b9":0.1},"category":0,"name":"Neural Lace","description":"Used in the development of brain-machine interfaces; can also be used to knit a neural doily for your gran.","creator":"00000000-0000-0000-0000-000000000000","mass":2.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"34b16da9-1e5e-4fba-b256-eb8a38274b39","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"Paparazzi Drone","description":"Now you can keep tabs on your favourite Lucent personalities from the comfort of your rest module! ","creator":"00000000-0000-0000-0000-000000000000","mass":11.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"675a1ebe-868c-4b27-a2eb-bee2fe5e356b","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":5,"name":"Reaction Chamber","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":25.0,"shape":null,"specificHeat":1.25,"conductivity":1.0,"price":0,"id":"0caaa08c-e0b6-4eaf-a9fd-7e03088371ea","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":3,"name":"Rope","description":"Ties things. And people.","creator":"00000000-0000-0000-0000-000000000000","mass":5.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"502a6ed8-73aa-4554-ae89-a50b67cfa9e0","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Safety Goggles","description":"Safety First, so your eyes burn up last.","creator":"00000000-0000-0000-0000-000000000000","mass":0.5,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"5837ec5e-036b-4f73-9098-dbe11339909f","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":5,"name":"Secret Storage Compartment","description":"Hide your snacks from your thieving co workers who have no respect for the institution of dibs, LARRY. Also smuggling.","creator":"00000000-0000-0000-0000-000000000000","mass":4.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"452bbd60-11df-449b-a4b7-a4ca22527123","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Sheet Metal","description":"Oh sheet, it's metal!","creator":"00000000-0000-0000-0000-000000000000","mass":5.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"421e9788-d094-4c17-88cc-0d820e3cfeca","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Ship Decal","description":"Express your unique style with mass produced stickers","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"4d5929a9-5cb1-470c-a0b7-12f8abaf4497","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Ship Fins","description":"Aerodynamic! Because that's obviously needed in a low-friction environment. ","creator":"00000000-0000-0000-0000-000000000000","mass":24.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"4681d1af-1a6d-4c7e-b10d-5ee8295b9a79","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"SpaceCast","description":"News from the sector, available on entry","creator":"00000000-0000-0000-0000-000000000000","mass":0.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"6713c2b2-d886-4440-b076-dd206c22848a","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Spacesuit","description":"Because dying naked in space would be adding insult to injury","creator":"00000000-0000-0000-0000-000000000000","mass":7.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"1af83f0b-11ae-4d03-acc3-c5d478d55f14","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Spacewalking Boots","description":"Go on your feet","creator":"00000000-0000-0000-0000-000000000000","mass":3.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"22917d5e-313a-4470-a91e-0c78f1e08044","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Stealth Coating","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":2.0,"shape":null,"specificHeat":1.5,"conductivity":1.0,"price":0,"id":"33944941-5bd1-43ca-91a4-348c253f7e8b","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{"0e91c198-d6c6-4d28-a7e0-d5316db3b7d0":0.25,"3f608054-8e4a-43fb-926c-261da4cc92d9":0.75},"category":1,"name":"Super Tough Toffee","description":"Revenge is sweet. Jawbreaker toffee is sweeter. (leftovers are excellent for ship repair!) ","creator":"00000000-0000-0000-0000-000000000000","mass":2.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"498c664d-05ff-45a0-b3b6-2b98feec8611","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":4,"name":"Support Strut","description":"This genre of metal only has 400 fans! Keeps things from falling apart.","creator":"00000000-0000-0000-0000-000000000000","mass":5.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"6dc76b7c-65c3-4cc1-bc2a-eace8e4f58d2","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{"2103d2d5-bf5c-4dd9-9381-c90f1e39496f":0.75,"3f608054-8e4a-43fb-926c-261da4cc92d9":0.75},"category":1,"name":"Sure Bet Sherbet Fountain","description":"Each fizzy, sweet-tart purchase enters you automatically into an annual lottery held by Miss Terri’s. What’s the prize? Well, it wouldn’t be fun if we told you, would it?* *by purchasing this candy you agree to 1 non negotiable entry into the annual Sugar Bowl Lottery. Winning entrants are required by law to appear at the Miss Terri’s main factory on BonBon 26 on a date to be specified by the MTSSC Legal team. No unauthorized absences will be tolerated.","creator":"00000000-0000-0000-0000-000000000000","mass":3.0,"shape":null,"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"3689a855-9264-40f0-91b3-8b235dac80b6","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":2,"name":"Travel Permit","description":"Allows for travel between specified territories. For Limited Espionage Permits as specified in Subsection 1121!, Clause W of the Unified Government Corporate Rights and Privileges Amendment (Not recognized in the Terri-Tory) please submit your application in person at the offices on the surface of your local sun. ","creator":"00000000-0000-0000-0000-000000000000","mass":0.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"4081eb4c-3376-4912-a230-c43096d90ad1","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":5,"name":"Trigger","description":"Makes you happy. And fires your weapon.","creator":"00000000-0000-0000-0000-000000000000","mass":0.2,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"40004417-d242-47d2-9f27-1bbcf8548779","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":0,"name":"Trousers","description":"Goes on your legs.","creator":"00000000-0000-0000-0000-000000000000","mass":1.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"515734e6-4287-470c-bf56-188c4b257420","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"demandProfile":{},"category":3,"name":"Universal Translator","description":"Speaks your language. And Everyone elses! Downloaded directly into your brain.","creator":"00000000-0000-0000-0000-000000000000","mass":0.0,"shape":null,"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"3a33da73-ba06-4574-afec-d529097408b5","$type":"CompoundCommodityData"}

View file

@ -0,0 +1 @@
{"maxSize":[18,18],"interiorShape":{"name":[[true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true],[true,true,true,true,true,true,true,true]]},"schematic":"","behaviors":[],"durability":1000.0,"minTemp":-3.8451617E-06,"maxTemp":673.15,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Medium Docking Bay","description":null,"creator":"8443f966-0d88-4ec7-a20e-8edf73fa62f6","mass":750.0,"shape":{"name":[[true,true,true,true],[true,true,true,true],[true,true,true,true],[true,true,true,true]]},"specificHeat":0.75,"conductivity":1.0,"price":500000,"id":"3e930a2c-ac72-4385-98aa-1c5b0b90db46","$type":"DockingBayData"}

View file

@ -0,0 +1 @@
{"name":"Adrasteia","shortName":"Adrasteia","description":"The best defense is not to need one.","logo":"","personality":{},"primaryColor":[0.09,0.123157874,0.3],"secondaryColor":[0.4032,0.760051847,0.8],"nameFile":"95c298ae-d7b4-4481-9fff-deb3eb5872e9","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":3,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.389,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.811,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.607,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.233,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.434,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.559,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.155,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.957,"a9672650-c335-484a-9555-71a35c841aa1":0.251,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.881,"bbd619ed-76c1-464c-829d-3f419cdc2525":1.0,"d6466821-6776-4f40-9609-2342debf5c86":0.978},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"bbd619ed-76c1-464c-829d-3f419cdc2525","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Aeronautics Unlimited","shortName":"AU","description":"\"Quick expansion and retrieval of resources is key to a successful quarter, every quarter.\"","logo":"Assets/Resources/Sprites/Icons/Tech/Tex_skill_47.PNG","personality":{"0e91c198-d6c6-4d28-a7e0-d5316db3b7d0":0.3,"2103d2d5-bf5c-4dd9-9381-c90f1e39496f":0.65},"primaryColor":[0.3294118,0.498696,0.8392157],"secondaryColor":[0.270588279,0.8117647,0.5093596],"nameFile":"350eac1f-ecca-4439-9a86-7bcef44f780c","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":5,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.794,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.498,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.415,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.749,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.474,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":1.0,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.466,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.289,"a9672650-c335-484a-9555-71a35c841aa1":0.658,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.874,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.414,"d6466821-6776-4f40-9609-2342debf5c86":0.306},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"8443f966-0d88-4ec7-a20e-8edf73fa62f6","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Alakrita","shortName":"Alakrita","description":"Speed. Elegance. Alakrita.","logo":"","personality":{},"primaryColor":[0.04705884,0.628758132,0.745098054],"secondaryColor":[0.264150918,0.0,0.0],"nameFile":"86257ba5-2c68-4b6f-a269-7f02ff7372c3","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":4,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.555,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.708,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.022,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.598,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.606,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.284,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.823,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":1.0,"a9672650-c335-484a-9555-71a35c841aa1":0.325,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.085,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.908,"d6466821-6776-4f40-9609-2342debf5c86":0.809},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"a1f76631-d6d1-443a-9be1-c9b1267d6ca2","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Death Monkey Explosives","shortName":"DME","description":"Some people just want to watch the world burn. We’re here to help!","logo":"","personality":{},"primaryColor":[0.8980392,0.564925969,0.0980392247],"secondaryColor":[0.819607854,0.279215753,0.196078435],"nameFile":"ecffecc1-d0b9-4014-be4d-442f72382721","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":3,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.289,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.727,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.313,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.724,"8419f9bc-0167-46ec-86c3-3265d2905fbc":1.0,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.544,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.784,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.817,"a9672650-c335-484a-9555-71a35c841aa1":0.106,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.148,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.973,"d6466821-6776-4f40-9609-2342debf5c86":0.973},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"8419f9bc-0167-46ec-86c3-3265d2905fbc","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Ewan Hart Inc","shortName":"Ewan Hart","description":"Money does grow on trees","logo":"","personality":{},"primaryColor":[0.0,0.764151,0.299815148],"secondaryColor":[0.146092921,0.46226418,0.324359715],"nameFile":"cfbb1969-2a8c-40dd-9f5d-c1b9e69d356d","bossHull":"00000000-0000-0000-0000-000000000000","influence":2,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.874,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.162,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.953,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.559,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.233,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.973,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.491,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.166,"a9672650-c335-484a-9555-71a35c841aa1":1.0,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.875,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.068,"d6466821-6776-4f40-9609-2342debf5c86":0.257},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"a9672650-c335-484a-9555-71a35c841aa1","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Finch Cybernetics","shortName":"Finch","description":"“The search for knowledge is the duty of all intelligent beings.”","logo":"Assets/Resources/Sprites/Icons/Logos/finch.png","personality":{"0e91c198-d6c6-4d28-a7e0-d5316db3b7d0":0.2,"2103d2d5-bf5c-4dd9-9381-c90f1e39496f":0.25,"3f608054-8e4a-43fb-926c-261da4cc92d9":0.9,"8e5a2064-9603-4205-baf7-4d037ebfda90":0.4,"d6506d2d-3699-4c8c-8e90-5e4b8f2f43b9":0.7},"primaryColor":[0.4552703,0.0,1.0],"secondaryColor":[1.0,0.0,0.0],"nameFile":"43872e8e-df2f-4e03-81bb-e1d71f39b696","bossHull":"00000000-0000-0000-0000-000000000000","influence":5,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.262,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":1.0,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.567,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.215,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.651,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.536,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.848,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.628,"a9672650-c335-484a-9555-71a35c841aa1":0.481,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.638,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.959,"d6466821-6776-4f40-9609-2342debf5c86":0.087},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"1dfaa629-6c63-42a7-91e1-f1ae90f92f09","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Lightsail Express","shortName":"Lightsail","description":"We’ll lose our lives before we lose your cargo.","logo":"","personality":{},"primaryColor":[0.324836552,0.270588249,0.596078455],"secondaryColor":[0.6690326,0.6629583,0.735849],"nameFile":"fc790c9c-8b47-4519-8f2c-2486185f9064","bossHull":"00000000-0000-0000-0000-000000000000","influence":3,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.754,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.181,"2f74e6b4-d268-48a9-b2a8-24591c680e84":1.0,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.333,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.313,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.653,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.544,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.056,"a9672650-c335-484a-9555-71a35c841aa1":0.792,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.967,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.197,"d6466821-6776-4f40-9609-2342debf5c86":0.126},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"2f74e6b4-d268-48a9-b2a8-24591c680e84","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Lucent Media","shortName":"Lucent","description":"“People will do anything for the adulation or loathing of their peers. We at Lucent have harnessed that heretofore destructive tendency for the benefit of all.”","logo":"Assets/Resources/Sprites/Icons/Logos/lucent.png","personality":{"0e91c198-d6c6-4d28-a7e0-d5316db3b7d0":0.7,"2103d2d5-bf5c-4dd9-9381-c90f1e39496f":0.9,"3f608054-8e4a-43fb-926c-261da4cc92d9":0.3,"8e5a2064-9603-4205-baf7-4d037ebfda90":0.6,"d6506d2d-3699-4c8c-8e90-5e4b8f2f43b9":0.2},"primaryColor":[0.8396226,0.04356533,0.3411568],"secondaryColor":[0.821494758,0.08962262,1.0],"nameFile":"35f90a4b-460c-416c-9a4e-f7e661850787","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":6,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.252,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.679,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.305,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.914,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.831,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.808,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":1.0,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.714,"a9672650-c335-484a-9555-71a35c841aa1":0.329,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.333,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.583,"d6466821-6776-4f40-9609-2342debf5c86":0.53},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"a012e0f4-4b22-47b7-8b24-ff3e1439c949","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Miss Terri’s Sugariffic Snack Company","shortName":"Miss Terri's","description":"Candy for all! Suspiciously experimental substances for some!","logo":"Assets/Resources/Sprites/Icons/Logos/miss_terri.png","personality":{"0e91c198-d6c6-4d28-a7e0-d5316db3b7d0":0.75,"2103d2d5-bf5c-4dd9-9381-c90f1e39496f":0.9,"3f608054-8e4a-43fb-926c-261da4cc92d9":0.8},"primaryColor":[1.0,0.0500000119,0.6796082],"secondaryColor":[0.9150943,0.9150943,0.9150943],"nameFile":"8af167f7-2ac7-4cba-b204-25f5a6ba5f33","bossHull":"00000000-0000-0000-0000-000000000000","influence":2,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.048,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.587,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.429,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.914,"8419f9bc-0167-46ec-86c3-3265d2905fbc":1.0,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.402,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.802,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.718,"a9672650-c335-484a-9555-71a35c841aa1":0.216,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.059,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.939,"d6466821-6776-4f40-9609-2342debf5c86":1.0},"overworldMusic":237948771,"combatMusic":0,"bossMusic":0,"id":"d6466821-6776-4f40-9609-2342debf5c86","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"NiteLife Energy","shortName":"NiteLife","description":"We keep the lights on, so you can keep on keeping on.","logo":"","personality":{},"primaryColor":[0.2235294,0.611764669,1.0],"secondaryColor":[0.7075472,0.2236116,0.7007313],"nameFile":"d0959e52-7726-4510-bdaa-c267c58f2855","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":4,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.25,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.5,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.2,"73d368dd-58a8-4431-b9ba-2d44754d36a1":1.0,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.9,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.75,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":1.0,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.75,"a9672650-c335-484a-9555-71a35c841aa1":0.6,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.25,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.5,"d6466821-6776-4f40-9609-2342debf5c86":0.75},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"73d368dd-58a8-4431-b9ba-2d44754d36a1","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Rossum & Douglas","shortName":"R&D","description":null,"logo":"","personality":{},"primaryColor":[0.735849,0.689622641,0.510234952],"secondaryColor":[0.254717,0.254717,0.254717],"nameFile":"dfb8e9b0-31cd-4ff9-b6f3-bae707469e7c","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":5,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":0.5,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.8,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.6,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.4,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.1,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":1.0,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.3,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.25,"a9672650-c335-484a-9555-71a35c841aa1":0.6,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.75,"d6466821-6776-4f40-9609-2342debf5c86":0.1},"overworldMusic":0,"combatMusic":0,"bossMusic":0,"id":"adfb9b08-aabc-45c6-9586-915698a9c4b0","$type":"Faction"}

View file

@ -0,0 +1 @@
{"name":"Zhestokost","shortName":"Zhestokost","description":"\"It is a truth universally acknowledged that nothing is as useful in diplomacy and warfare as a gigantic nuclear arsenal.\"","logo":"Assets/Resources/Sprites/Icons/Logos/colferv.png","personality":{"0e91c198-d6c6-4d28-a7e0-d5316db3b7d0":0.25,"2103d2d5-bf5c-4dd9-9381-c90f1e39496f":0.3},"primaryColor":[1.0,0.0500000119,0.0500000119],"secondaryColor":[1.0,1.0,0.0500000119],"nameFile":"5fb6de6e-616e-478c-9323-58f197af51b9","bossHull":"bb5d9f73-612f-4060-8fb4-f72d6b93b616","influence":6,"allegiance":{"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3":1.0,"1dfaa629-6c63-42a7-91e1-f1ae90f92f09":0.162,"2f74e6b4-d268-48a9-b2a8-24591c680e84":0.724,"73d368dd-58a8-4431-b9ba-2d44754d36a1":0.186,"8419f9bc-0167-46ec-86c3-3265d2905fbc":0.305,"8443f966-0d88-4ec7-a20e-8edf73fa62f6":0.632,"a012e0f4-4b22-47b7-8b24-ff3e1439c949":0.325,"a1f76631-d6d1-443a-9be1-c9b1267d6ca2":0.153,"a9672650-c335-484a-9555-71a35c841aa1":0.541,"adfb9b08-aabc-45c6-9586-915698a9c4b0":0.919,"bbd619ed-76c1-464c-829d-3f419cdc2525":0.027,"d6466821-6776-4f40-9609-2342debf5c86":0.182},"overworldMusic":3285854189,"combatMusic":681474673,"bossMusic":3119006570,"id":"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3","$type":"Faction"}

View file

@ -0,0 +1 @@
{"hardpointType":6,"schematic":"","behaviors":[{"targetTemp":273.15,"highPass":true,"adjustable":false,"group":0,"$type":"ThermotoggleData"},{"emissivity":{"min":2.0,"max":5.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.25,"qualityExponent":1.5},"pumpedHeat":{"min":750.0,"max":4000.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.5,"qualityExponent":2.0},"temperatureFloor":273.15,"wasteHeat":{"min":75.0,"max":50.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.5,"qualityExponent":1.5},"energyUsage":{"min":3.0,"max":2.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.5,"qualityExponent":1.25},"thermalMass":{"min":65.0,"max":105.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.0,"qualityExponent":2.0},"group":0,"$type":"RadiatorData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":30.0,"minTemp":223.15,"maxTemp":473.15,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":2.0,"actionIcon":"","soundBank":0,"audioStats":[],"name":"Arctica","description":"Go blazingly fast, without burning up.","creator":"a1f76631-d6d1-443a-9be1-c9b1267d6ca2","mass":50.0,"shape":{"name":[[true],[true]]},"specificHeat":1.0,"conductivity":1.0,"price":350000,"id":"2935b4d4-2ad5-4b90-8416-a85bbb38171b","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":1,"schematic":"","behaviors":[null],"durability":0.0,"minTemp":273.15,"maxTemp":373.15,"heatCurve":null,"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Assembly Line","description":"Yup it updated.","creator":"00000000-0000-0000-0000-000000000000","mass":1300.0,"shape":{"name":[[true]]},"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"a4d971ab-d312-461e-814a-15210606c51d","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":12,"schematic":"","behaviors":[{"targetTemp":288.15,"highPass":false,"adjustable":false,"group":0,"$type":"ThermotoggleData"},{"draw":{"min":25.0,"max":25.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"perSecond":true,"group":0,"$type":"EnergyDrawData"},{"group":1,"$type":"CockpitData"},{"heat":{"min":200.0,"max":200.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"perSecond":true,"group":0,"$type":"HeatData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":223.15,"maxTemp":398.15,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":5.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Cockpit 2x2","description":"","creator":"2f74e6b4-d268-48a9-b2a8-24591c680e84","mass":50.0,"shape":{"name":[[true,true],[true,true]]},"specificHeat":1.0,"conductivity":1.0,"price":50000,"id":"31325c3d-0537-40ec-9e5e-80930ea01496","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":5,"schematic":"","behaviors":[{"charge":{"min":100.0,"max":100.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":1.5},"efficiency":{"min":0.05,"max":0.1,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.8},"overload":{"min":0.001,"max":0.005,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":2.0},"underload":{"min":1.5,"max":3.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":1.75},"group":0,"$type":"ReactorData"},{"perSecond":false,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":200.0,"maxTemp":450.0,"heatCurve":{"keys":[]},"resilience":250.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Core Power","description":"It gets the job done, but that's all.","creator":"00000000-0000-0000-0000-000000000000","mass":50.0,"shape":{"name":[[true,true],[true,true]]},"specificHeat":2.5,"conductivity":1.0,"price":250000,"id":"4bc1fe6f-347a-425e-be1b-997920175bee","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":1,"schematic":"","behaviors":[null],"durability":0.0,"minTemp":273.15,"maxTemp":373.15,"heatCurve":null,"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Deep Ore Extractor","description":"Get the most out of your resource rights! The Deep Ore Extractor ensures that any planet or asteroid you choose to mine will be left a hollow, barren husk, just as nature intended.","creator":"00000000-0000-0000-0000-000000000000","mass":550.0,"shape":{"name":[[true]]},"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"518e1b4c-4c6c-4a9a-903f-940e3ac91ad5","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":1,"schematic":"","behaviors":[{"targetTemp":288.15,"highPass":false,"adjustable":false,"group":0,"$type":"ThermotoggleData"},{"draw":{"min":1000.0,"max":2500.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":1.0},"perSecond":true,"group":0,"$type":"EnergyDrawData"},{"heat":{"min":50000.0,"max":100000.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":1.0},"perSecond":true,"group":0,"$type":"HeatData"}],"durability":0.0,"minTemp":150.0,"maxTemp":400.0,"heatCurve":null,"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Industrial Thermostatic Heater","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":250.0,"shape":{"name":[[false,true,true,false],[true,true,true,true],[true,true,true,true],[false,true,true,false]]},"specificHeat":2.0,"conductivity":1.0,"price":0,"id":"2c911da4-fad0-4a38-be5b-5e327c0c9e43","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":3,"schematic":"","behaviors":[{"thrust":{"min":250000.0,"max":250000.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":1.0},"visibility":{"min":100.0,"max":100.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":1.0},"heat":{"min":2500.0,"max":2500.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":1.0},"energy":{"min":0.0,"max":0.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"Particles":"Assets/Resources/Prefabs/Thrusters/Thruster 1.prefab","group":0,"$type":"ThrusterData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":200.0,"maxTemp":400.0,"heatCurve":null,"resilience":10.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Large Drive","description":"Keeps you going and going and going...","creator":"00000000-0000-0000-0000-000000000000","mass":100.0,"shape":{"name":[[true,true],[true,true]]},"specificHeat":2.5,"conductivity":5.0,"price":100000,"id":"5cd802dd-ef0e-4303-bd87-c30988326e4b","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":6,"schematic":"","behaviors":[{"targetTemp":273.15,"highPass":true,"adjustable":false,"group":0,"$type":"ThermotoggleData"},{"emissivity":{"min":15.0,"max":15.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"pumpedHeat":{"min":2500.0,"max":2500.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"temperatureFloor":278.15,"wasteHeat":{"min":100.0,"max":100.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"energyUsage":{"min":1.0,"max":1.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"thermalMass":{"min":0.0,"max":0.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"group":0,"$type":"RadiatorData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":223.15,"maxTemp":473.15,"heatCurve":null,"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Long Radiator","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":50.0,"shape":{"name":[[true],[true],[true],[true]]},"specificHeat":1.0,"conductivity":1.0,"price":150000,"id":"4b019503-1865-4bad-a6e9-c85b558aacea","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":5,"schematic":"","behaviors":[{"charge":{"min":500.0,"max":1000.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.125,"qualityExponent":1.5},"efficiency":{"min":0.05,"max":0.15,"heatExponentMultiplier":0.03125,"durabilityExponentMultiplier":0.25,"qualityExponent":2.0},"overload":{"min":0.0005,"max":0.005,"heatExponentMultiplier":0.03125,"durabilityExponentMultiplier":0.25,"qualityExponent":3.0},"underload":{"min":1.5,"max":3.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.125,"qualityExponent":1.75},"group":0,"$type":"ReactorData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":200.0,"maxTemp":450.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":10.0,"actionIcon":"","soundBank":2204642885,"audioStats":[],"name":"Manhattan","description":"Because might is right and finesse is for fools","creator":"16bad4f9-7fb5-41c5-8da0-dc76709eb7d3","mass":500.0,"shape":{"name":[[true,true,true],[true,true,true],[true,true,true]]},"specificHeat":2.5,"conductivity":1.0,"price":750000,"id":"3baa2c43-b389-4438-94cb-fbb04489cd77","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":5,"schematic":"","behaviors":[{"charge":{"min":25.0,"max":125.0,"heatExponentMultiplier":0.125,"durabilityExponentMultiplier":0.25,"qualityExponent":1.5},"efficiency":{"min":0.015,"max":0.1,"heatExponentMultiplier":0.0625,"durabilityExponentMultiplier":0.125,"qualityExponent":2.0},"overload":{"min":0.00025,"max":0.005,"heatExponentMultiplier":0.0625,"durabilityExponentMultiplier":0.125,"qualityExponent":2.5},"underload":{"min":2.5,"max":20.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.25,"qualityExponent":2.25},"group":0,"$type":"ReactorData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":200.0,"maxTemp":500.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":5.0,"actionIcon":"","soundBank":2204642885,"audioStats":[],"name":"MoveOnPro","description":"The only muon catalyst fusion reactor on the market! Always gets a great reaction.","creator":"73d368dd-58a8-4431-b9ba-2d44754d36a1","mass":300.0,"shape":{"name":[[true,true],[true,true]]},"specificHeat":2.5,"conductivity":1.0,"price":900000,"id":"372d23cc-5ef0-42b5-9d96-807f2e412b0d","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":5,"schematic":"","behaviors":[{"charge":{"min":400.0,"max":1200.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.125,"qualityExponent":2.0},"efficiency":{"min":0.025,"max":0.1,"heatExponentMultiplier":0.0625,"durabilityExponentMultiplier":0.25,"qualityExponent":2.5},"overload":{"min":0.0005,"max":0.005,"heatExponentMultiplier":0.0625,"durabilityExponentMultiplier":0.25,"qualityExponent":3.0},"underload":{"min":3.0,"max":12.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.25,"qualityExponent":1.75},"group":0,"$type":"ReactorData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":250.0,"maxTemp":450.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":10.0,"actionIcon":"","soundBank":2204642885,"audioStats":[],"name":"Notorious","description":"A reactor for those who want the biggest reaction","creator":"a012e0f4-4b22-47b7-8b24-ff3e1439c949","mass":750.0,"shape":{"name":[[true,true,true],[true,true,true],[true,true,true]]},"specificHeat":2.5,"conductivity":1.0,"price":1000000,"id":"394612a6-9198-4797-a69b-c70cd0ee3273","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":6,"schematic":"","behaviors":[{"targetTemp":273.15,"highPass":true,"adjustable":false,"group":0,"$type":"ThermotoggleData"},{"emissivity":{"min":4.0,"max":8.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.5,"qualityExponent":1.75},"pumpedHeat":{"min":1000.0,"max":4000.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.5,"qualityExponent":2.0},"temperatureFloor":278.15,"wasteHeat":{"min":500.0,"max":100.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.5,"qualityExponent":1.5},"energyUsage":{"min":6.0,"max":3.0,"heatExponentMultiplier":0.25,"durabilityExponentMultiplier":0.5,"qualityExponent":1.75},"thermalMass":{"min":75.0,"max":125.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.0,"qualityExponent":2.0},"group":0,"$type":"RadiatorData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":223.15,"maxTemp":473.15,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":1.0,"actionIcon":"","soundBank":0,"audioStats":[],"name":"OK Disperser","description":"Adapted from the patented cooling system Lucent uses in their professional gaming setups. A high quality cooler, built to withstand even the most aggressive of rage quits.","creator":"a012e0f4-4b22-47b7-8b24-ff3e1439c949","mass":150.0,"shape":{"name":[[true,true],[true,true]]},"specificHeat":1.0,"conductivity":1.0,"price":250000,"id":"542169f2-363c-41f7-8d6d-60a5bd7578bd","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":1,"schematic":"","behaviors":[{"capacity":{"min":50.0,"max":150.0,"heatExponentMultiplier":0.125,"durabilityExponentMultiplier":0.0625,"qualityExponent":2.0},"efficiency":{"min":0.5,"max":0.99,"heatExponentMultiplier":0.0625,"durabilityExponentMultiplier":0.25,"qualityExponent":2.0},"group":0,"$type":"CapacitorData"}],"durability":50.0,"minTemp":200.0,"maxTemp":500.0,"heatCurve":{"keys":[[0.0,0.0,8.389394,8.389394],[0.357228935,0.8660065,-2.46956825,-2.46956825],[1.0,0.0,-0.6179685,-0.6179685]]},"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"PotaT+-","description":"[TODO]","creator":"73d368dd-58a8-4431-b9ba-2d44754d36a1","mass":75.0,"shape":{"name":[[true]]},"specificHeat":1.0,"conductivity":1.0,"price":75000,"id":"34b15c33-c01f-4712-ac75-5fcf779f0685","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":1,"schematic":"","behaviors":[null],"durability":0.0,"minTemp":273.15,"maxTemp":373.15,"heatCurve":null,"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Refinery","description":"Generates plastics, refines raw materials, creates larger molecules","creator":"00000000-0000-0000-0000-000000000000","mass":1300.0,"shape":{"name":[[true]]},"specificHeat":1.0,"conductivity":1.0,"price":0,"id":"18a67053-2407-4bd7-90ca-9c19891594a9","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":1,"schematic":"","behaviors":[null],"durability":0.0,"minTemp":273.15,"maxTemp":373.15,"heatCurve":null,"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Shipyard","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":10000.0,"shape":{"name":[[true]]},"specificHeat":0.0,"conductivity":1.0,"price":0,"id":"c6b994e6-a366-46b2-bc43-8a81944039f0","$type":"GearData"}

View file

@ -0,0 +1 @@
{"hardpointType":6,"schematic":"","behaviors":[{"targetTemp":273.15,"highPass":true,"adjustable":false,"group":0,"$type":"ThermotoggleData"},{"emissivity":{"min":5.0,"max":5.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"pumpedHeat":{"min":1000.0,"max":1000.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"temperatureFloor":278.15,"wasteHeat":{"min":100.0,"max":100.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"energyUsage":{"min":1.0,"max":1.0,"heatExponentMultiplier":1.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"thermalMass":{"min":0.0,"max":0.0,"heatExponentMultiplier":0.0,"durabilityExponentMultiplier":0.0,"qualityExponent":0.0},"group":0,"$type":"RadiatorData"},{"perSecond":true,"group":0,"$type":"WearData"}],"durability":100.0,"minTemp":223.15,"maxTemp":473.15,"heatCurve":null,"resilience":1.0,"actionIcon":null,"soundBank":0,"audioStats":[],"name":"Small Radiator","description":null,"creator":"00000000-0000-0000-0000-000000000000","mass":50.0,"shape":{"name":[[true],[true]]},"specificHeat":1.0,"conductivity":1.0,"price":50000,"id":"bc3870ae-8e31-45ec-99d9-745a4262f78a","$type":"GearData"}

Some files were not shown because too many files have changed in this diff Show more