initial commit
This commit is contained in:
54
Assets/Network/Client.cs
Normal file
54
Assets/Network/Client.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace FastArena
|
||||
{
|
||||
public static class Client
|
||||
{
|
||||
private static TcpClient _tcp;
|
||||
private static UdpClient _udp;
|
||||
|
||||
public static void SendUserAction()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public static void Connect(IPAddress ip, short portFirst)
|
||||
{
|
||||
_tcp = new TcpClient();
|
||||
_udp = new UdpClient();
|
||||
_tcp.BeginConnect(ip, portFirst, TCPConnectCallback, null);
|
||||
_udp.BeginSend(StructBinaryConverter.GetBytes(new ConnectionRequestUDP()))
|
||||
}
|
||||
|
||||
private static void TCPConnectCallback(IAsyncResult ar)
|
||||
{
|
||||
_tcp.EndConnect(ar);
|
||||
}
|
||||
|
||||
private static Dictionary<int, SyncTransform> _syncTransforms = new();
|
||||
|
||||
private static void CreateGameObject(int id, ref CreateObjectPacket packet)
|
||||
{
|
||||
var prefab = Resources.Load(packet.prefabPath, typeof(GameObject));
|
||||
var go = (GameObject)Object.Instantiate(prefab);
|
||||
var idComponent = go.AddComponent<GameObjectId>();
|
||||
idComponent._SetId(packet.gameObjectId);
|
||||
if (go.TryGetComponent(out SyncTransform syncTransform))
|
||||
{
|
||||
_syncTransforms.Add(packet.gameObjectId, syncTransform);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateObjectTransform(int id, ref TransformUpdatePacket packet)
|
||||
{
|
||||
if(!_syncTransforms.TryGetValue(id, out var component))
|
||||
return;
|
||||
component.UpdateTransform(ref packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Network/Client.cs.meta
Normal file
3
Assets/Network/Client.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c0ca1a557b3445bb080f944580f6393
|
||||
timeCreated: 1719762842
|
||||
3
Assets/Network/Packets.meta
Normal file
3
Assets/Network/Packets.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8390671da7da4562881b1dc29107131f
|
||||
timeCreated: 1752080612
|
||||
21
Assets/Network/Packets/ConnectionPackets.cs
Normal file
21
Assets/Network/Packets/ConnectionPackets.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FastArena
|
||||
{
|
||||
internal struct Hash256
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct ConnectionRequestTCP
|
||||
{
|
||||
internal readonly PacketHeader header;
|
||||
private SHA256 _sha256;
|
||||
|
||||
public ConnectionRequestTCP()
|
||||
{
|
||||
header = new PacketHeader(PacketType.ConnectionRequestTCP);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Network/Packets/ConnectionPackets.cs.meta
Normal file
3
Assets/Network/Packets/ConnectionPackets.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 973e6f96c4a74c8299406cfe25e29414
|
||||
timeCreated: 1752080764
|
||||
18
Assets/Network/Packets/CreateObjectPacket.cs
Normal file
18
Assets/Network/Packets/CreateObjectPacket.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FastArena;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct CreateObjectPacket
|
||||
{
|
||||
internal readonly PacketHeader header;
|
||||
internal readonly int gameObjectId;
|
||||
internal readonly string prefabPath;
|
||||
|
||||
internal CreateObjectPacket(int _gameObjectId, string _prefabPath)
|
||||
{
|
||||
header = new PacketHeader(PacketType.CreateObject);
|
||||
gameObjectId = _gameObjectId;
|
||||
prefabPath = _prefabPath;
|
||||
}
|
||||
}
|
||||
3
Assets/Network/Packets/CreateObjectPacket.cs.meta
Normal file
3
Assets/Network/Packets/CreateObjectPacket.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0bc94f4527d493d88a018b32d36ae4f
|
||||
timeCreated: 1752080638
|
||||
32
Assets/Network/Packets/PacketHeader.cs
Normal file
32
Assets/Network/Packets/PacketHeader.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FastArena
|
||||
{
|
||||
internal enum PacketType : ushort
|
||||
{
|
||||
Invalid = 0, // not packet
|
||||
|
||||
ConnectionRequestTCP,
|
||||
ConnectionRequestUDP,
|
||||
ConnectionResponseTCP,
|
||||
ConnectionResponseUDP,
|
||||
|
||||
TransformUpdate,
|
||||
CreateObject
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
internal readonly struct PacketHeader
|
||||
{
|
||||
internal const ushort MAGIC_CONST = 0x6313;
|
||||
|
||||
internal readonly ushort magic;
|
||||
internal readonly PacketType type;
|
||||
|
||||
internal PacketHeader(PacketType t)
|
||||
{
|
||||
magic = MAGIC_CONST;
|
||||
type = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Network/Packets/PacketHeader.cs.meta
Normal file
3
Assets/Network/Packets/PacketHeader.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5d47bd361a840ab95f8411ad0d2458a
|
||||
timeCreated: 1719857658
|
||||
15
Assets/Network/Packets/PacketParser.cs
Normal file
15
Assets/Network/Packets/PacketParser.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace FastArena;
|
||||
|
||||
internal static class PacketParser
|
||||
{
|
||||
internal static PacketType ReadHeader(byte[] data)
|
||||
{
|
||||
var h = StructBinaryConverter.ReadStruct<PacketHeader>(data);
|
||||
return h.magic == PacketHeader.MAGIC_CONST ? h.type : PacketType.Invalid;
|
||||
}
|
||||
|
||||
internal static T ReadPacket<T>(byte[] data) where T : unmanaged
|
||||
{
|
||||
return StructBinaryConverter.ReadStruct<T>(data);
|
||||
}
|
||||
}
|
||||
3
Assets/Network/Packets/PacketParser.cs.meta
Normal file
3
Assets/Network/Packets/PacketParser.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f0a0f3489a547308cf0e57b45bed6c6
|
||||
timeCreated: 1752080621
|
||||
21
Assets/Network/Packets/TransformUpdatePacket.cs
Normal file
21
Assets/Network/Packets/TransformUpdatePacket.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FastArena;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal readonly struct TransformUpdatePacket
|
||||
{
|
||||
internal readonly PacketHeader header;
|
||||
internal readonly int gameObjectId;
|
||||
internal readonly Vector3 position;
|
||||
internal readonly Quaternion rotation;
|
||||
|
||||
internal TransformUpdatePacket(int _gameObjectId, Transform transform)
|
||||
{
|
||||
header = new PacketHeader(PacketType.TransformUpdate);
|
||||
gameObjectId = _gameObjectId;
|
||||
position = transform.position;
|
||||
rotation = transform.rotation;
|
||||
}
|
||||
}
|
||||
3
Assets/Network/Packets/TransformUpdatePacket.cs.meta
Normal file
3
Assets/Network/Packets/TransformUpdatePacket.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b57b439f5bd74ca1a4fdbe3621fae51d
|
||||
timeCreated: 1752080633
|
||||
92
Assets/Network/Server.cs
Normal file
92
Assets/Network/Server.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FastArena
|
||||
{
|
||||
public class ServerConfig
|
||||
{
|
||||
public int PortFirst = 26782;
|
||||
public int MaxPlayers = 20;
|
||||
}
|
||||
|
||||
public static class Server
|
||||
{
|
||||
private static UdpClient _udp;
|
||||
private static TcpListener _tcp;
|
||||
|
||||
public class ClientConnection
|
||||
{
|
||||
// public int id { get; private set; }
|
||||
private TcpClient _tcp;
|
||||
|
||||
public ClientConnection(TcpClient tcp)
|
||||
{
|
||||
_tcp = tcp;
|
||||
}
|
||||
|
||||
public IPEndPoint GetEndPoint()
|
||||
{
|
||||
return (IPEndPoint)_tcp.Client.RemoteEndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ClientConnection> connections = new List<ClientConnection>();
|
||||
|
||||
public static void Start(ServerConfig config)
|
||||
{
|
||||
_tcp = new TcpListener(IPAddress.Any, config.PortFirst);
|
||||
_udp = new UdpClient(config.PortFirst + 1);
|
||||
_tcp.Start();
|
||||
_tcp.BeginAcceptTcpClient(TcpAcceptCallback, null);
|
||||
_udp.BeginReceive(UdpReceiveCallback, null);
|
||||
}
|
||||
|
||||
|
||||
private static void TcpAcceptCallback(IAsyncResult ar)
|
||||
{
|
||||
var tcpClient = _tcp.EndAcceptTcpClient(ar);
|
||||
var connection = new ClientConnection(tcpClient);
|
||||
connections.Add(connection);
|
||||
}
|
||||
|
||||
private static void UdpReceiveCallback(IAsyncResult ar)
|
||||
{
|
||||
IPEndPoint clientEndPoint = new IPEndPoint(IPAddress.None, 0);
|
||||
byte[] data = _udp.EndReceive(ar, ref clientEndPoint);
|
||||
// begin receiving new data immediately
|
||||
_udp.BeginReceive(UdpReceiveCallback, null);
|
||||
|
||||
PacketType t = PacketParser.ReadHeader(data);
|
||||
switch (t)
|
||||
{
|
||||
case PacketType.Invalid:
|
||||
break;
|
||||
default:
|
||||
Debug.Log($"received unexpected packet of type {t}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UdpSendTo(byte[] data, IPEndPoint cliendEnd)
|
||||
{
|
||||
_udp.BeginSend(data, data.Length, cliendEnd, null, null);
|
||||
}
|
||||
|
||||
private static void UdpSendTo(byte[] data, ClientConnection client)
|
||||
{
|
||||
UdpSendTo(data, client.GetEndPoint());
|
||||
}
|
||||
|
||||
public static void SendTransformUpdate(int id, Transform transform)
|
||||
{
|
||||
byte[] data = StructBinaryConverter.GetBytes(new TransformUpdatePacket(id, transform));
|
||||
foreach(var p in connections)
|
||||
{
|
||||
UdpSendTo(data, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Network/Server.cs.meta
Normal file
3
Assets/Network/Server.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e44812093d941899b0c6458f2218197
|
||||
timeCreated: 1719762837
|
||||
55
Assets/Network/StructBinaryConverter.cs
Normal file
55
Assets/Network/StructBinaryConverter.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FastArena
|
||||
{
|
||||
public static class StructBinaryConverter
|
||||
{
|
||||
public static byte[] GetBytes<T>(T s) where T : unmanaged
|
||||
{
|
||||
return GetBytes(ref s);
|
||||
}
|
||||
|
||||
public static byte[] GetBytes<T>(ref T s) where T : unmanaged
|
||||
{
|
||||
int size = Marshal.SizeOf(typeof(T));
|
||||
byte[] buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(Marshal.SizeOf<T>());
|
||||
|
||||
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (T* s_ptr = &s)
|
||||
{
|
||||
Marshal.Copy((IntPtr)s_ptr, buffer, 0, size);
|
||||
Marshal.StructureToPtr();
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
Marshal.StructureToPtr(msg_struct, handle.AddrOfPinnedObject(), false);
|
||||
return buffer;
|
||||
}
|
||||
finally
|
||||
{
|
||||
handle.Free();
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static T ReadStruct<T>(byte[] buffer) where T : unmanaged
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
T s = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
||||
return s;
|
||||
}
|
||||
finally
|
||||
{
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Network/StructBinaryConverter.cs.meta
Normal file
3
Assets/Network/StructBinaryConverter.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55c4eabd2994422da052a6dd70a1bdf4
|
||||
timeCreated: 1719866226
|
||||
43
Assets/Network/SyncTransform.cs
Normal file
43
Assets/Network/SyncTransform.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FastArena
|
||||
{
|
||||
public class GameObjectId : MonoBehaviour
|
||||
{
|
||||
public int Id { get; private set; } = -1;
|
||||
|
||||
internal void _SetId(int packetGameObjectId)
|
||||
{
|
||||
if (Id != -1)
|
||||
throw new Exception($"GameObjectId is already set to {Id}");
|
||||
Id = packetGameObjectId;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Component fetching GameObject's Transform from the server every tick.
|
||||
/// </summary>
|
||||
public class SyncTransform : MonoBehaviour
|
||||
{
|
||||
public GameObjectId IdRef { get; private set; }
|
||||
|
||||
private void Start()
|
||||
{
|
||||
IdRef = GetComponent<GameObjectId>();
|
||||
}
|
||||
|
||||
#if UNITY_SERVER
|
||||
private void FixedUpdate()
|
||||
{
|
||||
Server.SendTransformUpdate(IdRef.Id, transform);
|
||||
}
|
||||
#else
|
||||
internal void UpdateTransform(ref TransformUpdatePacket data)
|
||||
{
|
||||
transform.position = data.position;
|
||||
transform.rotation = data.rotation;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Assets/Network/SyncTransform.cs.meta
Normal file
11
Assets/Network/SyncTransform.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4a82b5feb6640b4f914a1743053b1e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user