|
|
|
using Dictionary = Godot.Collections.Dictionary;
|
|
|
|
|
|
|
|
public partial class Workshop : Area3D
|
|
|
|
{
|
|
|
|
/// <summary> Returns whether this workshop is owned by the local player. </summary>
|
|
|
|
public bool IsLocal => this.IsAuthority();
|
|
|
|
|
|
|
|
/// <summary> Gets the peer ID of the player owning this workshop. </summary>
|
|
|
|
public int PeerId => GetMultiplayerAuthority();
|
|
|
|
|
|
|
|
/// <summary> Gets the player that owns this workshop. </summary>
|
|
|
|
public Player Player => Game.Players.ByPeerId(PeerId);
|
|
|
|
|
|
|
|
[Export] public Node Objects { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
{
|
|
|
|
// TODO: This is very ugly please send help.
|
|
|
|
var manager = this.GetNodeOrThrow<ItemManager>(nameof(ItemManager));
|
|
|
|
manager.TrackedItems.Clear();
|
|
|
|
|
|
|
|
foreach (var obj in Objects.GetChildren()) {
|
|
|
|
if (obj is Item) {
|
|
|
|
Objects.RemoveChild(obj);
|
|
|
|
obj.QueueFree();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj.GetNodeOrNull(nameof(Grid)) is Grid g)
|
|
|
|
foreach (var child in g.GetChildren().OfType<Item>()) {
|
|
|
|
g.RemoveChild(child);
|
|
|
|
child.QueueFree();
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Do we need to do recursion here?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void FromDictionary(Dictionary dict)
|
|
|
|
{
|
|
|
|
// TODO: File information shouldn't be handled by this.
|
|
|
|
var version = dict["version"].AsInt32();
|
|
|
|
if (version != 0) throw new Exception($"Unknown version '{version}'");
|
|
|
|
|
|
|
|
Clear();
|
|
|
|
|
|
|
|
var manager = this.GetNodeOrThrow<ItemManager>(nameof(ItemManager));
|
|
|
|
var objectsDict = dict["objects"].AsGodotDictionary<string, Dictionary>();
|
|
|
|
foreach (var (childName, childDict) in objectsDict)
|
|
|
|
FromDictionary(manager, Objects, childName, childDict);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void FromDictionary(ItemManager manager, Node parent, string name, Dictionary dict)
|
|
|
|
{
|
|
|
|
Node node;
|
|
|
|
|
|
|
|
if (dict.ContainsKey("scene")) {
|
|
|
|
var sceneName = dict["scene"].AsString();
|
|
|
|
var scene = ResourceLoader.Load<PackedScene>(sceneName, "PackedScene");
|
|
|
|
|
|
|
|
var item = scene.Instantiate<Item>();
|
|
|
|
item.Name = name;
|
|
|
|
item.Transform = ArrayToTransform(dict["transform"].AsFloat32Array());
|
|
|
|
parent.AddChild(item);
|
|
|
|
manager.Add(item);
|
|
|
|
|
|
|
|
node = item;
|
|
|
|
} else {
|
|
|
|
node = parent.GetNodeOrThrow<Node>(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dict.ContainsKey("grid")) {
|
|
|
|
var grid = node.GetNodeOrThrow<Grid>(nameof(Grid));
|
|
|
|
|
|
|
|
var gridDict = dict["grid"].AsGodotDictionary<string, Dictionary>();
|
|
|
|
foreach (var (childName, childDict) in gridDict)
|
|
|
|
FromDictionary(manager, grid, childName, childDict);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Dictionary ToDictionary()
|
|
|
|
{
|
|
|
|
var result = new Dictionary {
|
|
|
|
["version"] = 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
var objects = new Dictionary();
|
|
|
|
foreach (var child in Objects.GetChildren())
|
|
|
|
objects[child.Name] = ToDictionary(child);
|
|
|
|
result["objects"] = objects;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Rework the way object are loaded / saved.
|
|
|
|
// Since it will be likely that objects will have varying data
|
|
|
|
// associated with them, only save the scene / object ID and let
|
|
|
|
// the object itself handle loading and saving its data.
|
|
|
|
static Dictionary ToDictionary(Node node)
|
|
|
|
{
|
|
|
|
var result = new Dictionary();
|
|
|
|
|
|
|
|
if (node is Item item) {
|
|
|
|
result["scene"] = item.SceneFilePath;
|
|
|
|
result["transform"] = TransformToArray(item.Transform);
|
|
|
|
}
|
|
|
|
|
|
|
|
var grid = new Dictionary();
|
|
|
|
if (node.GetNodeOrNull(nameof(Grid)) is Grid g)
|
|
|
|
foreach (var child in g.GetChildren().OfType<Item>())
|
|
|
|
grid[child.Name] = ToDictionary(child);
|
|
|
|
if (grid.Count > 0)
|
|
|
|
result["grid"] = grid;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SaveToFile(string path)
|
|
|
|
{
|
|
|
|
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Write)
|
|
|
|
?? throw new Exception($"Failed to open '{path}' for writing: {FileAccess.GetOpenError()}");
|
|
|
|
file.StoreString(Json.Stringify(ToDictionary()));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void LoadFromFile(string path)
|
|
|
|
{
|
|
|
|
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read)
|
|
|
|
?? throw new Exception($"Failed to open '{path}' for reading: {FileAccess.GetOpenError()}");
|
|
|
|
var json = file.GetLine();
|
|
|
|
|
|
|
|
var dict = Json.ParseString(json).AsGodotDictionary();
|
|
|
|
FromDictionary(dict);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static float[] TransformToArray(Transform3D t)
|
|
|
|
=> [ t[0, 0], t[1, 0], t[2, 0],
|
|
|
|
t[0, 1], t[1, 1], t[2, 1],
|
|
|
|
t[0, 2], t[1, 2], t[2, 2],
|
|
|
|
t[3, 0], t[3, 1], t[3, 2] ];
|
|
|
|
|
|
|
|
static Transform3D ArrayToTransform(float[] a)
|
|
|
|
=> new(a[ 0], a[ 1], a[ 2],
|
|
|
|
a[ 3], a[ 4], a[ 5],
|
|
|
|
a[ 6], a[ 7], a[ 8],
|
|
|
|
a[ 9], a[10], a[11]);
|
|
|
|
}
|