2017-05-09 16:15:21 +02:00
|
|
|
|
using System.Collections.Generic;
|
2017-05-08 23:03:02 +02:00
|
|
|
|
using System;
|
|
|
|
|
using UnityEngine;
|
2017-05-09 16:15:21 +02:00
|
|
|
|
using Cyber.Networking.Serverside;
|
2017-05-10 15:05:02 +02:00
|
|
|
|
using Cyber.Entities.SyncBases;
|
2017-05-11 18:58:33 +02:00
|
|
|
|
using Cyber.Console;
|
2017-05-08 23:03:02 +02:00
|
|
|
|
|
|
|
|
|
namespace Cyber.Entities {
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A database of the game's all syncable components. Syncable components are
|
|
|
|
|
/// the instances of the subclasses of <see cref="SyncBase"/>.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class SyncDB : MonoBehaviour {
|
|
|
|
|
|
|
|
|
|
private static readonly Type[] SyncableClasses = new Type[] {
|
2017-05-11 03:01:33 +02:00
|
|
|
|
typeof(Character),
|
2017-05-11 18:58:33 +02:00
|
|
|
|
typeof(Button),
|
|
|
|
|
typeof(Door),
|
|
|
|
|
typeof(Computer)
|
2017-05-08 23:03:02 +02:00
|
|
|
|
};
|
|
|
|
|
|
2017-05-09 05:13:30 +02:00
|
|
|
|
private int IDCounter = 0;
|
|
|
|
|
private Dictionary<int, SyncBase> Database = new Dictionary<int, SyncBase>();
|
2017-05-09 16:15:21 +02:00
|
|
|
|
private Dictionary<Type, List<int>> CategorizedDatabase = new Dictionary<Type, List<int>>();
|
|
|
|
|
private Dictionary<Type, SyncHandletype> SyncHandletypes = new Dictionary<Type, SyncHandletype>();
|
2017-05-08 23:03:02 +02:00
|
|
|
|
|
2017-05-11 03:01:33 +02:00
|
|
|
|
private List<int> StaticSyncBaseIDList = new List<int>();
|
|
|
|
|
|
2017-05-08 23:03:02 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Add an entity to the database with the given IDs.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="gameObject">Game object.</param>
|
|
|
|
|
/// <param name="ids">The IDs. Should be from <see cref="GetEntityIDs"/> or
|
|
|
|
|
/// <see cref="GetNewEntityIDs"/>, since the order is important.</param>
|
2017-05-09 05:13:30 +02:00
|
|
|
|
public void AddEntity(GameObject gameObject, int[] ids) {
|
2017-05-08 23:03:02 +02:00
|
|
|
|
int Index = 0;
|
|
|
|
|
for (int i = 0; i < SyncableClasses.Length; i++) {
|
|
|
|
|
SyncBase Syncable = (SyncBase)gameObject.GetComponent(SyncableClasses[i]);
|
|
|
|
|
if (Syncable != null) {
|
2017-05-11 03:01:33 +02:00
|
|
|
|
Syncable.ID = ids[Index++];
|
|
|
|
|
AddSyncBaseToDatabase(Syncable);
|
2017-05-08 23:03:02 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Makes an ordered list of the given gameobject's syncable components'
|
|
|
|
|
/// IDs.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The IDs.</returns>
|
|
|
|
|
/// <param name="gameObject">Game object.</param>
|
|
|
|
|
/// <param name="newIDs">Whether or not new IDs are created.
|
|
|
|
|
/// <see cref="GetNewEntityIDs"/> is a shorthand for this function with
|
|
|
|
|
/// this parameter set to true.</param>
|
2017-05-09 05:13:30 +02:00
|
|
|
|
public int[] GetEntityIDs(GameObject gameObject, bool newIDs = false) {
|
|
|
|
|
List<int> IDs = new List<int>();
|
2017-05-08 23:03:02 +02:00
|
|
|
|
for (int i = 0; i < SyncableClasses.Length; i++) {
|
|
|
|
|
SyncBase Syncable = (SyncBase)gameObject.GetComponent(SyncableClasses[i]);
|
|
|
|
|
if (Syncable != null) {
|
|
|
|
|
if (newIDs) {
|
|
|
|
|
Syncable.ID = CreateID();
|
|
|
|
|
}
|
|
|
|
|
IDs.Add(Syncable.ID);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-09 05:13:30 +02:00
|
|
|
|
int[] IDArray = new int[IDs.Count];
|
2017-05-08 23:03:02 +02:00
|
|
|
|
for (int i = 0; i < IDs.Count; i++) {
|
|
|
|
|
IDArray[i] = IDs[i];
|
|
|
|
|
}
|
|
|
|
|
return IDArray;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates an ordered list of the given gameobject's syncable components'
|
|
|
|
|
/// IDs. See <see cref="GetEntityIDs"/> for more information.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The new IDs.</returns>
|
|
|
|
|
/// <param name="gameObject">Game object.</param>
|
2017-05-09 05:13:30 +02:00
|
|
|
|
public int[] GetNewEntityIDs(GameObject gameObject) {
|
2017-05-08 23:03:02 +02:00
|
|
|
|
return GetEntityIDs(gameObject, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Get a synced component by its ID.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">The ID.</param>
|
2017-05-09 05:13:30 +02:00
|
|
|
|
public SyncBase Get(int id) {
|
2017-05-09 06:15:34 +02:00
|
|
|
|
if (!Database.ContainsKey(id)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2017-05-08 23:03:02 +02:00
|
|
|
|
return Database[id];
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-09 16:15:21 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gives the database categorized into lists of their types.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>A dictionary of categorized SyncBases.</returns>
|
|
|
|
|
public Dictionary<Type, List<int>> GetCategorizedDatabase() {
|
|
|
|
|
return CategorizedDatabase;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the Sync Handletypes currently known by the SyncDB.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The Sync Handletypes by Type.</returns>
|
|
|
|
|
public Dictionary<Type, SyncHandletype> GetSyncHandletypes() {
|
|
|
|
|
return SyncHandletypes;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-08 23:03:02 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates a new ID which isn't in use yet.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>A new, free ID.</returns>
|
2017-05-09 05:13:30 +02:00
|
|
|
|
public int CreateID() {
|
|
|
|
|
int ID;
|
2017-05-08 23:03:02 +02:00
|
|
|
|
try {
|
|
|
|
|
ID = IDCounter++;
|
|
|
|
|
} catch (OverflowException) {
|
|
|
|
|
ID = 0;
|
|
|
|
|
IDCounter = 1;
|
|
|
|
|
}
|
2017-05-09 05:13:30 +02:00
|
|
|
|
while (Database.ContainsKey(ID) && ID < int.MaxValue) {
|
2017-05-08 23:03:02 +02:00
|
|
|
|
ID++;
|
2017-05-09 05:13:30 +02:00
|
|
|
|
if (ID < int.MaxValue - 1)
|
2017-05-08 23:03:02 +02:00
|
|
|
|
IDCounter = ID + 1;
|
|
|
|
|
}
|
|
|
|
|
if (Database.ContainsKey(ID)) {
|
|
|
|
|
// Somehow we've managed to fill up the whole database.
|
|
|
|
|
// I can't even imagine why or how.
|
|
|
|
|
Debug.LogError("!!!WARNING!!! The SyncDB is full. Update the game to use longs instead of uints. !!!WARNING!!!");
|
|
|
|
|
}
|
|
|
|
|
return ID;
|
|
|
|
|
}
|
2017-05-11 03:01:33 +02:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sets static objects for all objects in the world. This method should be called once per game launch ever.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="idList">The list of id's to be set. If null, will create new ids.</param>
|
|
|
|
|
public void SetStaticObjectsIDs(int[] idList = null) {
|
2017-05-11 18:58:33 +02:00
|
|
|
|
SyncBase[] SyncBases = GameObject.Find("/StaticWorld").GetComponentsInChildren<SyncBase>();
|
2017-05-11 03:01:33 +02:00
|
|
|
|
Array.Sort(SyncBases, (a, b) => {
|
|
|
|
|
Vector3 APos = a.gameObject.transform.position;
|
2017-05-11 18:58:33 +02:00
|
|
|
|
float AComparison = APos.x * 677 + APos.y * 881 + APos.z * 313 + Array.IndexOf(SyncableClasses, a) * 463;
|
2017-05-11 03:01:33 +02:00
|
|
|
|
Vector3 BPos = b.gameObject.transform.position;
|
2017-05-11 18:58:33 +02:00
|
|
|
|
float BComparison = BPos.x * 677 + BPos.y * 881 + BPos.z * 313 + Array.IndexOf(SyncableClasses, b) * 463;
|
2017-05-11 03:01:33 +02:00
|
|
|
|
|
|
|
|
|
return AComparison.CompareTo(BComparison);
|
|
|
|
|
});
|
|
|
|
|
if (idList == null) {
|
|
|
|
|
foreach (SyncBase SyncBase in SyncBases) {
|
|
|
|
|
SyncBase.ID = CreateID();
|
|
|
|
|
AddSyncBaseToDatabase(SyncBase);
|
|
|
|
|
StaticSyncBaseIDList.Add(SyncBase.ID);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < Math.Min(SyncBases.Length, idList.Length); i++) {
|
|
|
|
|
SyncBases[i].ID = idList[i];
|
|
|
|
|
AddSyncBaseToDatabase(SyncBases[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-11 05:13:02 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the list of id's on the static objects that exist on the world by default.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
2017-05-11 03:01:33 +02:00
|
|
|
|
public int[] GetStaticSyncBaseIDList() {
|
|
|
|
|
return StaticSyncBaseIDList.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddSyncBaseToDatabase(SyncBase syncBase) {
|
|
|
|
|
Database[syncBase.ID] = syncBase;
|
|
|
|
|
if (Server.IsRunning()) {
|
|
|
|
|
Type Type = syncBase.GetType();
|
|
|
|
|
if (!CategorizedDatabase.ContainsKey(Type)) {
|
|
|
|
|
CategorizedDatabase.Add(Type, new List<int>());
|
|
|
|
|
SyncHandletypes.Add(Type, syncBase.GetSyncHandletype());
|
|
|
|
|
}
|
|
|
|
|
CategorizedDatabase[Type].Add(syncBase.ID);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-08 23:03:02 +02:00
|
|
|
|
}
|
|
|
|
|
}
|