This commit is contained in:
Sofia 2017-05-09 00:14:30 +03:00
commit 7134c406f3
26 changed files with 555 additions and 487 deletions

View File

@ -1,49 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// A syncable component that all characters have. Controls the character's subsystems.
/// </summary>
public class Character : SyncBase {
/// <summary>
/// How fast the player should move in Unity's spatial units per second.
/// </summary>
public float MovementSpeed = 5.0f;
/// <summary>
/// The character controller, used to move the character. Handles collisions.
/// </summary>
public CharacterController CharacterController;
private Vector3 MovementDirection = new Vector3();
/// <summary>
/// Moves the character in the given direction.
/// </summary>
/// <param name="Direction">Movement direction.</param>
public void Move(Vector3 Direction) {
if (!Direction.Equals(MovementDirection)) {
MovementDirection = Direction.normalized;
}
}
/// <summary>
/// Stops the player from moving.
/// </summary>
public void Stop() {
if (Moving()) {
MovementDirection = new Vector3();
}
}
/// <summary>
/// Whether the player is moving or not.
/// </summary>
public bool Moving() {
return MovementDirection.sqrMagnitude != 0;
}
private void FixedUpdate() {
CharacterController.Move(MovementDirection * MovementSpeed * Time.fixedDeltaTime);
}
}

View File

