diff --git a/.gitmodules b/.gitmodules index c23b65d89..3e1970886 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "Assets/UnityStandardAssets"] path = Assets/UnityStandardAssets url = https://github.com/GTA-ASM/UnityStandardAssets +[submodule "Assets/RCONdotnet"] + path = Assets/RCONdotnet + url = https://github.com/undbsd/rcon-dotnet diff --git a/Assets/Prefabs/GameManager.prefab b/Assets/Prefabs/GameManager.prefab index 95ed07bc8..7eefad21d 100644 --- a/Assets/Prefabs/GameManager.prefab +++ b/Assets/Prefabs/GameManager.prefab @@ -24,6 +24,7 @@ GameObject: - component: {fileID: 1318502437576191535} - component: {fileID: 7442340376164908290} - component: {fileID: 8446601354455743255} + - component: {fileID: 5853763562556677784} m_Layer: 0 m_Name: GameManager m_TagString: Untagged @@ -299,3 +300,15 @@ MonoBehaviour: type: 3} messagesContainer: {fileID: 0} messagePoolSize: 10 +--- !u!114 &5853763562556677784 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297494511425690} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c77317cdc437f244b8d409c229aa2e95, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Assets/RCONdotnet b/Assets/RCONdotnet new file mode 160000 index 000000000..b5e93d94f --- /dev/null +++ b/Assets/RCONdotnet @@ -0,0 +1 @@ +Subproject commit b5e93d94fd0a3b46dd19e3d62cf427f72f58ed40 diff --git a/Assets/RCONdotnet.meta b/Assets/RCONdotnet.meta new file mode 100644 index 000000000..e6ca7902c --- /dev/null +++ b/Assets/RCONdotnet.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: be08b0c2aac61f94f8676008c1f1a546 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/config.json b/Assets/Resources/config.json index 40a80f7f3..b86c6fba0 100644 --- a/Assets/Resources/config.json +++ b/Assets/Resources/config.json @@ -10,7 +10,7 @@ "sv_max_connections": 32, "sv_port": 14242, - "game_dir" : "", + "game_dir": "", "archive_paths": [ "${game_dir}/models/gta3.img", @@ -35,10 +35,13 @@ "water_path": "${game_dir}/data/water.dat", "car_colors_path": "${game_dir}/data/carcols.dat", "anim_groups_paths": [ - "${game_dir}/data/animgrp.dat", + "${game_dir}/data/animgrp.dat" ], "weapons_path": "${game_dir}/data/weapon.dat", "dontLoadTextures": false, - + + "RCON_enabled": false, + "RCON_password": "super_secret_password", + "RCON_port": 25575 } \ No newline at end of file diff --git a/Assets/Scripts/RCON.meta b/Assets/Scripts/RCON.meta new file mode 100644 index 000000000..bd664770c --- /dev/null +++ b/Assets/Scripts/RCON.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 381eb0e589457424db93a1587f86f9eb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/RCON/CommandInterpreter.cs b/Assets/Scripts/RCON/CommandInterpreter.cs new file mode 100644 index 000000000..48c5dd11e --- /dev/null +++ b/Assets/Scripts/RCON/CommandInterpreter.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SanAndreasUnity.RCON +{ + public class CommandInterpreter + { + public static String Interpret(String command) + { + string[] words = command.Split(' '); + + if (command == "heartbeat") + { + // Implement heartbeat ping + return "Heartbeat was sent to master server"; + } + + if (command == "help") + { + return "The available commands for now are heartbeat, announce and help"; + } + + if (words[0] == "announce") + { + String announcement = String.Join(" ", words, 1, words.Length - 1); + SanAndreasUnity.Chat.ChatManager.SendChatMessageToAllPlayersAsServer(announcement); + return "Server : " + announcement; + } + + return "Unknown command"; + } + } + +} \ No newline at end of file diff --git a/Assets/Scripts/RCON/CommandInterpreter.cs.meta b/Assets/Scripts/RCON/CommandInterpreter.cs.meta new file mode 100644 index 000000000..8ac37831e --- /dev/null +++ b/Assets/Scripts/RCON/CommandInterpreter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9cf8ca8374941dd4aaa862202a1a2b7b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/RCON/RCONManager.cs b/Assets/Scripts/RCON/RCONManager.cs new file mode 100644 index 000000000..40e90f023 --- /dev/null +++ b/Assets/Scripts/RCON/RCONManager.cs @@ -0,0 +1,100 @@ +using Rcon; +using Rcon.Events; +using SanAndreasUnity.Net; +using SanAndreasUnity.Utilities; +using System; +using System.Collections.Concurrent; +using System.ComponentModel; +using System.Threading.Tasks; +using UnityEngine; + +namespace SanAndreasUnity.RCON +{ + public class RCONManager : MonoBehaviour + { + // Todo : set these from config + private static String password; + private static int portNumber; + + // Objects used to pass commands and responses between threads + private static BlockingCollection mainToSec = new BlockingCollection(1); + private static BlockingCollection secToMain = new BlockingCollection(1); + + private static BackgroundWorker workerInstance = null; + + public static void StartServer() + { + password = Config.Get("RCON_password"); + portNumber = Config.Get("RCON_port"); + + if (workerInstance != null) + return; + + workerInstance = new BackgroundWorker(); + + workerInstance.DoWork += new DoWorkEventHandler( worker_doWork ); + workerInstance.ProgressChanged += new ProgressChangedEventHandler( worker_progressChanged ); + workerInstance.WorkerReportsProgress = true; + // workerInstance.WorkerSupportsCancellation = true; + + workerInstance.RunWorkerAsync(); // Call the background worker + } + + #region Code that runs in the RCON Server Thread + private static void worker_doWork(object sender, DoWorkEventArgs e) + { + using (RconServer server = new RconServer(password, portNumber)) + { + server.OnClientCommandReceived += Server_OnClientCommandReceived; + server.OnClientConnected += Server_OnClientConnected; + server.OnClientAuthenticated += Server_OnClientAuthenticated; + server.OnClientDisconnected += Server_OnClientDisconnected; + server.Start(); + } + } + static void Server_OnClientAuthenticated(object sender, ClientAuthenticatedEventArgs e) + { + // Console.WriteLine("{0} authenticated", e.Client.Client.LocalEndPoint); + } + static void Server_OnClientDisconnected(object sender, ClientDisconnectedEventArgs e) + { + // Console.WriteLine("{0} disconnected", e.EndPoint); + } + static void Server_OnClientConnected(object sender, ClientConnectedEventArgs e) + { + // Console.WriteLine("{0} connected", e.Client.Client.LocalEndPoint); + } + static string Server_OnClientCommandReceived(object sender, ClientSentCommandEventArgs e) + { + secToMain.Add(e.Command); // Pass the command to the main thread + + workerInstance.ReportProgress(0); //Report our progress to the main thread + + String commandResult = "Command didn't process correctly"; // default value + + commandResult = mainToSec.Take(); + + return commandResult; + } + #endregion + + // Runs in main thread + private static void worker_progressChanged(object sender, ProgressChangedEventArgs e) + { + String command = "unknown"; + + command = secToMain.Take(); + + mainToSec.Add(CommandInterpreter.Interpret(command)); + } + + void OnLoaderFinished() + { + if (NetStatus.IsServer) + { + if (Config.Get("RCON_enabled")) + StartServer(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/RCON/RCONManager.cs.meta b/Assets/Scripts/RCON/RCONManager.cs.meta new file mode 100644 index 000000000..875af0128 --- /dev/null +++ b/Assets/Scripts/RCON/RCONManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c77317cdc437f244b8d409c229aa2e95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: