You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

235 lines
6.3 KiB

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
public interface IBytable
{
byte[] Serialize();
void Deserialize(byte[] bytes);
}
public class RemoteDataPipelines
{
interface IPipeline
{
void OnRequest(TcpServerClient server, uint ownerUserID);
void OnRecv(byte[] bytes);
}
class Pipeline<T> : IPipeline where T : IBytable
{
Func<T> onRequest;
Action<T> onRecv;
public Pipeline(Func<T> onRequest, Action<T> onRecv)
{
this.onRequest = onRequest;
this.onRecv = onRecv;
}
public void OnRequest(TcpServerClient server, uint ownerUserID)
{
var instance = onRequest.Invoke();
byte[] bytes = instance.Serialize();
// TODO : Send bytes to server
ByteStream stream = new ByteStream();
//stream.Write(ownerUserID);
stream.Write(bytes);
var toBytes = stream.Bytes;
int dataSize = toBytes.Length;
Packet packet = new Packet();
//packet.header.code = HeaderCode.?;
packet.header.size = dataSize;
packet.body.data = toBytes;
server.Send(packet);
}
public void OnRecv(byte[] bytes)
{
var instance = Activator.CreateInstance<T>();
instance.Deserialize(bytes);
onRecv.Invoke(instance);
}
}
TcpServerClient client;
uint ownerUserID;
Dictionary<uint, IPipeline> pipeLines = new();
public event Action<uint, uint> OnRecvRequestEvent;
public RemoteDataPipelines(TcpServerClient client, uint ownerUserID)
{
this.client = client;
this.ownerUserID = ownerUserID;
}
public void AddPipeline<T>(uint eventID, Func<T> onRequest, Action<T> onRecv) where T : IBytable
{
if (!pipeLines.ContainsKey(eventID))
{
var recvEvent = new Pipeline<T>(onRequest, onRecv);
pipeLines.Add(eventID, recvEvent);
}
}
public void RemovePipeline(uint eventID)
{
pipeLines.Remove(eventID);
}
public void RequestEvent(uint eventID)
{
if (pipeLines.TryGetValue(eventID, out var pipeline))
{
pipeline.OnRequest(client, ownerUserID);
}
}
}
public class RemoteTrasnfrom : IBytable
{
Vector3 position;
Vector3 scale;
Vector3 rotation;
public Vector3 Position => position;
public Vector3 Scale => scale;
public Vector3 Rotation => rotation;
public byte[] Serialize()
{
byte[] bytes = new byte[sizeof(float) * 3 * 3];
BitConverter.GetBytes(position.x).CopyTo(bytes, 0);
BitConverter.GetBytes(position.y).CopyTo(bytes, sizeof(float));
BitConverter.GetBytes(position.z).CopyTo(bytes, sizeof(float) * 2);
BitConverter.GetBytes(scale.x).CopyTo(bytes, sizeof(float) * 3);
BitConverter.GetBytes(scale.y).CopyTo(bytes, sizeof(float) * 4);
BitConverter.GetBytes(scale.z).CopyTo(bytes, sizeof(float) * 5);
BitConverter.GetBytes(rotation.x).CopyTo(bytes, sizeof(float) * 6);
BitConverter.GetBytes(rotation.y).CopyTo(bytes, sizeof(float) * 7);
BitConverter.GetBytes(rotation.z).CopyTo(bytes, sizeof(float) * 8);
return bytes;
}
public void Deserialize(byte[] bytes)
{
position.x = BitConverter.ToSingle(bytes, 0);
position.y = BitConverter.ToSingle(bytes, sizeof(float));
position.z = BitConverter.ToSingle(bytes, sizeof(float) * 2);
scale.x = BitConverter.ToSingle(bytes, sizeof(float) * 3);
scale.y = BitConverter.ToSingle(bytes, sizeof(float) * 4);
scale.z = BitConverter.ToSingle(bytes, sizeof(float) * 5);
rotation.x = BitConverter.ToSingle(bytes, sizeof(float) * 6);
rotation.y = BitConverter.ToSingle(bytes, sizeof(float) * 7);
rotation.z = BitConverter.ToSingle(bytes, sizeof(float) * 8);
}
}
public class TestTcpClient : TcpServerClient
{
static Dictionary<HeaderCode, Type> remoteCommandTypeMap = new Dictionary<HeaderCode, Type>()
{
{ HeaderCode.JoinGame, typeof(UserJoinToServerPacket) },
};
protected override void OnDataReceived(in Packet packet)
{
if(TryCreateRemoteCommand(packet, out var command))
{
command.Execute();
}
}
private bool TryCreateRemoteCommand(in Packet packet, out RemoteCommand command)
{
command = null;
if (remoteCommandTypeMap.TryGetValue(packet.header.code, out var type))
{
command = Activator.CreateInstance(type) as RemoteCommand;
command.SetData(packet);
}
return command != null;
}
}
public abstract class RemoteCommand
{
public abstract void SetData(in Packet packet);
public abstract void Execute();
}
public class UserState
{
public int userID;
public Vector3 position;
public static int GetSize() => sizeof(int) + sizeof(float) * 3;
}
public class UserJoinToServerPacket : RemoteCommand
{
UserState userState;
public override void SetData(in Packet packet)
{
Debug.Assert(packet.header.code == HeaderCode.JoinGame, "Invalid packet code");
Debug.Assert(packet.header.size == UserState.GetSize(), "Invalid packet size");
userState = new UserState();
userState.userID = BitConverter.ToInt32(packet.body.data, 0);
userState.position.x = BitConverter.ToSingle(packet.body.data, sizeof(int));
}
public override void Execute()
{
GameObject user = new GameObject("User");
user.transform.position = userState.position;
Logger.Log("user " + userState.userID + " joined to server at " + userState.position.ToString());
}
}
public abstract class Monster : ICloneable
{
public abstract object Clone();
}
public class Orc : Monster
{
public override object Clone()
{
return new Orc();
}
}
public class Goblin : Monster
{
public override object Clone()
{
return new Goblin();
}
}
public class MonsterSpawner
{
Monster prototype;
public MonsterSpawner(Monster prototype)
{
this.prototype = prototype;
}
public Monster SpawnMonster()
{
return prototype.Clone() as Monster;
}
}