You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
4.2 KiB
147 lines
4.2 KiB
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]); |
|
}
|
|
|