Basic loading / saving but it's janky

main
copygirl 6 months ago
parent afe534376d
commit c95a07c9e6
  1. 1
      player/PickupController.cs
  2. 18
      player/Player.cs
  3. 16
      player/player.tscn
  4. 1
      project.godot
  5. 7
      scenes/ItemManager.cs
  6. 136
      scenes/Workshop.cs
  7. 109
      scenes/workshop.tscn
  8. 17
      scripts/MultiplayerManager.cs
  9. 3
      scripts/globals/PhysicsLayer.cs
  10. 12
      ui/LoadSaveMenu.cs
  11. 4
      ui/menu.tscn

@ -158,6 +158,7 @@ public partial class PickupController : Node3D
var result = GetWorld3D().DirectSpaceState.IntersectRay(query); var result = GetWorld3D().DirectSpaceState.IntersectRay(query);
return (result.Count > 0) ? new( return (result.Count > 0) ? new(
// FIXME: Unable to cast object of type 'ReplacePalette' to type 'Godot.CollisionObject3D'.
result["collider"].As<CollisionObject3D>(), result["collider"].As<CollisionObject3D>(),
(Vector3)result["position"], (Vector3)result["position"],
(Vector3)result["normal"] (Vector3)result["normal"]

@ -7,7 +7,10 @@ public partial class Player : CharacterBody3D
public int PeerId => GetMultiplayerAuthority(); public int PeerId => GetMultiplayerAuthority();
/// <summary> Gets the workshop owned by this player. </summary> /// <summary> Gets the workshop owned by this player. </summary>
public Workshop Workshop => Game.Workshops.ByPeerId(PeerId); public Workshop OwnedWorkshop => Game.Workshops.ByPeerId(PeerId);
/// <summary> Gets the workshop the player is physically in, if any. </summary>
public Workshop EnteredWorkshop { get; private set; }
public MovementController Movement { get; private set; } public MovementController Movement { get; private set; }
@ -22,4 +25,17 @@ public partial class Player : CharacterBody3D
Animation = GetNode<AnimationController>(nameof(AnimationController)); Animation = GetNode<AnimationController>(nameof(AnimationController));
Pickup = GetNode<PickupController>(nameof(PickupController)); Pickup = GetNode<PickupController>(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;
}
} }

@ -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="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"] [ext_resource type="Script" path="res://player/Player.cs" id="1_a0mas"]
@ -12,6 +12,9 @@
radius = 0.24 radius = 0.24
height = 1.5 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"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_l8s0f"]
radius = 0.24 radius = 0.24
height = 1.5 height = 1.5
@ -107,6 +110,14 @@ script = ExtResource("1_a0mas")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("CapsuleShape3D_h1mfd") 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="."] [node name="PushbackArea" type="Area3D" parent="."]
collision_layer = 4 collision_layer = 4
collision_mask = 4 collision_mask = 4
@ -231,3 +242,6 @@ external_skeleton = NodePath("../../../../../../../Model/Skeleton/Skeleton3D")
[node name="PickupController" type="Node3D" parent="."] [node name="PickupController" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, -0.45) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, -0.45)
script = ExtResource("2_ns2pe") script = ExtResource("2_ns2pe")
[connection signal="area_entered" from="WorkshopTracker" to="." method="OnWorkshopTrackerAreaEntered"]
[connection signal="area_exited" from="WorkshopTracker" to="." method="OnWorkshopTrackerAreaExited"]

