diff --git a/Assets/Scripts/Entities/Spawner.cs b/Assets/Scripts/Entities/Spawner.cs
index 54b8824..271fd9b 100644
--- a/Assets/Scripts/Entities/Spawner.cs
+++ b/Assets/Scripts/Entities/Spawner.cs
@@ -34,7 +34,7 @@ namespace Cyber.Entities {
/// set if they exist already (eg. the server has sent them over). These
/// ids should be from . To create new
/// ids, leave as the default (null).
- public GameObject Spawn(EntityType type, Vector3 position, uint[] ids = null) {
+ public GameObject Spawn(EntityType type, Vector3 position, int[] ids = null) {
GameObject Spawned = null;
switch (type) {
case EntityType.PC:
@@ -55,7 +55,6 @@ namespace Cyber.Entities {
}
private void Start() {
- Spawn(EntityType.PC, new Vector3());
}
private void Update() {
diff --git a/Assets/Scripts/Entities/SyncBase.cs b/Assets/Scripts/Entities/SyncBase.cs
index b541091..9b0bc5d 100644
--- a/Assets/Scripts/Entities/SyncBase.cs
+++ b/Assets/Scripts/Entities/SyncBase.cs
@@ -14,6 +14,6 @@ namespace Cyber.Entities {
/// The ID this syncable component can be found with from its parent
/// .
///
- public uint ID;
+ public int ID;
}
}
\ No newline at end of file
diff --git a/Assets/Scripts/Entities/SyncDB.cs b/Assets/Scripts/Entities/SyncDB.cs
index 9685026..5fc2d7e 100644
--- a/Assets/Scripts/Entities/SyncDB.cs
+++ b/Assets/Scripts/Entities/SyncDB.cs
@@ -15,8 +15,8 @@ namespace Cyber.Entities {
typeof(Character)
};
- private uint IDCounter = 0;
- private Dictionary Database = new Dictionary();
+ private int IDCounter = 0;
+ private Dictionary Database = new Dictionary();
///
/// Add an entity to the database with the given IDs.
@@ -24,7 +24,7 @@ namespace Cyber.Entities {
/// Game object.
/// The IDs. Should be from or
/// , since the order is important.
- public void AddEntity(GameObject gameObject, uint[] ids) {
+ public void AddEntity(GameObject gameObject, int[] ids) {
int Index = 0;
for (int i = 0; i < SyncableClasses.Length; i++) {
SyncBase Syncable = (SyncBase)gameObject.GetComponent(SyncableClasses[i]);
@@ -44,8 +44,8 @@ namespace Cyber.Entities {
/// Whether or not new IDs are created.
/// is a shorthand for this function with
/// this parameter set to true.
- public uint[] GetEntityIDs(GameObject gameObject, bool newIDs = false) {
- List IDs = new List();
+ public int[] GetEntityIDs(GameObject gameObject, bool newIDs = false) {
+ List IDs = new List();
for (int i = 0; i < SyncableClasses.Length; i++) {
SyncBase Syncable = (SyncBase)gameObject.GetComponent(SyncableClasses[i]);
if (Syncable != null) {
@@ -55,7 +55,7 @@ namespace Cyber.Entities {
IDs.Add(Syncable.ID);
}
}
- uint[] IDArray = new uint[IDs.Count];
+ int[] IDArray = new int[IDs.Count];
for (int i = 0; i < IDs.Count; i++) {
IDArray[i] = IDs[i];
}
@@ -68,7 +68,7 @@ namespace Cyber.Entities {
///
/// The new IDs.
/// Game object.
- public uint[] GetNewEntityIDs(GameObject gameObject) {
+ public int[] GetNewEntityIDs(GameObject gameObject) {
return GetEntityIDs(gameObject, true);
}
@@ -76,7 +76,7 @@ namespace Cyber.Entities {
/// Get a synced component by its ID.
///
/// The ID.
- public SyncBase Get(uint id) {
+ public SyncBase Get(int id) {
return Database[id];
}
@@ -84,17 +84,17 @@ namespace Cyber.Entities {
/// Creates a new ID which isn't in use yet.
///
/// A new, free ID.
- public uint CreateID() {
- uint ID;
+ public int CreateID() {
+ int ID;
try {
ID = IDCounter++;
} catch (OverflowException) {
ID = 0;
IDCounter = 1;
}
- while (Database.ContainsKey(ID) && ID < uint.MaxValue) {
+ while (Database.ContainsKey(ID) && ID < int.MaxValue) {
ID++;
- if (ID < uint.MaxValue - 1)
+ if (ID < int.MaxValue - 1)
IDCounter = ID + 1;
}
if (Database.ContainsKey(ID)) {
diff --git a/Assets/Scripts/Networking/Clientside/Client.cs b/Assets/Scripts/Networking/Clientside/Client.cs
index 954ed80..ef2af51 100644
--- a/Assets/Scripts/Networking/Clientside/Client.cs
+++ b/Assets/Scripts/Networking/Clientside/Client.cs
@@ -1,4 +1,5 @@
using Cyber.Console;
+using Cyber.Entities;
using Cyber.Networking.Messages;
using System.Collections.Generic;
using UnityEngine;
@@ -24,11 +25,13 @@ namespace Cyber.Networking.Clientside {
private static Client Singleton;
+ private Spawner Spawner;
+
///
/// The player of this client
///
private CConnectedPlayer Player;
- private List Players = new List();
+ private Dictionary Players = new Dictionary();
///
/// Creates the client and sets it as the signleton.
@@ -86,6 +89,11 @@ namespace Cyber.Networking.Clientside {
return Singleton.NetClient.isConnected;
}
+
+ private void Start() {
+ Spawner = GetComponent();
+ }
+
private bool LaunchClient(string ip, int port) {
if (Running) {
return false;
@@ -104,6 +112,7 @@ namespace Cyber.Networking.Clientside {
NetClient.RegisterHandler(PktType.TextMessage, HandlePacket);
NetClient.RegisterHandler(PktType.Identity, HandlePacket);
NetClient.RegisterHandler(PktType.MassIdentity, HandlePacket);
+ NetClient.RegisterHandler(PktType.SpawnEntity, HandlePacket);
NetClient.RegisterHandler(MsgType.Connect, OnConnected);
NetClient.RegisterHandler(MsgType.Disconnect, OnDisconnected);
@@ -134,15 +143,27 @@ namespace Cyber.Networking.Clientside {
Debug.Log(Conn.ConnectionID + " connected!");
Term.Println(Conn.ConnectionID + " connected!");
}
- Players.Add(Conn);
+ Players.Add(Conn.ConnectionID, Conn);
break;
case (PktType.MassIdentity):
MassIdentityPkt Identities = new MassIdentityPkt();
Identities.Deserialize(msg.reader);
foreach (int currId in Identities.IdList) {
- Players.Add(new CConnectedPlayer(currId));
+ Players.Add(currId, new CConnectedPlayer(currId));
}
break;
+ case (PktType.SpawnEntity):
+ SpawnEntityPkt SpawnPkt = new SpawnEntityPkt();
+ SpawnPkt.Deserialize(msg.reader);
+
+ EntityType EntityType = SpawnPkt.EntityType;
+ // Check if you are the owner and if they are spawning an NPC
+ if (SpawnPkt.OwnerID == Player.ConnectionID && EntityType == EntityType.NPC) {
+ // Change it into a PC instead.
+ EntityType = EntityType.PC;
+ }
+ Spawner.Spawn(EntityType, SpawnPkt.Position, SpawnPkt.SyncBaseIDList);
+ break;
default:
Debug.LogError("Received an unknown packet, id: " + msg.msgType);
Term.Println("Received an unknown packet, id: " + msg.msgType);
diff --git a/Assets/Scripts/Networking/Messages/MassIdentityPkt.cs b/Assets/Scripts/Networking/Messages/MassIdentityPkt.cs
index ceb7e83..e9a4940 100644
--- a/Assets/Scripts/Networking/Messages/MassIdentityPkt.cs
+++ b/Assets/Scripts/Networking/Messages/MassIdentityPkt.cs
@@ -8,16 +8,30 @@ namespace Cyber.Networking.Messages {
///
public class MassIdentityPkt : MessageBase {
+ ///
+ /// List of Connection ID's to send
+ ///
public int[] IdList;
+ ///
+ /// Create a Mass Identity packet used to send a list of currently online connections.
+ ///
+ ///
public MassIdentityPkt(int[] idList) {
IdList = idList;
}
+ ///
+ /// Parameter-less constructor using when deserializing the message.
+ ///
public MassIdentityPkt() {
}
+ ///
+ /// Used to deserialize a message received via networking.
+ ///
+ ///
public override void Deserialize(NetworkReader reader) {
byte[][] ByteArray = new byte[4][];
ByteArray[0] = reader.ReadBytesAndSize();
@@ -27,6 +41,10 @@ namespace Cyber.Networking.Messages {
IdList = NetworkHelper.DeserializeIntArray(ByteArray);
}
+ ///
+ /// Used to serialize the message before it is sent.
+ ///
+ ///
public override void Serialize(NetworkWriter writer) {
byte[][] ByteArray = NetworkHelper.SerializeIntArray(IdList);
writer.WriteBytesFull(ByteArray[0]);
diff --git a/Assets/Scripts/Networking/Messages/SpawnEntityPkt.cs b/Assets/Scripts/Networking/Messages/SpawnEntityPkt.cs
new file mode 100644
index 0000000..fee555d
--- /dev/null
+++ b/Assets/Scripts/Networking/Messages/SpawnEntityPkt.cs
@@ -0,0 +1,86 @@
+
+using Cyber.Entities;
+using UnityEngine;
+using UnityEngine.Networking;
+
+namespace Cyber.Networking.Messages {
+
+ ///
+ /// Packet which tells the client to spawn an entity corresponding to the data inside.
+ ///
+ public class SpawnEntityPkt : MessageBase {
+
+ ///
+ /// The type of entity to spawn.
+ ///
+ public EntityType EntityType;
+ ///
+ /// The position of the entity, where it should be spawned
+ ///
+ public Vector3 Position;
+ ///
+ /// The List of Sync ID's for the entity.
+ ///
+ public int[] SyncBaseIDList;
+
+ ///
+ /// Connection ID of the owner of this entity
+ ///
+ public int OwnerID;
+
+ ///
+ /// Create a packet of information about spawning an entity to send the clients.
+ ///
+ /// Type of entity to spawn.
+ /// Position where the entity will be spawned.
+ /// List of Sync ID's for the entity.
+ /// The Connection ID who owns this entity (or -1).
+ public SpawnEntityPkt(EntityType entityType, Vector3 position, int[] syncIDList, int ownerID) {
+ EntityType = entityType;
+ Position = position;
+ SyncBaseIDList = syncIDList;
+ OwnerID = ownerID;
+ }
+
+ ///
+ /// Parameter-less constructor using when deserializing the message.
+ ///
+ public SpawnEntityPkt() {
+
+ }
+
+ ///
+ /// Used to deserialize a message received via networking.
+ ///
+ ///
+ public override void Deserialize(NetworkReader reader) {
+ EntityType = (EntityType) reader.ReadInt16();
+ Position = reader.ReadVector3();
+ OwnerID = reader.ReadInt32();
+
+ byte[][] ByteArray = new byte[4][];
+ ByteArray[0] = reader.ReadBytesAndSize();
+ ByteArray[1] = reader.ReadBytesAndSize();
+ ByteArray[2] = reader.ReadBytesAndSize();
+ ByteArray[3] = reader.ReadBytesAndSize();
+ SyncBaseIDList = NetworkHelper.DeserializeIntArray(ByteArray);
+ }
+
+ ///
+ /// Used to serialize the message before it is sent.
+ ///
+ ///
+ public override void Serialize(NetworkWriter writer) {
+ writer.Write((short) EntityType);
+ writer.Write(Position);
+ writer.Write(OwnerID);
+
+ byte[][] ByteArray = NetworkHelper.SerializeIntArray(SyncBaseIDList);
+ writer.WriteBytesFull(ByteArray[0]);
+ writer.WriteBytesFull(ByteArray[1]);
+ writer.WriteBytesFull(ByteArray[2]);
+ writer.WriteBytesFull(ByteArray[3]);
+ }
+
+ }
+}
diff --git a/Assets/Scripts/Networking/Messages/SpawnEntityPkt.cs.meta b/Assets/Scripts/Networking/Messages/SpawnEntityPkt.cs.meta
new file mode 100644
index 0000000..68cd034
--- /dev/null
+++ b/Assets/Scripts/Networking/Messages/SpawnEntityPkt.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: bcdedfecd6ba4a04397852ba038f0939
+timeCreated: 1494296640
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Networking/PktType.cs b/Assets/Scripts/Networking/PktType.cs
index aece22c..1c897f8 100644
--- a/Assets/Scripts/Networking/PktType.cs
+++ b/Assets/Scripts/Networking/PktType.cs
@@ -20,5 +20,10 @@ namespace Cyber.Networking {
/// Packet containing the identification details about everyone on the server before the client connected.
///
public const short MassIdentity = 202;
+
+ ///
+ /// Packet containing necessary information about spawning an entity.
+ ///
+ public const short SpawnEntity = 203;
}
}
\ No newline at end of file
diff --git a/Assets/Scripts/Networking/Serverside/Server.cs b/Assets/Scripts/Networking/Serverside/Server.cs
index 4bfd73e..582e66a 100644
--- a/Assets/Scripts/Networking/Serverside/Server.cs
+++ b/Assets/Scripts/Networking/Serverside/Server.cs
@@ -11,9 +11,10 @@ namespace Cyber.Networking.Serverside {
/// Server-class used to host a server and communicate to clients.
///
/// \todo Change connection channels to Unreliable to optimize ping.
+ /// \todo Remove PC/NPC and make a Human-type entity instead.
public class Server : MonoBehaviour {
- private List Players = new List();
+ private Dictionary Players = new Dictionary();
private static Server Singleton;
private Spawner Spawner;
@@ -130,28 +131,51 @@ namespace Cyber.Networking.Serverside {
// Internal built-in event handler
- private void OnConnected(NetworkMessage msg) {
+ private void OnConnected(NetworkMessage msg) {
+ // Get client's ID
int Id = msg.conn.connectionId;
Debug.Log(Id + " connected!");
Term.Println(Id + " connected!");
+ // Send all other clients a notification and collect their id's
int[] IdList = new int[Players.Count];
- for (int i = 0; i < Players.Count; i++) {
- SConnectedPlayer P = Players[i];
- IdList[i] = P.ConnectionID;
+ int TempCounter = 0;
+ foreach (SConnectedPlayer P in Players.Values) {
+ IdList[TempCounter++] = P.ConnectionID;
NetworkServer.SendToClient(P.ConnectionID, PktType.Identity, new IdentityPkt(Id, false));
}
- foreach (int id in IdList) {
- Debug.Log("id: " + id);
- }
+
+ // Then send the client a list of all other clients
NetworkServer.SendToClient(Id, PktType.MassIdentity, new MassIdentityPkt(IdList));
+ // Add the player to the list
SConnectedPlayer Player = new SConnectedPlayer(msg.conn.connectionId);
- Players.Add(Player);
+ Players.Add(Id, Player);
+ // Send the previously collected list to the player
NetworkServer.SendToClient(msg.conn.connectionId,
PktType.Identity, new IdentityPkt(msg.conn.connectionId, true));
+
+ // Spawn the player and collet it's IDs
+ Vector3 Position = new Vector3(0, 0, 0);
+ GameObject Obj = Spawner.Spawn(EntityType.NPC, Position);
+ int[] EntityIdList = Spawner.SyncDB.GetEntityIDs(Obj);
+ Player.Character = Obj.GetComponent();
+
+ NetworkServer.SendToAll(PktType.SpawnEntity, new SpawnEntityPkt(EntityType.NPC, Position, EntityIdList, Id));
+
+ // Send every entity to the player who just connected.
+ foreach (var Entry in Players) {
+ if (Entry.Key == Id) {
+ continue;
+ }
+ Character Char = Players[Entry.Key].Character;
+ GameObject CurrObj = Char.gameObject;
+ int[] CurrEntityIdList = Spawner.SyncDB.GetNewEntityIDs(CurrObj);
+ NetworkServer.SendToClient(Id, PktType.SpawnEntity,
+ new SpawnEntityPkt(EntityType.NPC, CurrObj.transform.position, CurrEntityIdList, Entry.Key));
+ }
}
private void OnDisconnected(NetworkMessage msg) {
diff --git a/ROADMAP.md b/ROADMAP.md
index f62d9d9..e8b2101 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -47,5 +47,5 @@ Version 0.1.0 - Gigantic
- [x] ...With movement capabilities.
- [ ] Client-server connectivity, players can see each other moving around.
- [x] 1. Client-server connectivity: the clients can connect to the server and send some messages back and forth.
- - [ ] 2. Players can see eachothers capsule-characters and send commands to move them around.
+ - [x] 2. Players can see eachothers capsule-characters and send commands to move them around.
- [ ] 3. Basic syncing (Send sync packages at certain intervals) in order to sync positions correctly between server and client.