@ -4,151 +4,158 @@ using System.Text.RegularExpressions;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
/// <summary> namespace Cyber.Console {
/// Controls an input and an output to implement a console interface to call
/// arbitrary commands which can be set from anywhere in the program through /// <summary>
/// <see cref="Term"/>. /// Controls an input and an output to implement a console interface to call
/// </summary> /// arbitrary commands which can be set from anywhere in the program through
public class DebugConsole : MonoBehaviour { /// <see cref="Term"/>.
private static readonly Regex CommandPartRegex = new Regex("([^ \"]+ )|(\"[^\"]+\")"); /// </summary>
public class DebugConsole : MonoBehaviour {
private static readonly Regex CommandPartRegex = new Regex("([^ \"]+ )|(\"[^\"]+\")");
/// <summary> /// <summary>
/// The parent of the <see cref="InputField"/> and <see cref="TextField"/>. /// The parent of the <see cref="InputField"/> and <see cref="TextField"/>.
/// </summary> /// </summary>
public GameObject Panel; public GameObject Panel;
/// <summary>
/// The input for the console.
/// </summary>
public InputField InputField;
/// <summary>
/// The output for the console.
/// </summary>
public Text TextField;
/// <summary>
/// Controls the visibility of the console. For how this is controlled in-game, see <see cref="Update"/>.
/// </summary>
public bool Visible = false;
private Dictionary<string, DebugConsoleAction> Actions = new Dictionary<string, DebugConsoleAction>(); /// <summary>
/// The input for the console.
/// </summary>
public InputField InputField;
/// <summary> /// <summary>
/// Creates a new <see cref="DebugConsole"/>, and sets the <see cref="Term"/>'s singleton. /// The output for the console.
/// <seealso cref="Term.SetDebugConsole"/> /// </summary>
/// </summary> public Text TextField;
public DebugConsole() {
Term.SetDebugConsole(this);
}
/// <summary> /// <summary>
/// Tries to call the command in the <see cref="InputField"/>. /// Controls the visibility of the console. For how this is controlled in-game, see <see cref="Update"/>.
/// </summary> /// </summary>
public void CallCommand() { public bool Visible = false;
if (InputField.text.Length == 0) {
return; private Dictionary<string, DebugConsoleAction> Actions = new Dictionary<string, DebugConsoleAction>();
/// <summary>
/// Creates a new <see cref="DebugConsole"/>, and sets the <see cref="Term"/>'s singleton.
/// <seealso cref="Term.SetDebugConsole"/>
/// </summary>
public DebugConsole() {
Term.SetDebugConsole(this);
} }
Println(InputField.text);
List<string> Arguments = new List<string>(); /// <summary>
MatchCollection Matches = CommandPartRegex.Matches(InputField.text + " "); /// Tries to call the command in the <see cref="InputField"/>.
for (int i = 0; i < Matches.Count; i++) { /// </summary>
Arguments.Add(Matches[i].Value.Replace('"', ' ').Trim()); public void CallCommand() {
} if (InputField.text.Length == 0) {
foreach (string Action in Actions.Keys) { return;
string[] Parts = Action.Split(' ');
if (Arguments.Count == Parts.Length && Arguments[0].Equals(Parts[0])) {
Arguments.RemoveAt(0);
Actions[Action].Call(Arguments);
break;
} }
} Println(InputField.text);
InputField.text = ""; List<string> Arguments = new List<string>();
InputField.ActivateInputField(); MatchCollection Matches = CommandPartRegex.Matches(InputField.text + " ");
} for (int i = 0; i < Matches.Count; i++) {
Arguments.Add(Matches[i].Value.Replace('"', ' ').Trim());
/// <summary>
/// Adds a command to be used in the console.
/// </summary>
/// <param name="command">The command template that should be used.
/// eg. "print (text)" or "add (number) (number)".</param>
/// <param name="description">Description.</param>
/// <param name="action">Action.</param>
public void AddCommand(string command, string description, DebugConsoleAction.Action action) {
string PrettyDescription = command;
foreach (string Line in description.Split('\n')) {
PrettyDescription += "\n " + Line;
}
Actions[command] = new DebugConsoleAction(PrettyDescription, action);
}
/// <summary>
/// Prints text into the DebugConsole and adds a newline.
/// </summary>
/// <param name="text">Text.</param>
public void Println(string text) {
Print(text + "\n");
}
// TODO: Handle removing history when it gets very long. Very long console logs might cause problems when displaying new prints.
/// <summary>
/// Prints text into the Console.
/// </summary>
/// <param name="text">Text.</param>
public void Print(string text) {
TextField.text += text;
}
private void Start() {
AddCommand("help", "Lists all commands.", (args) => {
Println("Commands:");
foreach (string Action in Actions.Keys) {
Println("- " + Action);
} }
});
AddCommand("help (command)", "Describes the given command.", (args) => {
// Check complete versions of the names (so you can do eg. help "help (command)")
foreach (string Action in Actions.Keys) {
if (Action.Equals(args[0])) {
Println(Actions[Action].Description);
return;
}
}
// Check just names
foreach (string Action in Actions.Keys) { foreach (string Action in Actions.Keys) {
string[] Parts = Action.Split(' '); string[] Parts = Action.Split(' ');
if (Parts[0].Equals(args[0])) { if (Arguments.Count == Parts.Length && Arguments[0].Equals(Parts[0])) {
Println(Actions[Action].Description); Arguments.RemoveAt(0);
return; Actions[Action].Call(Arguments);
break;
} }
} }
Println("That command doesn't exist."); InputField.text = "";
}); InputField.ActivateInputField();
AddCommand("print (text)", "Prints the given text.", (args) => {
Println(args[0]);
});
}
private void Update() {
if (Input.GetButtonDown("Console Toggle")) {
Visible = !Visible;
} }
RectTransform Rect = Panel.GetComponent<RectTransform>();
Vector2 OffsetMin = Rect.offsetMin; /// <summary>
if (Visible) { /// Adds a command to be used in the console.
if (OffsetMin.y > 1) { /// </summary>
OffsetMin.y = Mathf.Lerp(OffsetMin.y, 0, 5f * Time.deltaTime); /// <param name="command">The command template that should be used.
} /// eg. "print (text)" or "add (number) (number)".</param>
if (!InputField.isFocused) { /// <param name="description">Description.</param>
InputField.ActivateInputField(); /// <param name="action">Action.</param>
} public void AddCommand(string command, string description, DebugConsoleAction.Action action) {
} else { string PrettyDescription = command;
if (1000 - OffsetMin.y > 1) { foreach (string Line in description.Split('\n')) {
OffsetMin.y = Mathf.Lerp(OffsetMin.y, 1000, 1f * Time.deltaTime); PrettyDescription += "\n " + Line;
}
if (InputField.isFocused) {
InputField.DeactivateInputField();
} }
Actions[command] = new DebugConsoleAction(PrettyDescription, action);
}
/// <summary>
/// Prints text into the DebugConsole and adds a newline.
/// </summary>
/// <param name="text">Text.</param>
public void Println(string text) {
Print(text + "\n");
}
// TODO: Handle removing history when it gets very long. Very long console logs might cause problems when displaying new prints.
/// <summary>
/// Prints text into the Console.
/// </summary>
/// <param name="text">Text.</param>
public void Print(string text) {
TextField.text += text;
}
private void Start() {
AddCommand("help", "Lists all commands.", (args) => {
Println("Commands:");
foreach (string Action in Actions.Keys) {
Println("- " + Action);
}
});
AddCommand("help (command)", "Describes the given command.", (args) => {
// Check complete versions of the names (so you can do eg. help "help (command)")
foreach (string Action in Actions.Keys) {
if (Action.Equals(args[0])) {
Println(Actions[Action].Description);
return;
}
}
// Check just names
foreach (string Action in Actions.Keys) {
string[] Parts = Action.Split(' ');
if (Parts[0].Equals(args[0])) {
Println(Actions[Action].Description);
return;
}
}
Println("That command doesn't exist.");
});
AddCommand("print (text)", "Prints the given text.", (args) => {
Println(args[0]);
});
}
private void Update() {
if (Input.GetButtonDown("Console Toggle")) {
Visible = !Visible;
}
RectTransform Rect = Panel.GetComponent<RectTransform>();
Vector2 OffsetMin = Rect.offsetMin;
if (Visible) {
if (OffsetMin.y > 1) {
OffsetMin.y = Mathf.Lerp(OffsetMin.y, 0, 5f * Time.deltaTime);
}
if (!InputField.isFocused) {
InputField.ActivateInputField();
}
} else {
if (1000 - OffsetMin.y > 1) {
OffsetMin.y = Mathf.Lerp(OffsetMin.y, 1000, 1f * Time.deltaTime);
}
if (InputField.isFocused) {
InputField.DeactivateInputField();
}
}
Rect.offsetMin = OffsetMin;
} }
Rect.offsetMin = OffsetMin;
} }
} }