@ -89,6 +89,7 @@ interact_place={
3d_physics/layer_4="Item" 3d_physics/layer_4="Item"
3d_physics/layer_9="Pickup" 3d_physics/layer_9="Pickup"
3d_physics/layer_10="Place" 3d_physics/layer_10="Place"
3d_physics/layer_11="Areas"
[rendering] [rendering]

@ -144,9 +144,12 @@ public partial class ItemManager : Node
{ {
var item = VerifyAuthority(TrackedItems[itemTrackingId], "Item"); var item = VerifyAuthority(TrackedItems[itemTrackingId], "Item");
var player = item.FindParentOrThrow<Player>(); var player = item.FindParentOrThrow<Player>();
var world = GetParent<Node3D>();
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. // Throw item forward and up a bit.
var basis = player.Camera.Camera.GlobalBasis; var basis = player.Camera.Camera.GlobalBasis;

@ -1,3 +1,5 @@
using Dictionary = Godot.Collections.Dictionary;
public partial class Workshop : Area3D public partial class Workshop : Area3D
{ {
/// <summary> Returns whether this workshop is owned by the local player. </summary> /// <summary> Returns whether this workshop is owned by the local player. </summary>
@ -8,4 +10,138 @@ public partial class Workshop : Area3D
/// <summary> Gets the player that owns this workshop. </summary> /// <summary> Gets the player that owns this workshop. </summary>
public Player Player => Game.Players.ByPeerId(PeerId); 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]);
} }

@ -27,10 +27,11 @@ size = Vector3(2, 0.1, 1)
[sub_resource type="BoxMesh" id="BoxMesh_efbik"] [sub_resource type="BoxMesh" id="BoxMesh_efbik"]
size = Vector3(0.1, 0.9, 0.1) size = Vector3(0.1, 0.9, 0.1)
[node name="Workshop" type="Area3D"] [node name="Workshop" type="Area3D" node_paths=PackedStringArray("Objects")]
collision_layer = 0 collision_layer = 1024
collision_mask = 0 collision_mask = 0
script = ExtResource("1_i8qyc") script = ExtResource("1_i8qyc")
Objects = NodePath("Objects")
[node name="ItemManager" type="Node" parent="."] [node name="ItemManager" type="Node" parent="."]
script = ExtResource("1_l6hw6") script = ExtResource("1_l6hw6")
@ -51,124 +52,126 @@ shape = SubResource("WorldBoundaryShape3D_5erfn")
[node name="MeshInstance3D" type="MeshInstance3D" parent="Floor"] [node name="MeshInstance3D" type="MeshInstance3D" parent="Floor"]
mesh = SubResource("PlaneMesh_tg4vq") 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4)
collision_layer = 2 collision_layer = 2
collision_mask = 0 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
GridSize = Vector2i(38, 18) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.95, 0)
shape = SubResource("BoxShape3D_vkl3b") 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.95, 0)
mesh = SubResource("BoxMesh_548mk") 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.9, 0.45, 0.4)
mesh = SubResource("BoxMesh_efbik") mesh = SubResource("BoxMesh_efbik")
skeleton = NodePath("../MeshInstance3D") 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9, 0.45, 0.4)
mesh = SubResource("BoxMesh_efbik") mesh = SubResource("BoxMesh_efbik")
skeleton = NodePath("../MeshInstance3D") 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.9, 0.45, -0.4)
mesh = SubResource("BoxMesh_efbik") mesh = SubResource("BoxMesh_efbik")
skeleton = NodePath("../MeshInstance3D") 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9, 0.45, -0.4)
mesh = SubResource("BoxMesh_efbik") mesh = SubResource("BoxMesh_efbik")
skeleton = NodePath("../MeshInstance3D") 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) transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1.5, -4.6)
collision_layer = 2 collision_layer = 2
collision_mask = 0 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0)
GridSize = Vector2i(38, 18) 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0499997, 0)
shape = SubResource("BoxShape3D_vkl3b") 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) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0499997, 0)
mesh = SubResource("BoxMesh_548mk") mesh = SubResource("BoxMesh_548mk")
[node name="Crates" type="Node3D" parent="."] [node name="Plank" parent="Objects" instance=ExtResource("4_kupiv")]
[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")]
transform = Transform3D(-0.258819, 0, -0.965926, 0, 1, 0, 0.965926, 0, -0.258819, 1.775, 0.0467873, -4.05) 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) 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) 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) 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"]

