diff --git a/player/PickupController.cs b/player/PickupController.cs index 00f87a2..4c45b53 100644 --- a/player/PickupController.cs +++ b/player/PickupController.cs @@ -158,6 +158,7 @@ public partial class PickupController : Node3D var result = GetWorld3D().DirectSpaceState.IntersectRay(query); return (result.Count > 0) ? new( + // FIXME: Unable to cast object of type 'ReplacePalette' to type 'Godot.CollisionObject3D'. result["collider"].As(), (Vector3)result["position"], (Vector3)result["normal"] diff --git a/player/Player.cs b/player/Player.cs index 07f65cd..17d7871 100644 --- a/player/Player.cs +++ b/player/Player.cs @@ -7,7 +7,10 @@ public partial class Player : CharacterBody3D public int PeerId => GetMultiplayerAuthority(); /// Gets the workshop owned by this player. - public Workshop Workshop => Game.Workshops.ByPeerId(PeerId); + public Workshop OwnedWorkshop => Game.Workshops.ByPeerId(PeerId); + + /// Gets the workshop the player is physically in, if any. + public Workshop EnteredWorkshop { get; private set; } public MovementController Movement { get; private set; } @@ -22,4 +25,17 @@ public partial class Player : CharacterBody3D Animation = GetNode(nameof(AnimationController)); Pickup = GetNode(nameof(PickupController)); } + + + public void OnWorkshopTrackerAreaEntered(Area3D area) + { + if (area is Workshop workshop) + EnteredWorkshop = workshop; + } + + public void OnWorkshopTrackerAreaExited(Area3D area) + { + if (area is Workshop) + EnteredWorkshop = null; + } } diff --git a/player/player.tscn b/player/player.tscn index 22b7275..5757b7b 100644 --- a/player/player.tscn +++ b/player/player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=21 format=3 uid="uid://dmd7w2r8s0x6y"] +[gd_scene load_steps=22 format=3 uid="uid://dmd7w2r8s0x6y"] [ext_resource type="PackedScene" uid="uid://bfh3eqgywr0ul" path="res://assets/models/character.blend" id="1_3qh37"] [ext_resource type="Script" path="res://player/Player.cs" id="1_a0mas"] @@ -12,6 +12,9 @@ radius = 0.24 height = 1.5 +[sub_resource type="BoxShape3D" id="BoxShape3D_gtuvx"] +size = Vector3(0.6, 1.6, 0.6) + [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_l8s0f"] radius = 0.24 height = 1.5 @@ -107,6 +110,14 @@ script = ExtResource("1_a0mas") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] shape = SubResource("CapsuleShape3D_h1mfd") +[node name="WorkshopTracker" type="Area3D" parent="."] +collision_layer = 0 +collision_mask = 1024 +monitorable = false + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WorkshopTracker"] +shape = SubResource("BoxShape3D_gtuvx") + [node name="PushbackArea" type="Area3D" parent="."] collision_layer = 4 collision_mask = 4 @@ -231,3 +242,6 @@ external_skeleton = NodePath("../../../../../../../Model/Skeleton/Skeleton3D") [node name="PickupController" type="Node3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, -0.45) script = ExtResource("2_ns2pe") + +[connection signal="area_entered" from="WorkshopTracker" to="." method="OnWorkshopTrackerAreaEntered"] +[connection signal="area_exited" from="WorkshopTracker" to="." method="OnWorkshopTrackerAreaExited"] diff --git a/project.godot b/project.godot index 9b9bf43..fcab4a2 100644 --- a/project.godot +++ b/project.godot @@ -89,6 +89,7 @@ interact_place={ 3d_physics/layer_4="Item" 3d_physics/layer_9="Pickup" 3d_physics/layer_10="Place" +3d_physics/layer_11="Areas" [rendering] diff --git a/scenes/ItemManager.cs b/scenes/ItemManager.cs index 77b45cd..70384ac 100644 --- a/scenes/ItemManager.cs +++ b/scenes/ItemManager.cs @@ -144,9 +144,12 @@ public partial class ItemManager : Node { var item = VerifyAuthority(TrackedItems[itemTrackingId], "Item"); var player = item.FindParentOrThrow(); - var world = GetParent(); - item.Reparent(world, true); + // FIXME: Actually this doesn't work, the item won't have a Manager anymore. D: + // Add item to workshop, if player is currently in one, otherwise add to world. + var parent = player.EnteredWorkshop?.Objects ?? Game.Instance; + + item.Reparent(parent, true); // Throw item forward and up a bit. var basis = player.Camera.Camera.GlobalBasis; diff --git a/scenes/Workshop.cs b/scenes/Workshop.cs index 6b73de9..a62e137 100644 --- a/scenes/Workshop.cs +++ b/scenes/Workshop.cs @@ -1,3 +1,5 @@ +using Dictionary = Godot.Collections.Dictionary; + public partial class Workshop : Area3D { /// Returns whether this workshop is owned by the local player. @@ -8,4 +10,138 @@ public partial class Workshop : Area3D /// Gets the player that owns this workshop. 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(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()) { + 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(nameof(ItemManager)); + var objectsDict = dict["objects"].AsGodotDictionary(); + 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(sceneName, "PackedScene"); + + var item = scene.Instantiate(); + item.Name = name; + item.Transform = ArrayToTransform(dict["transform"].AsFloat32Array()); + parent.AddChild(item); + manager.Add(item); + + node = item; + } else { + node = parent.GetNodeOrThrow(name); + } + + if (dict.ContainsKey("grid")) { + var grid = node.GetNodeOrThrow(nameof(Grid)); + + var gridDict = dict["grid"].AsGodotDictionary(); + 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()) + 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]); } diff --git a/scenes/workshop.tscn b/scenes/workshop.tscn index 9e6dbe3..de95aed 100644 --- a/scenes/workshop.tscn +++ b/scenes/workshop.tscn @@ -27,10 +27,11 @@ size = Vector3(2, 0.1, 1) [sub_resource type="BoxMesh" id="BoxMesh_efbik"] size = Vector3(0.1, 0.9, 0.1) -[node name="Workshop" type="Area3D"] -collision_layer = 0 +[node name="Workshop" type="Area3D" node_paths=PackedStringArray("Objects")] +collision_layer = 1024 collision_mask = 0 script = ExtResource("1_i8qyc") +Objects = NodePath("Objects") [node name="ItemManager" type="Node" parent="."] script = ExtResource("1_l6hw6") @@ -51,124 +52,126 @@ shape = SubResource("WorldBoundaryShape3D_5erfn") [node name="MeshInstance3D" type="MeshInstance3D" parent="Floor"] mesh = SubResource("PlaneMesh_tg4vq") -[node name="Table" type="StaticBody3D" parent="."] +[node name="Crates" type="Node3D" parent="."] + +[node name="Crate1" parent="Crates" instance=ExtResource("2_j6a20")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0.5, -4) +Palette = ExtResource("3_kvstu") + +[node name="Crate2" parent="Crates" instance=ExtResource("2_j6a20")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0.5, 0) + +[node name="Crate3" parent="Crates" instance=ExtResource("2_j6a20")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0.5, 4) + +[node name="Crate4" parent="Crates" instance=ExtResource("2_j6a20")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 4) + +[node name="Crate5" parent="Crates" instance=ExtResource("2_j6a20")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.5, 4) + +[node name="Crate6" parent="Crates" instance=ExtResource("2_j6a20")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.5, 0) + +[node name="Crate7" parent="Crates" instance=ExtResource("2_j6a20")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.5, -4) + +[node name="Objects" type="Node" parent="."] + +[node name="Table" type="StaticBody3D" parent="Objects"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4) collision_layer = 2 collision_mask = 0 -[node name="Grid" parent="Table" instance=ExtResource("6_okibm")] +[node name="Grid" parent="Objects/Table" instance=ExtResource("6_okibm")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) GridSize = Vector2i(38, 18) -[node name="Nail" parent="Table/Grid" instance=ExtResource("4_6l6v6")] +[node name="Nail" parent="Objects/Table/Grid" instance=ExtResource("4_6l6v6")] transform = Transform3D(-4.37114e-08, -1, -4.37114e-08, 0, -4.37114e-08, 1, -1, 4.37114e-08, 1.91069e-15, -0.75, 0.025, 0.225) -[node name="Nail2" parent="Table/Grid" instance=ExtResource("4_6l6v6")] +[node name="Nail2" parent="Objects/Table/Grid" instance=ExtResource("4_6l6v6")] transform = Transform3D(1.31134e-07, 1, 4.37114e-08, 0, -4.37114e-08, 1, 1, -1.31134e-07, -5.73206e-15, -0.75, 0.025, 0.175) -[node name="Nail3" parent="Table/Grid" instance=ExtResource("4_6l6v6")] +[node name="Nail3" parent="Objects/Table/Grid" instance=ExtResource("4_6l6v6")] transform = Transform3D(-4.37114e-08, -1, -4.37114e-08, 0, -4.37114e-08, 1, -1, 4.37114e-08, 1.91069e-15, -0.75, 0.025, 0.125) -[node name="Nail4" parent="Table/Grid" instance=ExtResource("4_6l6v6")] +[node name="Nail4" parent="Objects/Table/Grid" instance=ExtResource("4_6l6v6")] transform = Transform3D(1.31134e-07, 1, 4.37114e-08, 0, -4.37114e-08, 1, 1, -1.31134e-07, -5.73206e-15, -0.75, 0.025, 0.075) -[node name="Nail5" parent="Table/Grid" instance=ExtResource("4_6l6v6")] +[node name="Nail5" parent="Objects/Table/Grid" instance=ExtResource("4_6l6v6")] transform = Transform3D(-4.37114e-08, -1, -4.37114e-08, 0, -4.37114e-08, 1, -1, 4.37114e-08, 1.91069e-15, -0.75, 0.025, 0.0250001) -[node name="Plank" parent="Table/Grid" instance=ExtResource("4_kupiv")] +[node name="Plank" parent="Objects/Table/Grid" instance=ExtResource("4_kupiv")] transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.775, 0.025, -0.05) -[node name="Cutting Board" parent="Table/Grid" instance=ExtResource("5_hj6pf")] +[node name="Cutting Board" parent="Objects/Table/Grid" instance=ExtResource("5_hj6pf")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.025, 0.2) -[node name="Bolt" parent="Table/Grid/Cutting Board/Grid" index="1" instance=ExtResource("5_r6ljd")] +[node name="Bolt" parent="Objects/Table/Grid/Cutting Board/Grid" index="1" instance=ExtResource("5_r6ljd")] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.1, 0.025, -0.0250001) -[node name="Bolt2" parent="Table/Grid/Cutting Board/Grid" index="2" instance=ExtResource("5_r6ljd")] +[node name="Bolt2" parent="Objects/Table/Grid/Cutting Board/Grid" index="2" instance=ExtResource("5_r6ljd")] transform = Transform3D(-1, 8.74228e-08, 3.82137e-15, 0, -4.37114e-08, 1, 8.74228e-08, 1, 4.37114e-08, 0.15, 0.025, -0.0250001) -[node name="Bolt3" parent="Table/Grid/Cutting Board/Grid" index="3" instance=ExtResource("5_r6ljd")] +[node name="Bolt3" parent="Objects/Table/Grid/Cutting Board/Grid" index="3" instance=ExtResource("5_r6ljd")] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.2, 0.025, -0.0250001) -[node name="CollisionShape3D" type="CollisionShape3D" parent="Table"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Objects/Table"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.95, 0) shape = SubResource("BoxShape3D_vkl3b") -[node name="MeshInstance3D" type="MeshInstance3D" parent="Table"] +[node name="MeshInstance3D" type="MeshInstance3D" parent="Objects/Table"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.95, 0) mesh = SubResource("BoxMesh_548mk") -[node name="Leg1" type="MeshInstance3D" parent="Table"] +[node name="Leg1" type="MeshInstance3D" parent="Objects/Table"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.9, 0.45, 0.4) mesh = SubResource("BoxMesh_efbik") skeleton = NodePath("../MeshInstance3D") -[node name="Leg2" type="MeshInstance3D" parent="Table"] +[node name="Leg2" type="MeshInstance3D" parent="Objects/Table"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9, 0.45, 0.4) mesh = SubResource("BoxMesh_efbik") skeleton = NodePath("../MeshInstance3D") -[node name="Leg3" type="MeshInstance3D" parent="Table"] +[node name="Leg3" type="MeshInstance3D" parent="Objects/Table"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.9, 0.45, -0.4) mesh = SubResource("BoxMesh_efbik") skeleton = NodePath("../MeshInstance3D") -[node name="Leg4" type="MeshInstance3D" parent="Table"] +[node name="Leg4" type="MeshInstance3D" parent="Objects/Table"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9, 0.45, -0.4) mesh = SubResource("BoxMesh_efbik") skeleton = NodePath("../MeshInstance3D") -[node name="Table2" type="StaticBody3D" parent="."] +[node name="Table2" type="StaticBody3D" parent="Objects"] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1.5, -4.6) collision_layer = 2 collision_mask = 0 -[node name="Grid" parent="Table2" instance=ExtResource("6_okibm")] +[node name="Grid" parent="Objects/Table2" instance=ExtResource("6_okibm")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) GridSize = Vector2i(38, 18) -[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Objects/Table2"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0499997, 0) shape = SubResource("BoxShape3D_vkl3b") -[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2"] +[node name="MeshInstance3D" type="MeshInstance3D" parent="Objects/Table2"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0499997, 0) mesh = SubResource("BoxMesh_548mk") -[node name="Crates" type="Node3D" parent="."] - -[node name="Crate1" parent="Crates" instance=ExtResource("2_j6a20")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0.5, -4) -Palette = ExtResource("3_kvstu") - -[node name="Crate2" parent="Crates" instance=ExtResource("2_j6a20")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0.5, 0) - -[node name="Crate3" parent="Crates" instance=ExtResource("2_j6a20")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0.5, 4) - -[node name="Crate4" parent="Crates" instance=ExtResource("2_j6a20")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 4) - -[node name="Crate5" parent="Crates" instance=ExtResource("2_j6a20")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.5, 4) - -[node name="Crate6" parent="Crates" instance=ExtResource("2_j6a20")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.5, 0) - -[node name="Crate7" parent="Crates" instance=ExtResource("2_j6a20")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0.5, -4) - -[node name="Plank" parent="." instance=ExtResource("4_kupiv")] +[node name="Plank" parent="Objects" instance=ExtResource("4_kupiv")] transform = Transform3D(-0.258819, 0, -0.965926, 0, 1, 0, 0.965926, 0, -0.258819, 1.775, 0.0467873, -4.05) -[node name="Plank2" parent="." instance=ExtResource("4_kupiv")] +[node name="Plank2" parent="Objects" instance=ExtResource("4_kupiv")] transform = Transform3D(-0.25506, 0.169814, -0.951897, -0.0338422, 0.982287, 0.184303, 0.966333, 0.0792227, -0.244795, 1.89731, 0.112917, -4.05) -[node name="Plank3" parent="." instance=ExtResource("4_kupiv")] +[node name="Plank3" parent="Objects" instance=ExtResource("4_kupiv")] transform = Transform3D(0.867391, 0.120474, -0.482823, -0.166746, 0.984526, -0.0538993, 0.468858, 0.12726, 0.874058, 2.18736, 0.136963, -4.05) -[node name="Plank4" parent="." instance=ExtResource("4_kupiv")] +[node name="Plank4" parent="Objects" instance=ExtResource("4_kupiv")] transform = Transform3D(0.716486, 0.0834318, -0.692594, -0.166746, 0.984526, -0.0538993, 0.67738, 0.154105, 0.719311, 2.05036, 0.136963, -3.70527) -[editable path="Table/Grid/Cutting Board"] +[editable path="Objects/Table/Grid/Cutting Board"] diff --git a/scripts/MultiplayerManager.cs b/scripts/MultiplayerManager.cs index 8813fd1..de61429 100644 --- a/scripts/MultiplayerManager.cs +++ b/scripts/MultiplayerManager.cs @@ -1,6 +1,7 @@ public partial class MultiplayerManager : Node { [Export] public PackedScene PlayerScene { get; set; } + [Export] public PackedScene WorkshopScene { get; set; } public event Action PlayerJoined; public event Action PlayerLeft; @@ -40,6 +41,7 @@ public partial class MultiplayerManager : Node void OnMultiplayerReady() { SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId()); + SetAuthorityAndName(Game.LocalWorkshop, Multiplayer.GetUniqueId()); // Spawn players for all the other peers. This excludes the server, // since `OnPeerConnected` will already be called for it on connecting. @@ -57,6 +59,7 @@ public partial class MultiplayerManager : Node OnPeerDisconnected(player.PeerId); SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId()); + SetAuthorityAndName(Game.LocalWorkshop, Multiplayer.GetUniqueId()); } void OnPeerConnected(long _peerId) @@ -64,6 +67,7 @@ public partial class MultiplayerManager : Node var player = PlayerScene.Instantiate(); SetAuthorityAndName(player, (int)_peerId); Game.Players.AddChild(player); + PlayerJoined?.Invoke(player); } @@ -71,14 +75,19 @@ public partial class MultiplayerManager : Node { var player = Game.Players.ByPeerId((int)_peerId); Game.Players.RemoveChild(player); - PlayerLeft?.Invoke(player); player.QueueFree(); + + var workshop = Game.Workshops.ByPeerId((int)_peerId); + Game.Workshops.RemoveChild(workshop); + workshop.QueueFree(); + + PlayerLeft?.Invoke(player); } - static void SetAuthorityAndName(Player player, int peerId) + static void SetAuthorityAndName(Node node, int peerId) { - player.SetMultiplayerAuthority(peerId); - player.Name = peerId.ToString(); + node.SetMultiplayerAuthority(peerId); + node.Name = peerId.ToString(); } } diff --git a/scripts/globals/PhysicsLayer.cs b/scripts/globals/PhysicsLayer.cs index 89ba1dc..9bf583e 100644 --- a/scripts/globals/PhysicsLayer.cs +++ b/scripts/globals/PhysicsLayer.cs @@ -14,4 +14,7 @@ public enum PhysicsLayer : uint Pickup = 1 << 8, /// Objects that other objects may be placed against. Place = 1 << 9, + + /// Various areas, such as workshops. + Areas = 1 << 10, } diff --git a/ui/LoadSaveMenu.cs b/ui/LoadSaveMenu.cs index 6440dc6..958eeb5 100644 --- a/ui/LoadSaveMenu.cs +++ b/ui/LoadSaveMenu.cs @@ -5,6 +5,9 @@ public partial class LoadSaveMenu : MarginContainer [Export] public FileDialog LoadFileDialog { get; set; } [Export] public FileDialog SaveFileDialog { get; set; } + [Export] public Label Filename { get; set; } + [Export] public Label LastSaved { get; set; } + public override void _EnterTree() { DirAccess.MakeDirAbsolute(SAVES_FOLDER); @@ -20,6 +23,7 @@ public partial class LoadSaveMenu : MarginContainer public void OnOverwriteSavePressed() { + OnSaveFileDialogSelected(Filename.Text); } public void OnCreateSavePressed() @@ -30,9 +34,17 @@ public partial class LoadSaveMenu : MarginContainer public void OnLoadFileDialogSelected(string path) { + Game.LocalWorkshop.LoadFromFile(path); + Filename.Text = path; + var time = FileAccess.GetModifiedTime(path); + var date = DateTimeOffset.FromUnixTimeSeconds((long)time).LocalDateTime; + LastSaved.Text = date.ToString("yyyy-MM-dd HH:mm:ss"); } public void OnSaveFileDialogSelected(string path) { + Game.LocalWorkshop.SaveToFile(path); + Filename.Text = path; + LastSaved.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); } } diff --git a/ui/menu.tscn b/ui/menu.tscn index fce4ba5..4eef8ef 100644 --- a/ui/menu.tscn +++ b/ui/menu.tscn @@ -105,7 +105,7 @@ size_flags_vertical = 3 tabs_visible = false use_hidden_tabs_for_min_size = true -[node name="LoadSave" type="MarginContainer" parent="PanelContainer/MarginContainer/VBoxContainer/GridContainer/TabContainer" node_paths=PackedStringArray("LoadFileDialog", "SaveFileDialog")] +[node name="LoadSave" type="MarginContainer" parent="PanelContainer/MarginContainer/VBoxContainer/GridContainer/TabContainer" node_paths=PackedStringArray("LoadFileDialog", "SaveFileDialog", "Filename", "LastSaved")] layout_mode = 2 theme_override_constants/margin_left = 8 theme_override_constants/margin_top = 8 @@ -114,6 +114,8 @@ theme_override_constants/margin_bottom = 8 script = ExtResource("2_0yqy1") LoadFileDialog = NodePath("LoadFileDialog") SaveFileDialog = NodePath("SaveFileDialog") +Filename = NodePath("VBoxContainer/GridContainer/Filename") +LastSaved = NodePath("VBoxContainer/GridContainer/LastSaved") [node name="LoadFileDialog" type="FileDialog" parent="PanelContainer/MarginContainer/VBoxContainer/GridContainer/TabContainer/LoadSave"] title = "Open a File"