diff --git a/RH-Engine/Command.cs b/RH-Engine/Command.cs
new file mode 100644
index 0000000..6491de4
--- /dev/null
+++ b/RH-Engine/Command.cs
@@ -0,0 +1,329 @@
+using LibNoise.Primitive;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+
+namespace RH_Engine
+{
+ class Command
+ {
+ public const string STANDARD_HEAD = "Head";
+ public const string STANDARD_GROUND = "GroundPlane";
+ public const string STANDARD_SUN = "SunLight";
+ public const string STANDARD_LEFTHAND = "LeftHand";
+ public const string STANDARD_RIGHTHAND = "RightHand";
+
+
+
+ string tunnelID;
+
+ public Command(string tunnelID)
+ {
+ this.tunnelID = tunnelID;
+ }
+
+ public string TerrainCommand(int[] sizeArray, float[] heightsArray)
+ {
+ dynamic payload = new
+ {
+ id = "scene/terrain/add",
+ data = new
+ {
+ size = sizeArray,
+ heights = heightsArray
+ }
+
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+ public string AddLayer(string uid, string texture)
+ {
+ dynamic payload = new
+ {
+ id = "scene/node/addlayer",
+ data = new
+ {
+ id = uid,
+ diffuse = @"C:\Users\woute\Downloads\NetworkEngine.18.10.10.1\NetworkEngine\data\NetworkEngine\textures\terrain\adesert_cracks_d.jpg",
+ normal = @"C:\Users\woute\Downloads\NetworkEngine.18.10.10.1\NetworkEngine\data\NetworkEngine\textures\terrain\adesert_mntn_d.jpg",
+ minHeight = 0,
+ maxHeight = 10,
+ fadeDist = 1
+ }
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+ public string UpdateTerrain()
+ {
+ dynamic payload = new
+ {
+ id = "scene/terrain/update",
+ data = new
+ {
+
+ }
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+ public string AddNodeCommand()
+ {
+ dynamic payload = new
+ {
+ id = "scene/node/add",
+ data = new
+ {
+ name = "newNode",
+ components = new
+ {
+ terrain = new
+ {
+ smoothnormals = true
+ }
+ }
+ }
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+ public string DeleteNode(string uuid)
+ {
+
+ dynamic payload = new
+ {
+ id = "scene/node/delete",
+ data = new
+ {
+ id = uuid,
+
+ }
+
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+
+ }
+
+ public string AddBikeModel()
+ {
+ return AddModel("bike", "data\\NetworkEngine\\models\\bike\\bike.fbx");
+ }
+
+ public string AddModel(string nodeName, string fileLocation)
+ {
+ return AddModel(nodeName, fileLocation, null, new float[] { 0, 0, 0 }, 1, new float[] { 0, 0, 0 });
+ }
+
+ public string AddModel(string nodeName, string fileLocation, float[] positionVector, float scalar, float[] rotationVector)
+ {
+ return AddModel(nodeName, fileLocation, null, positionVector, scalar, rotationVector);
+ }
+
+ public string AddModel(string nodeName, string fileLocation, string animationLocation, float[] positionVector, float scalar, float[] rotationVector)
+ {
+ string namename = nodeName;
+ bool animatedBool = false;
+ if (animationLocation != null)
+ {
+ animatedBool = true;
+ }
+
+ dynamic payload = new
+ {
+ id = "scene/node/add",
+ data = new
+ {
+ name = namename,
+ components = new
+ {
+ transform = new
+ {
+ position = positionVector,
+ scale = scalar,
+ rotation = rotationVector
+
+ },
+ model = new
+ {
+ file = fileLocation,
+ cullbackfaces = true,
+ animated = animatedBool,
+ animation = animationLocation
+ },
+ }
+ }
+
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+ public string MoveTo(string uuid, float[] positionVector, float rotateValue, float speedValue, float timeValue)
+ {
+ return MoveTo(uuid, "idk", positionVector, rotateValue, "linear", false, speedValue, timeValue);
+ }
+
+ private string MoveTo(string uuid, string stopValue, float[] positionVector, float rotateValue, string interpolateValue, bool followHeightValue, float speedValue, float timeValue)
+ {
+ dynamic payload = new
+ {
+ id = "scene/node/moveto",
+ data = new
+ {
+ id = uuid,
+ stop = stopValue,
+ position = positionVector,
+ rotate = rotateValue,
+ interpolate = interpolateValue,
+ followheight = followHeightValue,
+ speed = speedValue,
+ time = timeValue
+ }
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+
+ public string RouteCommand()
+ {
+ ImprovedPerlin improvedPerlin = new ImprovedPerlin(4325, LibNoise.NoiseQuality.Best);
+ Random r = new Random();
+ dynamic payload = new
+ {
+ id = "route/add",
+ data = new
+ {
+ nodes = new dynamic[]
+ {
+ new
+ {
+ /*pos = GetPos(0.6f, improvedPerlin)*/
+ pos = new int[] {0,0,5 },
+ dir = new int[] { r.Next(20,100),0,-r.Next(20, 100) }
+ },
+ new
+ {
+ //pos = GetPos(1.6f, improvedPerlin),
+ pos = new int[] {50,0,0 },
+ dir = new int[] { r.Next(20, 100),0,r.Next(20, 100) }
+ },
+ new
+ {
+ //pos = GetPos(2.654f, improvedPerlin),
+ pos = new int[] {20,0,20 },
+ dir = new int[] { r.Next(20, 100),0,r.Next(20, 100) }
+ },
+ new
+ {
+ //pos = GetPos(3.6543f, improvedPerlin),
+ pos = new int[] {10,0,50 },
+ dir = new int[] { -r.Next(3,7),0,r.Next(3,7) }
+ },
+ new
+ {
+ pos = new int[] {0,0,50 },
+ dir = new int[] { -r.Next(20, 50),0,-r.Next(20, 50) }
+ }
+ }
+ }
+ };
+ Console.WriteLine("route command: " + JsonConvert.SerializeObject(Payload(payload)));
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+ private float[] GetPos(float n, ImprovedPerlin improvedPerlin)
+ {
+ float[] res = new float[] { improvedPerlin.GetValue(n) * 50, 0, improvedPerlin.GetValue(n) * 50 };
+ return res;
+ }
+
+ private int[] GetDir()
+ {
+ Random rng = new Random();
+ int[] dir = {rng.Next(50), 0, rng.Next(50)};
+ return dir;
+ }
+
+ public string FollowRouteCommand()
+ {
+ return "";
+ }
+
+ public string RoadCommand(string uuid_route)
+ {
+ Console.WriteLine("road");
+ dynamic payload = new
+ {
+ id = "scene/road/add",
+ data = new
+ {
+ route = uuid_route,
+ diffuse = "data/NetworkEngine/textures/tarmac_diffuse.png",
+ normal = "data/NetworkEngine/textures/tarmac_normale.png",
+ specular = "data/NetworkEngine/textures/tarmac_specular.png",
+ heightoffset = 1f
+ }
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+ public string GetSceneInfoCommand()
+ {
+ dynamic payload = new
+ {
+ id = "scene/get"
+ };
+
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+ public string ResetScene()
+ {
+ dynamic payload = new
+ {
+ id = "scene/reset"
+ };
+
+ return JsonConvert.SerializeObject(Payload(payload));
+ }
+
+ public string SkyboxCommand(double timeToSet)
+ {
+ if (timeToSet < 0 || timeToSet > 24)
+ {
+ throw new Exception("The time must be between 0 and 24!");
+ }
+
+
+ dynamic payload = new
+ {
+ id = "scene/skybox/settime",
+ data = new
+ {
+ time = timeToSet
+ }
+
+ };
+ return JsonConvert.SerializeObject(Payload(payload));
+
+ }
+
+
+ private object Payload(dynamic message)
+ {
+ return new
+ {
+ id = "tunnel/send",
+ data = new
+ {
+ dest = tunnelID,
+ data = message,
+ }
+ };
+ }
+
+
+
+ }
+}
diff --git a/RH-Engine/JSONParser.cs b/RH-Engine/JSONParser.cs
new file mode 100644
index 0000000..2f1f903
--- /dev/null
+++ b/RH-Engine/JSONParser.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Sockets;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace RH_Engine
+{
+ class JSONParser
+ {
+ ///
+ /// returns all the users from the given response
+ ///
+ /// the message gotten from the server, without the length prefix
+ ///
+ public static PC[] GetUsers(string msg)
+ {
+ dynamic jsonData = JsonConvert.DeserializeObject(msg);
+ Newtonsoft.Json.Linq.JArray data = jsonData.data;
+ PC[] res = new PC[data.Count];
+ int counter = 0;
+ foreach (dynamic d in data)
+ {
+ res[counter] = new PC((string)d.clientinfo.host, (string)d.clientinfo.user);
+ counter++;
+ }
+
+ return res;
+
+ }
+
+ public static string GetSessionID(string msg, PC[] PCs)
+ {
+ dynamic jsonData = JsonConvert.DeserializeObject(msg);
+ Newtonsoft.Json.Linq.JArray data = jsonData.data;
+ for (int i = data.Count-1; i >= 0; i--)
+ {
+ dynamic d = data[i];
+ foreach (PC pc in PCs)
+ {
+ if (d.clientinfo.host == pc.host && d.clientinfo.user == pc.user)
+ {
+ Console.WriteLine("connecting to {0}, on {1} with id {2}", pc.user, pc.host, d.id);
+ return d.id;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static string GetTunnelID(string json)
+ {
+ dynamic jsonData = JsonConvert.DeserializeObject(json);
+ if (jsonData.data.status == "ok")
+ {
+ return jsonData.data.id;
+ }
+ return null;
+ }
+
+ public static string GetRouteID(string json)
+ {
+ dynamic jsonData = JsonConvert.DeserializeObject(json);
+ if (jsonData.data.status == "ok")
+ {
+ return jsonData.data.uuid;
+ }
+ return null;
+ }
+
+ }
+}
diff --git a/RH-Engine/Program.cs b/RH-Engine/Program.cs
new file mode 100644
index 0000000..5955866
--- /dev/null
+++ b/RH-Engine/Program.cs
@@ -0,0 +1,257 @@
+using LibNoise.Primitive;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Globalization;
+using System.IO;
+using System.Net.Sockets;
+using System.Runtime.Intrinsics.X86;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading;
+
+namespace RH_Engine
+{
+
+ internal class Program
+ {
+ private static PC[] PCs = {
+ //new PC("DESKTOP-M2CIH87", "Fabian"),
+ new PC("T470S", "Shinichi"),
+ //new PC("DESKTOP-DHS478C", "semme"),
+ //new PC("DESKTOP-TV73FKO", "Wouter"),
+ //new PC("DESKTOP-SINMKT1", "Ralf"),
+ //new PC("NA", "Bart")
+ };
+ private static void Main(string[] args)
+ {
+ TcpClient client = new TcpClient("145.48.6.10", 6666);
+
+ CreateConnection(client.GetStream());
+
+
+ }
+
+ ///
+ /// writes a message to the server
+ ///
+ /// the network stream to use
+ /// the message to send
+ public static void WriteTextMessage(NetworkStream stream, string message)
+ {
+ byte[] msg = Encoding.ASCII.GetBytes(message);
+ byte[] res = new byte[msg.Length + 4];
+
+ Array.Copy(BitConverter.GetBytes(msg.Length), 0, res, 0, 4);
+ Array.Copy(msg, 0, res, 4, msg.Length);
+
+ stream.Write(res);
+
+ //Console.WriteLine("sent message " + message);
+ }
+
+ ///
+ /// reads a response from the server
+ ///
+ /// the network stream to use
+ /// the returned message from the server
+ public static string ReadPrefMessage(NetworkStream stream)
+ {
+ byte[] lengthBytes = new byte[4];
+
+ stream.Read(lengthBytes, 0, 4);
+ Console.WriteLine("read message..");
+
+ int length = BitConverter.ToInt32(lengthBytes);
+
+ //Console.WriteLine("length is: " + length);
+
+ byte[] buffer = new byte[length];
+ int totalRead = 0;
+
+ //read bytes until stream indicates there are no more
+ do
+ {
+ int read = stream.Read(buffer, totalRead, buffer.Length - totalRead);
+ totalRead += read;
+ //Console.WriteLine("ReadMessage: " + read);
+ } while (totalRead < length);
+
+ return Encoding.UTF8.GetString(buffer, 0, totalRead);
+ }
+ ///
+ /// connects to the server and creates the tunnel
+ ///
+ /// the network stream to use
+ private static void CreateConnection(NetworkStream stream)
+ {
+ WriteTextMessage(stream, "{\r\n\"id\" : \"session/list\"\r\n}");
+ string id = JSONParser.GetSessionID(ReadPrefMessage(stream), PCs);
+
+ string tunnelCreate = "{\"id\" : \"tunnel/create\", \"data\" : {\"session\" : \"" + id + "\"}}";
+
+ WriteTextMessage(stream, tunnelCreate);
+
+ string tunnelResponse = ReadPrefMessage(stream);
+
+ Console.WriteLine(tunnelResponse);
+
+ string tunnelID = JSONParser.GetTunnelID(tunnelResponse);
+ if (tunnelID == null)
+ {
+ Console.WriteLine("could not find a valid tunnel id!");
+ return;
+ }
+
+ sendCommands(stream, tunnelID);
+
+
+ }
+
+ ///
+ /// sends all the commands to the server
+ ///
+ /// the network stream to use
+ /// the tunnel id to use
+ private static void sendCommands(NetworkStream stream, string tunnelID)
+ {
+ Command mainCommand = new Command(tunnelID);
+
+
+ WriteTextMessage(stream, mainCommand.ResetScene());
+ ReadPrefMessage(stream);
+ string routeid = CreateRoute(stream, mainCommand);
+
+ WriteTextMessage(stream, mainCommand.TerrainCommand(new int[] { 256, 256 }, null));
+ Console.WriteLine(ReadPrefMessage(stream));
+ string command;
+
+ command = mainCommand.AddBikeModel();
+
+ WriteTextMessage(stream, command);
+
+ Console.WriteLine(ReadPrefMessage(stream));
+
+ command = mainCommand.AddModel("car", "data\\customModels\\TeslaRoadster.fbx");
+
+ WriteTextMessage(stream, command);
+
+ Console.WriteLine(ReadPrefMessage(stream));
+
+ }
+
+ ///
+ /// gets the id of the object with the given name
+ ///
+ /// the name of the object
+ /// the network stream to send requests to
+ /// the create graphics object to create all the commands
+ /// the uuid of the object with the given name, null otherwise.
+ public static string GetId(string name, NetworkStream stream, Command createGraphics)
+ {
+ JArray children = GetChildren(stream, createGraphics);
+
+ foreach (dynamic child in children)
+ {
+ if (child.name == name)
+ {
+ return child.uuid;
+ }
+ }
+ Console.WriteLine("Could not find id of " + name);
+ return null;
+
+ }
+
+ public static string CreateRoute(NetworkStream stream, Command createGraphics)
+ {
+ WriteTextMessage(stream, createGraphics.RouteCommand());
+ dynamic response = JsonConvert.DeserializeObject(ReadPrefMessage(stream));
+ if (response.data.data.id == "route/add")
+ {
+ return response.data.data.data.uuid;
+ }
+ return null;
+
+ }
+
+ public static void CreateTerrain(NetworkStream stream, Command createGraphics)
+ {
+ float x = 0f;
+ float[] height = new float[256 * 256];
+ ImprovedPerlin improvedPerlin = new ImprovedPerlin(0, LibNoise.NoiseQuality.Best);
+ for (int i = 0; i < 256 * 256; i++)
+ {
+ height[i] = improvedPerlin.GetValue(x / 10, x / 10, x * 100) + 1;
+ x += 0.001f;
+ }
+
+ WriteTextMessage(stream, createGraphics.TerrainCommand(new int[] { 256, 256 }, height));
+ Console.WriteLine(ReadPrefMessage(stream));
+
+ WriteTextMessage(stream, createGraphics.AddNodeCommand());
+ Console.WriteLine(ReadPrefMessage(stream));
+ }
+
+ ///
+ /// gets all the children in the current scene
+ ///
+ /// the network stream to send requests to
+ /// the create graphics object to create all the commands
+ /// all the children objects in the current scene
+ public static JArray GetChildren(NetworkStream stream, Command createGraphics)
+ {
+ WriteTextMessage(stream, createGraphics.GetSceneInfoCommand());
+ dynamic response = JsonConvert.DeserializeObject(ReadPrefMessage(stream));
+ return response.data.data.data.children;
+ }
+
+ ///
+ /// returns all objects in the current scene, as name-uuid tuples.
+ ///
+ /// the network stream to send requests to
+ /// the create graphics object to create all the commands
+ /// an array of name-uuid tuples for each object
+ public static (string, string)[] GetObjectsInScene(NetworkStream stream, Command createGraphics)
+ {
+ JArray children = GetChildren(stream, createGraphics);
+ (string, string)[] res = new (string, string)[children.Count];
+
+ int i = 0;
+ foreach (dynamic child in children)
+ {
+ res[i] = (child.name, child.uuid);
+ i++;
+ }
+
+ return res;
+
+ }
+
+ public static string getUUIDFromResponse(string response)
+ {
+ dynamic JSON = JsonConvert.DeserializeObject(response);
+ return JSON.data.data.data.uuid;
+ }
+
+ }
+
+ ///
+ /// struct used to store the host pc name and user
+ ///
+ public readonly struct PC
+ {
+ public PC(string host, string user)
+ {
+ this.host = host;
+ this.user = user;
+ }
+ public string host { get; }
+ public string user { get; }
+
+ public override string ToString()
+ {
+ return "PC - host:" + host + " - user:" + user;
+ }
+ }
+}
\ No newline at end of file
diff --git a/RH-Engine/RH-Engine.csproj b/RH-Engine/RH-Engine.csproj
new file mode 100644
index 0000000..0c92efb
--- /dev/null
+++ b/RH-Engine/RH-Engine.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ netcoreapp3.1
+ RH_Engine
+
+
+
+
+
+
+
+
diff --git a/RH-Engine/RH-Engine.sln b/RH-Engine/RH-Engine.sln
new file mode 100644
index 0000000..90896e8
--- /dev/null
+++ b/RH-Engine/RH-Engine.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30503.244
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RH-Engine", "RH-Engine.csproj", "{12E8F82B-C464-4152-B4FB-FCB5E1A9FCFA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {12E8F82B-C464-4152-B4FB-FCB5E1A9FCFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12E8F82B-C464-4152-B4FB-FCB5E1A9FCFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12E8F82B-C464-4152-B4FB-FCB5E1A9FCFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12E8F82B-C464-4152-B4FB-FCB5E1A9FCFA}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C75B8E99-BE3D-496F-B2F0-03C4069493B2}
+ EndGlobalSection
+EndGlobal