View File

@ -1,36 +1,41 @@
using System.Collections.Generic; using System.Collections.Generic;
/// <summary> namespace Cyber.Console {
/// Class that defines an action that commands in the
/// <see cref="DebugConsole"/> might use.
/// </summary>
public class DebugConsoleAction {
/// <summary> /// <summary>
/// A delegate for all of the actions that commands do. /// Class that defines an action that commands in the
/// <see cref="DebugConsole"/> might use.
/// </summary> /// </summary>
public delegate void Action(List<string> command); public class DebugConsoleAction {
/// <summary>
/// A description that will be shown when using the "help (command)" command in the console. /// <summary>
/// </summary> /// A delegate for all of the actions that commands do.
public readonly string Description; /// </summary>
public delegate void Action(List<string> command);
private Action ActionFunc; /// <summary>
/// A description that will be shown when using the "help (command)" command in the console.
/// </summary>
public readonly string Description;
/// <summary> private Action ActionFunc;
/// Initializes a new instance of the <see cref="DebugConsoleAction"/> class.
/// </summary>
/// <param name="description">Description.</param>
/// <param name="actionFunc">Action func.</param>
public DebugConsoleAction(string description, Action actionFunc) {
this.Description = description;
this.ActionFunc = actionFunc;
}
/// <summary> /// <summary>
/// Executes the <see cref="ActionFunc"/>. /// Initializes a new instance of the <see cref="DebugConsoleAction"/> class.
/// </summary> /// </summary>
/// <param name="command">Command.</param> /// <param name="description">Description.</param>
public void Call(List<string> command) { /// <param name="actionFunc">Action func.</param>
ActionFunc(command); public DebugConsoleAction(string description, Action actionFunc) {
this.Description = description;
this.ActionFunc = actionFunc;
}
/// <summary>
/// Executes the <see cref="ActionFunc"/>.
/// </summary>
/// <param name="command">Command.</param>
public void Call(List<string> command) {
ActionFunc(command);
}
} }
} }