@ -1,6 +1,7 @@
public partial class MultiplayerManager : Node public partial class MultiplayerManager : Node
{ {
[Export] public PackedScene PlayerScene { get; set; } [Export] public PackedScene PlayerScene { get; set; }
[Export] public PackedScene WorkshopScene { get; set; }
public event Action<Player> PlayerJoined; public event Action<Player> PlayerJoined;
public event Action<Player> PlayerLeft; public event Action<Player> PlayerLeft;
@ -40,6 +41,7 @@ public partial class MultiplayerManager : Node
void OnMultiplayerReady() void OnMultiplayerReady()
{ {
SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId()); SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId());
SetAuthorityAndName(Game.LocalWorkshop, Multiplayer.GetUniqueId());
// Spawn players for all the other peers. This excludes the server, // Spawn players for all the other peers. This excludes the server,
// since `OnPeerConnected` will already be called for it on connecting. // since `OnPeerConnected` will already be called for it on connecting.
@ -57,6 +59,7 @@ public partial class MultiplayerManager : Node
OnPeerDisconnected(player.PeerId); OnPeerDisconnected(player.PeerId);
SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId()); SetAuthorityAndName(Game.LocalPlayer, Multiplayer.GetUniqueId());
SetAuthorityAndName(Game.LocalWorkshop, Multiplayer.GetUniqueId());
} }
void OnPeerConnected(long _peerId) void OnPeerConnected(long _peerId)
@ -64,6 +67,7 @@ public partial class MultiplayerManager : Node
var player = PlayerScene.Instantiate<Player>(); var player = PlayerScene.Instantiate<Player>();
SetAuthorityAndName(player, (int)_peerId); SetAuthorityAndName(player, (int)_peerId);
Game.Players.AddChild(player); Game.Players.AddChild(player);
PlayerJoined?.Invoke(player); PlayerJoined?.Invoke(player);
} }
@ -71,14 +75,19 @@ public partial class MultiplayerManager : Node
{ {
var player = Game.Players.ByPeerId((int)_peerId); var player = Game.Players.ByPeerId((int)_peerId);
Game.Players.RemoveChild(player); Game.Players.RemoveChild(player);
PlayerLeft?.Invoke(player);
player.QueueFree(); 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); node.SetMultiplayerAuthority(peerId);
player.Name = peerId.ToString(); node.Name = peerId.ToString();
} }
} }

@ -14,4 +14,7 @@ public enum PhysicsLayer : uint
Pickup = 1 << 8, Pickup = 1 << 8,
/// <summary> Objects that other objects may be placed against. </summary> /// <summary> Objects that other objects may be placed against. </summary>
Place = 1 << 9, Place = 1 << 9,
/// <summary> Various areas, such as workshops. </summary>
Areas = 1 << 10,
} }

@ -5,6 +5,9 @@ public partial class LoadSaveMenu : MarginContainer
[Export] public FileDialog LoadFileDialog { get; set; } [Export] public FileDialog LoadFileDialog { get; set; }
[Export] public FileDialog SaveFileDialog { get; set; } [Export] public FileDialog SaveFileDialog { get; set; }
[Export] public Label Filename { get; set; }
[Export] public Label LastSaved { get; set; }
public override void _EnterTree() public override void _EnterTree()
{ {
DirAccess.MakeDirAbsolute(SAVES_FOLDER); DirAccess.MakeDirAbsolute(SAVES_FOLDER);
@ -20,6 +23,7 @@ public partial class LoadSaveMenu : MarginContainer
public void OnOverwriteSavePressed() public void OnOverwriteSavePressed()
{ {
OnSaveFileDialogSelected(Filename.Text);
} }
public void OnCreateSavePressed() public void OnCreateSavePressed()
@ -30,9 +34,17 @@ public partial class LoadSaveMenu : MarginContainer
public void OnLoadFileDialogSelected(string path) 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) public void OnSaveFileDialogSelected(string path)
{ {
Game.LocalWorkshop.SaveToFile(path);
Filename.Text = path;
LastSaved.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
} }
} }

@ -105,7 +105,7 @@ size_flags_vertical = 3
tabs_visible = false tabs_visible = false
use_hidden_tabs_for_min_size = true 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 layout_mode = 2
theme_override_constants/margin_left = 8 theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8 theme_override_constants/margin_top = 8
@ -114,6 +114,8 @@ theme_override_constants/margin_bottom = 8
script = ExtResource("2_0yqy1") script = ExtResource("2_0yqy1")
LoadFileDialog = NodePath("LoadFileDialog") LoadFileDialog = NodePath("LoadFileDialog")
SaveFileDialog = NodePath("SaveFileDialog") 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"] [node name="LoadFileDialog" type="FileDialog" parent="PanelContainer/MarginContainer/VBoxContainer/GridContainer/TabContainer/LoadSave"]
title = "Open a File" title = "Open a File"

Loading…
Cancel
Save