Skip to content

Commit dd15297

Browse files
committed
Add targeted sync and json message flow
Introduce peer-targeted entity sync so the server can send current state to a specific client on connect, while keeping broadcast sync for normal updates. Route connect handling through internal message processing so clients emit OnConnected only after receiving their assigned peer ID. Allow server startup with an explicit port from NetworkService and replace packet-processor send paths with unified NetworkMessage serialization. BREAKING CHANGE: network packet serialization now uses JSON payloads inside NetworkMessage; previous NetPacketProcessor-based packet format is no longer compatible.
1 parent 0e46c37 commit dd15297

3 files changed

Lines changed: 72 additions & 103 deletions

File tree

KitsuneEngine.Network/NetworkManager.cs

Lines changed: 62 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
using System.Net;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using System.Text;
10+
using System.Text.Json;
911

1012
namespace KitsuneEngine.Network
1113
{
1214
public class NetworkManager : IDisposable
1315
{
1416
private NetManager? _netManager;
1517
private EventBasedNetListener _listener;
16-
private NetDataWriter _dataWriter;
17-
private NetPacketProcessor _packetProcessor;
1818

1919
private readonly NetworkConfig _config;
2020
private readonly ConcurrentDictionary<uint, NetPeer> _peers;
@@ -45,12 +45,9 @@ public NetworkManager(NetworkConfig? config = null)
4545
_incomingMessages = new ConcurrentQueue<NetworkMessage>();
4646
_networkEvents = new ConcurrentQueue<NetworkEventArgs>();
4747
_messageHandlers = new Dictionary<MessageType, Action<NetworkMessage>>();
48-
_dataWriter = new NetDataWriter();
4948
_listener = new EventBasedNetListener();
50-
_packetProcessor = new NetPacketProcessor();
5149

5250
SetupListeners();
53-
RegisterPacketTypes();
5451
}
5552

5653
private void SetupListeners()
@@ -78,11 +75,11 @@ private void SetupListeners()
7875
if (_isServer)
7976
{
8077
SendPeerId(peer, peerId);
78+
_networkEvents.Enqueue(new NetworkEventArgs { PeerId = peerId });
79+
OnConnected?.Invoke(this, new NetworkEventArgs { PeerId = peerId });
8180
}
8281

8382
Log($"Peer connected: {peer.Address}:{peer.Port}");
84-
_networkEvents.Enqueue(new NetworkEventArgs { PeerId = peerId });
85-
OnConnected?.Invoke(this, new NetworkEventArgs { PeerId = peerId });
8683
};
8784

8885
_listener.PeerDisconnectedEvent += (peer, info) =>
@@ -138,57 +135,12 @@ private bool IsReliableDeliveryMethod(LiteNetLib.DeliveryMethod method)
138135
method == LiteNetLib.DeliveryMethod.ReliableOrdered;
139136
}
140137

