From e62d7f5ee6895f477908f15dee4f4438b259282b Mon Sep 17 00:00:00 2001 From: copygirl Date: Sat, 1 May 2021 15:33:41 +0200 Subject: [PATCH] Merge SyncObject and SyncProperty attributes - New attribute name: Sync - No longer provide Scene or Container information to Sync attribute - Scene name comes from Type name - Container node is simply /Game/World - Remove unnecessary container properties from Game class --- scene/GameScene.tscn | 6 ------ src/Network/NetworkRPC.cs | 4 ++-- src/Network/Sync.cs | 4 ++-- src/Network/SyncClient.cs | 4 ++-- src/Network/SyncRegistry.cs | 34 ++++++++++------------------------ src/Network/SyncServer.cs | 6 +++--- src/Objects/Block.cs | 6 +++--- src/Objects/Player.cs | 8 ++++---- src/Scenes/Game.cs | 12 ------------ 9 files changed, 26 insertions(+), 58 deletions(-) diff --git a/scene/GameScene.tscn b/scene/GameScene.tscn index 62e943a..97024f3 100644 --- a/scene/GameScene.tscn +++ b/scene/GameScene.tscn @@ -5,11 +5,5 @@ [node name="Game" type="Node2D"] pause_mode = 2 script = ExtResource( 3 ) -PlayerContainerPath = NodePath("World/Players") -BlockContainerPath = NodePath("World/Blocks") [node name="World" type="Node" parent="."] - -[node name="Players" type="Node" parent="World"] - -[node name="Blocks" type="Node" parent="World"] diff --git a/src/Network/NetworkRPC.cs b/src/Network/NetworkRPC.cs index 578839c..654a7bd 100644 --- a/src/Network/NetworkRPC.cs +++ b/src/Network/NetworkRPC.cs @@ -89,8 +89,8 @@ public static class NetworkRPC var rpc = method.GetCustomAttribute(); if (rpc == null) continue; - if (!method.IsStatic && (type.GetCustomAttribute() == null)) throw new Exception( - $"Type of non-static RPC method '{method.DeclaringType}.{method.Name}' must have {nameof(SyncObjectAttribute)}"); + if (!method.IsStatic && (type.GetCustomAttribute() == null)) throw new Exception( + $"Type of non-static RPC method '{method.DeclaringType}.{method.Name}' must have {nameof(SyncAttribute)}"); var deSerializers = new List(); var paramEnumerable = ((IEnumerable)method.GetParameters()).GetEnumerator(); diff --git a/src/Network/Sync.cs b/src/Network/Sync.cs index dafca7b..a4b364f 100644 --- a/src/Network/Sync.cs +++ b/src/Network/Sync.cs @@ -23,8 +23,8 @@ public class Sync public SyncStatus GetStatusOrNull(Node obj) { - if (obj.GetType().GetCustomAttribute() == null) - throw new ArgumentException($"Type {obj.GetType()} is missing {nameof(SyncObjectAttribute)}"); + if (obj.GetType().GetCustomAttribute() == null) + throw new ArgumentException($"Type {obj.GetType()} is missing {nameof(SyncAttribute)}"); return StatusByObject.TryGetValue(obj, out var value) ? value : null; } public SyncStatus GetStatusOrThrow(Node obj) diff --git a/src/Network/SyncClient.cs b/src/Network/SyncClient.cs index ea3da06..f6b27a1 100644 --- a/src/Network/SyncClient.cs +++ b/src/Network/SyncClient.cs @@ -20,11 +20,11 @@ public class SyncClient : Sync if (packetObj.Mode != SyncMode.Spawn) throw new Exception( $"Unknown synced object {info.Name} (ID {packetObj.SyncID})"); - var obj = info.InstanceScene.Init(); + var obj = info.Scene.Init(); status = new SyncStatus(packetObj.SyncID, obj, info); StatusBySyncID.Add(status.SyncID, status); StatusByObject.Add(status.Object, status); - Client.GetNode(info.ContainerNodePath).AddChild(obj); + Client.GetNode("World").AddChild(obj); } else { if (packetObj.Mode == SyncMode.Spawn) throw new Exception( $"Spawning object {info.Name} with ID {packetObj.SyncID}, but it already exists"); diff --git a/src/Network/SyncRegistry.cs b/src/Network/SyncRegistry.cs index 98d73ef..197575d 100644 --- a/src/Network/SyncRegistry.cs +++ b/src/Network/SyncRegistry.cs @@ -11,15 +11,15 @@ public static class SyncRegistry static SyncRegistry() { foreach (var type in typeof(SyncRegistry).Assembly.GetTypes()) { - var objAttr = type.GetCustomAttribute(); + var objAttr = type.GetCustomAttribute(); if (objAttr == null) continue; if (!typeof(Node).IsAssignableFrom(type)) throw new Exception( - $"Type {type} with {nameof(SyncObjectAttribute)} must be a subclass of {nameof(Node)}"); + $"Type {type} with {nameof(SyncAttribute)} must be a subclass of {nameof(Node)}"); var objInfo = new SyncObjectInfo((ushort)_byID.Count, type); foreach (var property in type.GetProperties()) { - if (property.GetCustomAttribute() == null) continue; + if (property.GetCustomAttribute() == null) continue; var propType = typeof(SyncPropertyInfo<,>).MakeGenericType(type, property.PropertyType); var propInfo = (SyncPropertyInfo)Activator.CreateInstance(propType, (byte)objInfo.PropertiesByID.Count, property); objInfo.PropertiesByID.Add(propInfo); @@ -41,7 +41,7 @@ public static class SyncRegistry => Get(typeof(T)); public static SyncObjectInfo Get(Type type) => _byType.TryGetValue(type, out var value) ? value : throw new Exception( - $"No {nameof(SyncObjectInfo)} found for type {type} (missing {nameof(SyncObjectAttribute)}?)"); + $"No {nameof(SyncObjectInfo)} found for type {type} (missing {nameof(SyncAttribute)}?)"); } @@ -49,22 +49,17 @@ public class SyncObjectInfo { public ushort ID { get; } public Type Type { get; } + public PackedScene Scene { get; } public string Name => Type.Name; - public PackedScene InstanceScene { get; } - public string ContainerNodePath { get; } - public List PropertiesByID { get; } = new List(); public Dictionary PropertiesByName { get; } = new Dictionary(); public SyncObjectInfo(ushort id, Type type) { - ID = id; - Type = type; - - var attr = type.GetCustomAttribute(); - InstanceScene = GD.Load($"res://scene/{attr.Scene}.tscn"); - ContainerNodePath = attr.Container; + ID = id; + Type = type; + Scene = GD.Load($"res://scene/{type.Name}.tscn"); } } @@ -95,16 +90,7 @@ public class SyncPropertyInfo : SyncPropertyInfo } -[AttributeUsage(AttributeTargets.Class)] -public class SyncObjectAttribute : Attribute -{ - public string Scene { get; } - public string Container { get; } - public SyncObjectAttribute(string scene, string container) - { Scene = scene; Container = container; } -} - -[AttributeUsage(AttributeTargets.Property)] -public class SyncPropertyAttribute : Attribute +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)] +public class SyncAttribute : Attribute { } diff --git a/src/Network/SyncServer.cs b/src/Network/SyncServer.cs index e47b57a..577c9ab 100644 --- a/src/Network/SyncServer.cs +++ b/src/Network/SyncServer.cs @@ -17,12 +17,12 @@ public class SyncServer : Sync where T : Node { var info = SyncRegistry.Get(); - var obj = info.InstanceScene.Init(); + var obj = info.Scene.Init(); var status = new SyncStatus(_syncIDCounter++, obj, info){ Mode = SyncMode.Spawn }; StatusBySyncID.Add(status.SyncID, status); StatusByObject.Add(status.Object, status); _dirtyObjects.Add(status); - Server.GetNode(info.ContainerNodePath).AddChild(obj); + Server.GetNode("World").AddChild(obj); return obj; } @@ -45,7 +45,7 @@ public class SyncServer : Sync { var status = GetStatusOrThrow(obj); if (!status.Info.PropertiesByName.TryGetValue(property, out var propInfo)) throw new ArgumentException( - $"No {nameof(SyncPropertyInfo)} found for {obj.GetType()}.{property} (missing {nameof(SyncPropertyAttribute)}?)", nameof(property)); + $"No {nameof(SyncPropertyInfo)} found for {obj.GetType()}.{property} (missing {nameof(SyncAttribute)}?)", nameof(property)); if (!(obj.GetGame() is Server)) return; status.DirtyProperties |= 1 << propInfo.ID; diff --git a/src/Objects/Block.cs b/src/Objects/Block.cs index 87c9583..dcf060e 100644 --- a/src/Objects/Block.cs +++ b/src/Objects/Block.cs @@ -1,15 +1,15 @@ using Godot; -[SyncObject("Block", "World/Blocks")] +[Sync] public class Block : StaticBody2D { - [SyncProperty] + [Sync] public new BlockPos Position { get => BlockPos.FromVector(base.Position); set => base.Position = this.SetSync(value).ToVector(); } - [SyncProperty] + [Sync] public Color Color { get => Modulate; set => Modulate = this.SetSync(value); diff --git a/src/Objects/Player.cs b/src/Objects/Player.cs index 4fa91a1..cb0edab 100644 --- a/src/Objects/Player.cs +++ b/src/Objects/Player.cs @@ -2,7 +2,7 @@ using System; using Godot; // TODO: Maybe figure out how we can make different classes (LocalPlayer, NPCPlayer) synchronizable. -[SyncObject("Player", "World/Players")] +[Sync] public class Player : KinematicBody2D, IInitializer { [Export] public NodePath DisplayNamePath { get; set; } @@ -14,19 +14,19 @@ public class Player : KinematicBody2D, IInitializer public bool IsLocal { get; private set; } = false; - [SyncProperty] + [Sync] public new Vector2 Position { get => base.Position; set { if (!IsLocal) base.Position = this.SetSync(value); } } - [SyncProperty] + [Sync] public Color Color { get => Sprite.Modulate; set => Sprite.Modulate = this.SetSync(value); } - [SyncProperty] + [Sync] public string DisplayName { get => DisplayNameLabel.Text; set => DisplayNameLabel.Text = this.SetSync(value); diff --git a/src/Scenes/Game.cs b/src/Scenes/Game.cs index b53ec52..54836d8 100644 --- a/src/Scenes/Game.cs +++ b/src/Scenes/Game.cs @@ -6,22 +6,10 @@ public abstract class Game : Node2D { public Sync Sync { get; protected set; } - [Export] public NodePath PlayerContainerPath { get; set; } - [Export] public NodePath BlockContainerPath { get; set; } - - public Node PlayerContainer { get; private set; } - public Node BlockContainer { get; private set; } - // Using _EnterTree to make sure this code runs before any other. public override void _EnterTree() => GD.Randomize(); - public override void _Ready() - { - PlayerContainer = GetNode(PlayerContainerPath); - BlockContainer = GetNode(BlockContainerPath); - } - // NOTE: When multithreaded physics are enabled, DirectSpaceState can only be used in _PhysicsProcess. public Block GetBlockAt(BlockPos position) => GetWorld2d().DirectSpaceState.IntersectPoint(position.ToVector()).Cast()