View File

@ -2,65 +2,69 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
/// <summary> namespace Cyber.Console {
/// A class that has static functions for printing text in the DebugConsole.
/// </summary>
public class Term {
private static DebugConsole Console;
/// <summary> /// <summary>
/// Sets the <see cref="DebugConsole"/> singleton that will be used in other static <see cref="Term"/> functions. /// A class that has static functions for printing text in the DebugConsole.
/// </summary> /// </summary>
/// <param name="console">Console.</param> public class Term {
public static void SetDebugConsole(DebugConsole console) {
Console = console; private static DebugConsole Console;
}
/// <summary> /// <summary>
/// Returns whether or not the DebugConsole is currently on the screen, ready to be used. /// Sets the <see cref="DebugConsole"/> singleton that will be used in other static <see cref="Term"/> functions.
/// </summary> /// </summary>
/// <returns><c>true</c> if is visible; otherwise, <c>false</c>.</returns> /// <param name="console">Console.</param>
public static bool IsVisible() { public static void SetDebugConsole(DebugConsole console) {
if (Console == null) { Console = console;
return false;
} else {
return Console.Visible;
} }
}
/// <summary> /// <summary>
/// See <see cref="DebugConsole.Println"/>. /// Returns whether or not the DebugConsole is currently on the screen, ready to be used.
/// </summary> /// </summary>
/// <param name="text">Text.</param> /// <returns><c>true</c> if is visible; otherwise, <c>false</c>.</returns>
public static void Println(string text) { public static bool IsVisible() {
if (Console == null) { if (Console == null) {
Debug.Log(text); return false;
} else { } else {
Console.Println(text); return Console.Visible;
}
} }
}
/// <summary> /// <summary>
/// See <see cref="DebugConsole.Print"/>. /// See <see cref="DebugConsole.Println"/>.
/// </summary> /// </summary>
/// <param name="text">Text.</param> /// <param name="text">Text.</param>
public static void Print(string text) { public static void Println(string text) {
if (Console == null) { if (Console == null) {
Debug.Log(text); Debug.Log(text);
} else { } else {
Console.Print(text); Console.Println(text);
}
} }
}
/// <summary> /// <summary>
/// See <see cref="DebugConsole.AddCommand"/> /// See <see cref="DebugConsole.Print"/>.
/// </summary> /// </summary>
/// <param name="command">Command.</param> /// <param name="text">Text.</param>
/// <param name="description">Description.</param> public static void Print(string text) {
/// <param name="action">Action.</param> if (Console == null) {
public static void AddCommand(string command, string description, DebugConsoleAction.Action action) { Debug.Log(text);
if (Console != null) { } else {
Console.AddCommand(command, description, action); Console.Print(text);
}
}
/// <summary>
/// See <see cref="DebugConsole.AddCommand"/>
/// </summary>
/// <param name="command">Command.</param>
/// <param name="description">Description.</param>
/// <param name="action">Action.</param>
public static void AddCommand(string command, string description, DebugConsoleAction.Action action) {
if (Console != null) {
Console.AddCommand(command, description, action);
}
} }
} }
} }

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ed8f719cfc1ca409787d1cbcb89e6fca
folderAsset: yes
timeCreated: 1494276190
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cyber.Entities;
using Cyber.Console;
namespace Cyber.Controls {
/// <summary>
/// Controls the player character. Shouldn't exist on the server, and only one
/// should exist per client (the character that client is controlling).
/// </summary>
public class PlayerController : MonoBehaviour {
/// <summary>
/// The character this controller should control.
/// </summary>
public Character Character;
private void Update() {
if (!Term.IsVisible()) {
// Handle inputs
Vector3 Move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
if (Move.sqrMagnitude != 0) {
Character.Move(transform.TransformDirection(Move));
} else if (Character.Moving()) {
Character.Stop();
}
} else if (Character.Moving()) {
// The debug console is open, stop the player.
Character.Stop();
}
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c0ce6f05a0f994c00be318d1738f7749
folderAsset: yes
timeCreated: 1494276297
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,52 @@
using UnityEngine;
namespace Cyber.Entities {
/// <summary>
/// A syncable component that all characters have. Controls the character's subsystems.
/// </summary>
public class Character : SyncBase {
/// <summary>
/// How fast the player should move in Unity's spatial units per second.
/// </summary>
public float MovementSpeed = 5.0f;
/// <summary>
/// The character controller, used to move the character. Handles collisions.
/// </summary>
public CharacterController CharacterController;
private Vector3 MovementDirection = new Vector3();
/// <summary>
/// Moves the character in the given direction.
/// </summary>
/// <param name="Direction">Movement direction.</param>
public void Move(Vector3 Direction) {
if (!Direction.Equals(MovementDirection)) {
MovementDirection = Direction.normalized;
}
}
/// <summary>
/// Stops the player from moving.
/// </summary>
public void Stop() {
if (Moving()) {
MovementDirection = new Vector3();
}
}
/// <summary>
/// Whether the player is moving or not.
/// </summary>
public bool Moving() {
return MovementDirection.sqrMagnitude != 0;
}
private void FixedUpdate() {
CharacterController.Move(MovementDirection * MovementSpeed * Time.fixedDeltaTime);
}
}
}

View File

@ -0,0 +1,24 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Cyber.Entities {
/// <summary>
/// Types of entities. Every entity type has its own prefab, see
/// <see cref="Spawner"/>.
/// </summary>
public enum EntityType {
/// <summary>
/// Player character.
/// </summary>
PC,
/// <summary>
/// Non player character.
/// </summary>
NPC
}
}

View File

@ -0,0 +1,69 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cyber.Console;
namespace Cyber.Entities {
/// <summary>
/// A utility class to spawn entities into the world based on
/// their <see cref="EntityType"/> and .
/// </summary>
public class Spawner : MonoBehaviour {
/// <summary>
/// The <see cref="SyncDB"/> this <see cref="Spawner"/> should be using to
/// set entities' IDs.
/// </summary>
public SyncDB SyncDB;
/// <summary>
/// The <see cref="EntityType.PC"/> prefab.
/// </summary>
public GameObject PCEntityPrefab;
/// <summary>
/// The <see cref="EntityType.NPC"/> prefab.
/// </summary>
public GameObject NPCEntityPrefab;
/// <summary>
/// Spawns an entity and returns that entity.
/// </summary>
/// <param name="type">Type.</param>
/// <param name="position">Position.</param>
/// <param name="ids">The ids of the entity's synced components. Should be
/// set if they exist already (eg. the server has sent them over). These
/// ids should be from <see cref="SyncDB.GetEntityIDs"/>. To create new
/// ids, leave as the default (null).</param>
public GameObject Spawn(EntityType type, Vector3 position, uint[] ids = null) {
GameObject Spawned = null;
switch (type) {
case EntityType.PC:
Spawned = Instantiate(PCEntityPrefab, position, new Quaternion(), transform);
break;
case EntityType.NPC:
Spawned = Instantiate(NPCEntityPrefab, position, new Quaternion(), transform);
break;
}
if (Spawned != null) {
if (ids != null) {
SyncDB.AddEntity(Spawned, ids);
} else {
SyncDB.AddEntity(Spawned, SyncDB.GetNewEntityIDs(Spawned));
}
}
return Spawned;
}
private void Start() {
Spawn(EntityType.PC, new Vector3());
}
private void Update() {
if (Input.GetButtonDown("Jump") && !Term.IsVisible()) {
Spawn(EntityType.NPC, new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-2f, 2f)));
}
}
}
}

View File

@ -0,0 +1,19 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Cyber.Entities {
/// <summary>
/// A base class for all syncable components. An instance of
/// <see cref="SyncDB"/> will contain all of the game's synced components.
/// </summary>
public class SyncBase : MonoBehaviour {
/// <summary>
/// The ID this syncable component can be found with from its parent
/// <see cref="SyncDB"/>.
/// </summary>
public uint ID;
}
}

View File

@ -0,0 +1,108 @@
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
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[] {
typeof(Character)
};
private uint IDCounter = 0;
private Dictionary<uint, SyncBase> Database = new Dictionary<uint, SyncBase>();
/// <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>
public void AddEntity(GameObject gameObject, uint[] ids) {
int Index = 0;
for (int i = 0; i < SyncableClasses.Length; i++) {
SyncBase Syncable = (SyncBase)gameObject.GetComponent(SyncableClasses[i]);
if (Syncable != null) {
Syncable.ID = ids[Index];
Database[ids[Index++]] = Syncable;
}
}
}
/// <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>
public uint[] GetEntityIDs(GameObject gameObject, bool newIDs = false) {
List<uint> IDs = new List<uint>();
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);
}
}
uint[] IDArray = new uint[IDs.Count];
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>
public uint[] GetNewEntityIDs(GameObject gameObject) {
return GetEntityIDs(gameObject, true);
}
/// <summary>
/// Get a synced component by its ID.
/// </summary>
/// <param name="id">The ID.</param>
public SyncBase Get(uint id) {
return Database[id];
}
/// <summary>
/// Creates a new ID which isn't in use yet.
/// </summary>
/// <returns>A new, free ID.</returns>
public uint CreateID() {
uint ID;
try {
ID = IDCounter++;
} catch (OverflowException) {
ID = 0;
IDCounter = 1;
}
while (Database.ContainsKey(ID) && ID < uint.MaxValue) {
ID++;
if (ID < uint.MaxValue - 1)
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;
}
}
}

View File

@ -1,18 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Types of entities. Every entity type has its own prefab, see
/// <see cref="Spawner"/>.
/// </summary>
public enum EntityType {
/// <summary>
/// Player character.
/// </summary>
PC,
/// <summary>
/// Non player character.
/// </summary>
NPC
}

View File

@ -1,4 +1,5 @@
using Cyber.Networking.Messages; using Cyber.Console;
using Cyber.Networking.Messages;
using UnityEngine; using UnityEngine;
using UnityEngine.Networking; using UnityEngine.Networking;

View File

@ -3,6 +3,7 @@ using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using Cyber.Networking.Clientside; using Cyber.Networking.Clientside;
using Cyber.Networking.Serverside; using Cyber.Networking.Serverside;
using Cyber.Console;
namespace Cyber.Networking { namespace Cyber.Networking {

View File

@ -1,4 +1,5 @@
using Cyber.Networking.Messages; using Cyber.Console;
using Cyber.Networking.Messages;
using UnityEngine; using UnityEngine;
using UnityEngine.Networking; using UnityEngine.Networking;

View File

@ -1,29 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Controls the player character. Shouldn't exist on the server, and only one
/// should exist per client (the character that client is controlling).
/// </summary>
public class PlayerController : MonoBehaviour {
/// <summary>
/// The character this controller should control.
/// </summary>
public Character Character;
private void Update() {
if (!Term.IsVisible()) {
// Handle inputs
Vector3 Move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
if (Move.sqrMagnitude != 0) {
Character.Move(transform.TransformDirection(Move));
} else if (Character.Moving()) {
Character.Stop();
}
} else if (Character.Moving()) {
// The debug console is open, stop the player.
Character.Stop();
}
}
}

View File

@ -1,62 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// A utility class to spawn entities into the world based on
/// their <see cref="EntityType"/> and .
/// </summary>
public class Spawner : MonoBehaviour {
/// <summary>
/// The <see cref="SyncDB"/> this <see cref="Spawner"/> should be using to
/// set entities' IDs.
/// </summary>
public SyncDB SyncDB;
/// <summary>
/// The <see cref="EntityType.PC"/> prefab.
/// </summary>
public GameObject PCEntityPrefab;
/// <summary>
/// The <see cref="EntityType.NPC"/> prefab.
/// </summary>
public GameObject NPCEntityPrefab;
/// <summary>
/// Spawns an entity and returns that entity.
/// </summary>
/// <param name="type">Type.</param>
/// <param name="position">Position.</param>
/// <param name="ids">The ids of the entity's synced components. Should be
/// set if they exist already (eg. the server has sent them over). These
/// ids should be from <see cref="SyncDB.GetEntityIDs"/>. To create new
/// ids, leave as the default (null).</param>
public GameObject Spawn(EntityType type, Vector3 position, uint[] ids = null) {
GameObject Spawned = null;
switch (type) {
case EntityType.PC:
Spawned = Instantiate(PCEntityPrefab, position, new Quaternion(), transform);
break;
case EntityType.NPC:
Spawned = Instantiate(NPCEntityPrefab, position, new Quaternion(), transform);
break;
}
if (Spawned != null) {
if (ids != null) {
SyncDB.AddEntity(Spawned, ids);
} else {
SyncDB.AddEntity(Spawned, SyncDB.GetNewEntityIDs(Spawned));
}
}
return Spawned;
}
private void Start() {
Spawn(EntityType.PC, new Vector3());
}
private void Update() {
if (Input.GetButtonDown("Jump") && !Term.IsVisible()) {
Spawn(EntityType.NPC, new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-2f, 2f)));
}
}
}