141-
private void RegisterPacketTypes()
142-
{
143-
// Register serialization methods for custom types
144-
_packetProcessor.RegisterNestedType(WriteVector2, ReadVector2);
145-
_packetProcessor.RegisterNestedType(WriteVector3, ReadVector3);
146-
_packetProcessor.RegisterNestedType(WriteQuaternion, ReadQuaternion);
147-
148-
// Register packet classes
149-
_packetProcessor.SubscribeReusable<ConnectPacket, NetPeer>(OnConnectPacket);
150-
_packetProcessor.SubscribeReusable<EntitySyncPacket, NetPeer>(OnEntitySyncPacket);
151-
_packetProcessor.SubscribeReusable<RPCPacket, NetPeer>(OnRPCPacket);
152-
}
153-
154-
// Serialization methods for custom types
155-
private void WriteVector2(NetDataWriter writer, NetVector2 vector)
156-
{
157-
writer.Put(vector.X);
158-
writer.Put(vector.Y);
159-
}
160-
161-
private NetVector2 ReadVector2(NetDataReader reader)
162-
{
163-
return new NetVector2(reader.GetFloat(), reader.GetFloat());
164-
}
165-
166-
private void WriteVector3(NetDataWriter writer, NetVector3 vector)
167-
{
168-
writer.Put(vector.X);
169-
writer.Put(vector.Y);
170-
writer.Put(vector.Z);
171-
}
172-
173-
private NetVector3 ReadVector3(NetDataReader reader)
174-
{
175-
return new NetVector3(reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
176-
}
177-
178-
private void WriteQuaternion(NetDataWriter writer, NetQuaternion quat)
179-
{
180-
writer.Put(quat.X);
181-
writer.Put(quat.Y);
182-
writer.Put(quat.Z);
183-
writer.Put(quat.W);
184-
}
185-
186-
private NetQuaternion ReadQuaternion(NetDataReader reader)
138+
public void StartServer()
187139
{
188-
return new NetQuaternion(reader.GetFloat(), reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
140+
StartServer(_config.Port);
189141
}
190142

191-
public void StartServer()
143+
public void StartServer(int port)
192144
{
193145
if (_isRunning) return;
194146

@@ -207,10 +159,10 @@ public void StartServer()
207159
UpdateTime = 15
208160
};
209161

210-
_netManager.Start(_config.Port);
162+
_netManager.Start(port);
211163
_isRunning = true;
212164

213-
Log($"Server started on port {_config.Port}");
165+
Log($"Server started on port {port}");
214166

215167
// Start update loop
216168
_cancellationTokenSource = new CancellationTokenSource();
@@ -307,6 +259,8 @@ private void ProcessIncomingMessages()
307259
{
308260
while (_incomingMessages.TryDequeue(out var message))
309261
{
262+
ProcessInternalMessage(message);
263+
310264
OnMessageReceived?.Invoke(this, new NetworkEventArgs
311265
{
312266
PeerId = message.SenderId,
@@ -320,6 +274,25 @@ private void ProcessIncomingMessages()
320274
}
321275
}
322276

277+
private void ProcessInternalMessage(NetworkMessage message)
278+
{
279+
switch (message.Type)
280+
{
281+
case MessageType.Connect:
282+
if (_isServer)
283+
{
284+
return;
285+
}
286+
287+
var connectPacket = Deserialize<ConnectPacket>(message.Data);
288+
_localPeerId = connectPacket.AssignedId;
289+
Log($"Assigned peer ID: {_localPeerId}");
290+
_networkEvents.Enqueue(new NetworkEventArgs { PeerId = _localPeerId });
291+
OnConnected?.Invoke(this, new NetworkEventArgs { PeerId = _localPeerId });
292+
break;
293+
}
294+
}
295+
323296
private void UpdateServer()
324297
{
325298
// Server-specific updates
@@ -336,22 +309,22 @@ public void SendMessage(NetworkMessage message, DeliveryMethod method = Delivery
336309
{
337310
if (!_isRunning || _netManager == null) return;
338311

339-
_dataWriter.Reset();
340-
_dataWriter.Put((byte)message.Type);
341-
_dataWriter.Put(message.SenderId);
342-
_dataWriter.Put(message.TargetId);
343-
_dataWriter.Put(message.Timestamp.ToBinary());
344-
_dataWriter.Put(message.Data);
312+
var writer = new NetDataWriter();
313+
writer.Put((byte)message.Type);
314+
writer.Put(message.SenderId);
315+
writer.Put(message.TargetId);
316+
writer.Put(message.Timestamp.ToBinary());
317+
writer.Put(message.Data);
345318

346319
var netMethod = ConvertDeliveryMethod(method);
347320

348321
if (message.TargetId == 0) // Broadcast
349322
{
350-
_netManager.SendToAll(_dataWriter, (byte)message.Channel, netMethod);
323+
_netManager.SendToAll(writer, (byte)message.Channel, netMethod);
351324
}
352325
else if (_peers.TryGetValue(message.TargetId, out var peer))
353326
{
354-
peer.Send(_dataWriter, (byte)message.Channel, netMethod);
327+
peer.Send(writer, (byte)message.Channel, netMethod);
355328
}
356329
}
357330

@@ -376,49 +349,40 @@ public void SendRPC(string methodName, params object[] args)
376349
Arguments = args
377350
};
378351

379-
SendPacket(packet, DeliveryMethod.ReliableOrdered);
380-
}
381-
382-
private void SendPacket<T>(T packet, DeliveryMethod method) where T : class, new()
383-
{
384-
if (!_isRunning || _netManager == null) return;
385-
386-
_dataWriter.Reset();
387-
_packetProcessor.Write(_dataWriter, packet);
388-
389-
_netManager.SendToAll(_dataWriter, ConvertDeliveryMethod(method));
352+
SendMessage(new NetworkMessage
353+
{
354+
Type = MessageType.RPC,
355+
SenderId = _localPeerId,
356+
TargetId = 0,
357+
Channel = 0,
358+
Timestamp = DateTime.UtcNow,
359+
Data = Serialize(packet)
360+
}, DeliveryMethod.ReliableOrdered);
390361
}
391362

392363
private void SendPeerId(NetPeer peer, uint peerId)
393364
{
394365
var packet = new ConnectPacket { AssignedId = peerId };
395-
SendToPeer(peer, packet, DeliveryMethod.ReliableOrdered);
396-
}
397-
398-
private void SendToPeer<T>(NetPeer peer, T packet, DeliveryMethod method) where T : class, new()
399-
{
400-
_dataWriter.Reset();
401-
_packetProcessor.Write(_dataWriter, packet);
402-
403-
peer.Send(_dataWriter, ConvertDeliveryMethod(method));
404-
}
405-
406-
// Packet handlers
407-
private void OnConnectPacket(ConnectPacket packet, NetPeer peer)
408-
{
409-
_localPeerId = packet.AssignedId;
410-
Log($"Assigned peer ID: {_localPeerId}");
411-
OnConnected?.Invoke(this, new NetworkEventArgs { PeerId = _localPeerId });
366+
SendMessage(new NetworkMessage
367+
{
368+
Type = MessageType.Connect,
369+
SenderId = _localPeerId,
370+
TargetId = peerId,
371+
Channel = 0,
372+
Timestamp = DateTime.UtcNow,
373+
Data = Serialize(packet)
374+
}, DeliveryMethod.ReliableOrdered);
412375
}
413376

414-
private void OnEntitySyncPacket(EntitySyncPacket packet, NetPeer peer)
377+
private byte[] Serialize<T>(T obj)
415378
{
416-
// Handle entity synchronization
379+
return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(obj));
417380
}
418381

419-
private void OnRPCPacket(RPCPacket packet, NetPeer peer)
382+
private T Deserialize<T>(byte[] data)
420383
{
421-
// Handle RPC calls
384+
var json = Encoding.UTF8.GetString(data);
385+
return JsonSerializer.Deserialize<T>(json)!;
422386
}
423387

424388
public void RegisterMessageHandler(MessageType type, Action<NetworkMessage> handler)
@@ -481,4 +445,4 @@ public class RPCPacket
481445
public string MethodName { get; set; } = string.Empty;
482446
public object[] Arguments { get; set; } = Array.Empty<object>();
483447
}
484-
}
448+
}

