Add base class for Server/ClientSyncer, fix #3

This commit is contained in:
Sofia 2017-05-14 23:20:18 +03:00
parent 43059e57ca
commit 1a7e44b733
7 changed files with 151 additions and 133 deletions

View File

@ -1,46 +1,25 @@

using Cyber.Networking.Messages;
using UnityEngine;
namespace Cyber.Networking.Clientside {
/// <summary>
/// Syncer used on the clientside which sends sync packets from the client to the server containing their movement direction, rotation and possible checksums.
/// </summary>
public class ClientSyncer : MonoBehaviour {
public class ClientSyncer : Syncer {
private const int ChecksumInterval = 10; // Every 10 ticks -> 1 per second
public ClientSyncer() : base(1f / 10) {}
private const float TickInterval = 1 / 10f;
private float TimeSinceLastTick = TickInterval;
private int TickCounter = 0;
public override void PerformTick(int Tick) {
private int SyncIDCounter = 0;
ClientSyncPkt SyncPkt = new ClientSyncPkt();
private void Update() {
TimeSinceLastTick += Time.deltaTime;
if (TimeSinceLastTick >= TickInterval) {
var PlayerCharacter = Client.GetConnectedPlayer().Character;
SyncPkt.ClientSyncID = NextSyncID();
SyncPkt.MoveDirection = PlayerCharacter.GetMovementDirection();
SyncPkt.Rotation = PlayerCharacter.GetRotation();
ClientSyncPkt SyncPkt = new ClientSyncPkt();
if (TickCounter % ChecksumInterval == 0) {
// Add checksums
}
var PlayerCharacter = Client.GetConnectedPlayer().Character;
SyncPkt.ClientSyncID = SyncIDCounter++;
SyncPkt.MoveDirection = PlayerCharacter.GetMovementDirection();
SyncPkt.Rotation = PlayerCharacter.GetRotation();
Client.SendByChannel(PktType.ClientSync, SyncPkt, NetworkChannelID.Unreliable);
if (TickCounter < int.MaxValue) {
TickCounter += 1;
} else {
TickCounter = 0;
}
TimeSinceLastTick -= TickInterval;
}
Client.SendByChannel(PktType.ClientSync, SyncPkt, NetworkChannelID.Unreliable);
}
}

View File

@ -21,9 +21,9 @@ namespace Cyber.Networking.Serverside {
private Spawner Spawner;
/// <summary>
/// The Syncer which syncs. <see cref="Syncer"/>
/// The Syncer which syncs. <see cref="ServerSyncer"/>
/// </summary>
public Syncer Syncer;
public ServerSyncer Syncer;
private ServerSyncHandler ServerSyncHandler;
@ -167,7 +167,7 @@ namespace Cyber.Networking.Serverside {
Shutdown();
});
Syncer = gameObject.AddComponent<Syncer>();
Syncer = gameObject.AddComponent<ServerSyncer>();
ServerSyncHandler = new ServerSyncHandler(Players);

View File

@ -0,0 +1,83 @@

using Cyber.Entities;
using Cyber.Networking.Messages;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cyber.Networking.Serverside {
/// <summary>
/// Keeps stuff in-sync over at clients. Periodically collects stuff that needs to be synced and then sends them on the next 'tick.'
/// </summary>
public class ServerSyncer : Syncer {
private SyncDB Database;
private List<int> QueuedSyncs = new List<int>();
private List<int> DirtySyncBases = new List<int>();
public ServerSyncer() : base(1f / 10) {}
/// <summary>
/// Mark a SyncBase "Dirty", which makes it eligible to sync.
/// </summary>
/// <param name="syncBaseID">The ID of the SyncBase. See <see cref="SyncBase.ID"/></param>
public void DirtSyncBase(int syncBaseID) {
if (DirtySyncBases.Contains(syncBaseID)) {
return;
}
DirtySyncBases.Add(syncBaseID);
}
/// <summary>
///
/// </summary>
/// <param name="Tick"></param>
public override void PerformTick(int Tick) {
var Categorized = Database.GetCategorizedDatabase();
List<int> checksummedIds = new List<int>();
List<int> checksums = new List<int>();
foreach (Type type in Categorized.Keys) {
SyncHandletype Handletype = Database.GetSyncHandletypes()[type];
if (Tick % Handletype.TickInterval == 0) {
foreach (int SyncBaseID in Categorized[type]) {
bool Contains = DirtySyncBases.Contains(SyncBaseID);
if (Contains == Handletype.RequireHash || Contains) {
QueueSyncBase(SyncBaseID);
if (Contains) {
DirtySyncBases.Remove(SyncBaseID);
}
}
if (Handletype.RequireHash) {
checksummedIds.Add(SyncBaseID);
checksums.Add(Database.Get(SyncBaseID).GenerateChecksum());
}
}
}
}
if (QueuedSyncs.Count > 0) {
int[] SyncIDs = QueuedSyncs.ToArray();
SyncPkt SyncPacket = new SyncPkt(Database, SyncIDs, checksummedIds.ToArray(), checksums.ToArray(), NextSyncID());
Server.SendToAllByChannel(PktType.Sync, SyncPacket, NetworkChannelID.Unreliable);
QueuedSyncs.Clear();
}
}
/// <summary>
/// Queue a SyncBase directly, so it will be synced next time a sync tick is called.
/// </summary>
/// <param name="SyncBaseID">The ID of the SyncBase. See <see cref="SyncBase.ID"/></param>
public void QueueSyncBase(int SyncBaseID) {
QueuedSyncs.Add(SyncBaseID);
}
private void Start() {
Database = GetComponent<SyncDB>();
}
}
}

View File

@ -1,100 +0,0 @@

using Cyber.Console;
using Cyber.Entities;
using Cyber.Entities.SyncBases;
using Cyber.Networking.Messages;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cyber.Networking.Serverside {
/// <summary>
/// Keeps stuff in-sync over at clients. Periodically collects stuff that needs to be synced and then sends them on the next 'tick.'
/// </summary>
public class Syncer : MonoBehaviour {
private SyncDB Database;
private int TickCounter = 0;
private const float TickInterval = 1f / 10;
private float TimeSinceLastTick = TickInterval;
private List<int> QueuedSyncs = new List<int>();
private List<int> DirtySyncBases = new List<int>();
private int SyncPacketID = 0;
/// <summary>
/// Mark a SyncBase "Dirty", which makes it eligible to sync.
/// </summary>
/// <param name="syncBaseID">The ID of the SyncBase. See <see cref="SyncBase.ID"/></param>
public void DirtSyncBase(int syncBaseID) {
if (DirtySyncBases.Contains(syncBaseID)) {
return;
}
DirtySyncBases.Add(syncBaseID);
}
/// <summary>
/// Queue a SyncBase directly, so it will be synced next time a sync tick is called.
/// </summary>
/// <param name="SyncBaseID">The ID of the SyncBase. See <see cref="SyncBase.ID"/></param>
public void QueueSyncBase(int SyncBaseID) {
QueuedSyncs.Add(SyncBaseID);
}
private void Start() {
Database = GetComponent<SyncDB>();
}
private void Update() {
TimeSinceLastTick += Time.deltaTime;
if (TimeSinceLastTick >= TickInterval) {
var Categorized = Database.GetCategorizedDatabase();
List<int> checksummedIds = new List<int>();
List<int> checksums = new List<int>();
foreach (Type type in Categorized.Keys) {
SyncHandletype Handletype = Database.GetSyncHandletypes()[type];
if (TickCounter % Handletype.TickInterval == 0) {
foreach (int SyncBaseID in Categorized[type]) {
bool Contains = DirtySyncBases.Contains(SyncBaseID);
if (Contains == Handletype.RequireHash || Contains) {
QueueSyncBase(SyncBaseID);
if (Contains) {
DirtySyncBases.Remove(SyncBaseID);
}
}
if (Handletype.RequireHash) {
checksummedIds.Add(SyncBaseID);
checksums.Add(Database.Get(SyncBaseID).GenerateChecksum());
}
}
}
}
if (QueuedSyncs.Count > 0) {
int[] SyncIDs = QueuedSyncs.ToArray();
SyncPkt SyncPacket = new SyncPkt(Database, SyncIDs, checksummedIds.ToArray(), checksums.ToArray(), SyncPacketID++);
Server.SendToAllByChannel(PktType.Sync, SyncPacket, NetworkChannelID.Unreliable);
QueuedSyncs.Clear();
}
if (TickCounter < int.MaxValue) {
TickCounter++;
} else {
TickCounter = 0;
}
TimeSinceLastTick -= TickInterval;
}
}
}
}

View File

@ -0,0 +1,44 @@

using UnityEngine;
namespace Cyber.Networking {
public abstract class Syncer : MonoBehaviour {
private int TickCounter = 0;
private readonly float TickInterval;
private float TimeSinceLastTick = 0;
private int SyncPacketID = 0;
public Syncer(float tickInterval) {
TickInterval = tickInterval;
TimeSinceLastTick = tickInterval;
}
public int NextSyncID() {
return SyncPacketID++;
}
private void Update() {
TimeSinceLastTick += Time.deltaTime;
if (TimeSinceLastTick > TickInterval) {
PerformTick(TickCounter);
if (TickCounter < int.MaxValue) {
TickCounter++;
} else {
TickCounter = 0;
}
TimeSinceLastTick -= TickInterval;
}
}
public abstract void PerformTick(int Tick);
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b9778f182f90b2a4291e31b85f12803c
timeCreated: 1494793021
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: