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]); | |
| }
 | |
| 
 |