KitsuneEngine.Network/NetworkService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public NetworkService(World world, NetworkConfig? config = null)
2626

2727
public void StartServer(int port = 7777)
2828
{
29-
_networkManager.StartServer();
29+
_networkManager.StartServer(port);
3030
}
3131

3232
public void StartClient(string address = "127.0.0.1", int port = 7777)
@@ -57,4 +57,4 @@ public void Dispose()
5757
_networkManager?.Dispose();
5858
}
5959
}
60-
}
60+
}

KitsuneEngine.Network/NetworkSystem.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ protected override void Update(float deltaTime, Span<NetworkComponent> component
5252

5353
private void SyncEntity(NetworkComponent component)
5454
{
55-
if (!component.IsOwner || !_networkManager.IsConnected) return;
55+
SyncEntity(component, 0, requireOwnership: true);
56+
}
57+
58+
private void SyncEntity(NetworkComponent component, uint targetPeerId, bool requireOwnership)
59+
{
60+
if ((requireOwnership && !component.IsOwner) || !_networkManager.IsConnected) return;
5661

5762
// Create sync packet
5863
var packet = new EntitySyncPacket
@@ -79,7 +84,7 @@ private void SyncEntity(NetworkComponent component)
7984
{
8085
Type = MessageType.EntitySync,
8186
SenderId = _networkManager.LocalPeerId,
82-
TargetId = 0, // Broadcast
87+
TargetId = targetPeerId, // 0 = Broadcast
8388
Data = Serialize(packet),
8489
Timestamp = DateTime.Now
8590
};
@@ -203,7 +208,7 @@ private void SendInitialState(uint peerId)
203208
foreach (var entity in _world.GetEntities().With<NetworkComponent>().AsEnumerable())
204209
{
205210
var component = entity.Get<NetworkComponent>();
206-
SyncEntity(component);
211+
SyncEntity(component, peerId, requireOwnership: false);
207212
}
208213
}
209214

0 commit comments

Comments
 (0)