View File

@ -1,15 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// A base class for all syncable components. An instance of
/// <see cref="SyncDB"/> will contain all of the game's synced components.
/// </summary>
public class SyncBase : MonoBehaviour {
/// <summary>
/// The ID this syncable component can be found with from its parent
/// <see cref="SyncDB"/>.
/// </summary>
public uint ID;
}

View File

@ -1,103 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
/// <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[]{
typeof(Character)
};
private uint IDCounter = 0;
private Dictionary<uint, SyncBase> Database = new Dictionary<uint, SyncBase>();
/// <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>
public void AddEntity(GameObject gameObject, uint[] ids) {
int Index = 0;
for (int i = 0; i < SyncableClasses.Length; i++) {
SyncBase Syncable = (SyncBase) gameObject.GetComponent(SyncableClasses[i]);
if (Syncable != null) {
Syncable.ID = ids[Index];
Database[ids[Index++]] = Syncable;
}
}
}
/// <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>
public uint[] GetEntityIDs(GameObject gameObject, bool newIDs = false) {
List<uint> IDs = new List<uint>();
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);
}
}
uint[] IDArray = new uint[IDs.Count];
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>
public uint[] GetNewEntityIDs(GameObject gameObject) {
return GetEntityIDs(gameObject, true);
}
/// <summary>
/// Get a synced component by its ID.
/// </summary>
/// <param name="id">The ID.</param>
public SyncBase Get(uint id) {
return Database[id];
}
/// <summary>
/// Creates a new ID which isn't in use yet.
/// </summary>
/// <returns>A new, free ID.</returns>
public uint CreateID() {
uint ID;
try {
ID = IDCounter++;
} catch (OverflowException) {
ID = 0;
IDCounter = 1;
}
while (Database.ContainsKey(ID) && ID < uint.MaxValue) {
ID++;
if (ID < uint.MaxValue - 1) 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;
}
}