示例#1
0
    protected override void OnMessage(MessageEventArgs e)
    {
        if (e.Data == "chatfull")
        {
            Send(RconManager.GetFullChatLog());
        }

        if (e.Data[0].Equals('1'))
        {
            RconManager.Instance.ReceiveRconChat(e.Data);
        }
    }
示例#2
0
    private void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode)
    {
        if (scene.name == "Lobby")
        {
            IsInGame = false;
            Managers.instance.SetScreenForLobby();
        }
        else
        {
            IsInGame = true;
            Managers.instance.SetScreenForGame();
            SetPlayerPreferences();
        }

        if (CustomNetworkManager.Instance.isNetworkActive)
        {
            //Reset stuff
            if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null || Instance.testServer)
            {
                IsHeadlessServer = true;
            }
            if (IsInGame && GameManager.Instance != null && CustomNetworkManager.Instance._isServer)
            {
                GameManager.Instance.ResetRoundTime();
            }
            return;
        }
        //force vsync when not-headless
        if (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Null && !Instance.testServer && !IsHeadlessServer)
        {
            Application.targetFrameRate = 60;
            QualitySettings.vSyncCount  = 1;
        }
        //Check if running in batchmode (headless server)
        if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null || Instance.testServer)
        {
            float calcFrameRate = 1f / Time.fixedDeltaTime;
            Application.targetFrameRate = (int)calcFrameRate;
            Logger.Log("START SERVER HEADLESS MODE");
            IsHeadlessServer = true;
            StartCoroutine(WaitToStartServer());

            if (rconManager == null)
            {
                GameObject rcon = Instantiate(Resources.Load("Rcon/RconManager") as GameObject, null) as GameObject;
                rconManager = rcon.GetComponent <RconManager>();
                Logger.Log("Start rcon server", Category.Rcon);
            }
        }
    }
示例#3
0
    private void PropagateChatToClients(ChatEvent chatEvent)
    {
        var players = PlayerList.Instance.InGamePlayers;

        //Local chat range checks:
        if (chatEvent.channels == ChatChannel.Local || chatEvent.channels == ChatChannel.Combat)
        {
            //			var speaker = PlayerList.Instance.Get(chatEvent.speaker);
            RaycastHit2D hit;
            LayerMask    layerMask = 1 << 9;          //Walls layer
            for (int i = 0; i < players.Count(); i++)
            {
                if (Vector2.Distance(chatEvent.position,                //speaker.GameObject.transform.position,
                                     players[i].GameObject.transform.position) > 14f)
                {
                    //Player in the list is too far away for local chat, remove them:
                    players.Remove(players[i]);
                }
                else
                {
                    //within range, but check if they are in another room or hiding behind a wall
                    if (Physics2D.Linecast(chatEvent.position,                    //speaker.GameObject.transform.position,
                                           players[i].GameObject.transform.position, layerMask))
                    {
                        //if it hit a wall remove that player
                        players.Remove(players[i]);
                    }
                }
            }
        }

        for (var i = 0; i < players.Count; i++)
        {
            var         playerScript = players[i].GameObject.GetComponent <PlayerScript>();
            ChatChannel channels     = playerScript.GetAvailableChannelsMask(false) & chatEvent.channels;
            UpdateChatMessage.Send(players[i].GameObject, channels, chatEvent.message);
        }

        if (RconManager.Instance != null)
        {
            string name = "";
            if ((namelessChannels & chatEvent.channels) != chatEvent.channels)
            {
                name = "<b>[" + chatEvent.channels + "]</b> ";
            }
            RconManager.AddChatLog(name + chatEvent.message);
        }
    }
示例#4
0
    private void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode)
    {
        if (scene.name == "Lobby")
        {
            IsInGame = false;
            Managers.instance.SetScreenForLobby();
        }
        else
        {
            IsInGame = true;
            Managers.instance.SetScreenForGame();
            SetPlayerPreferences();
        }

        if (CustomNetworkManager.Instance.isNetworkActive)
        {
            //Reset stuff
            CheckHeadlessState();

            if (IsInGame && GameManager.Instance != null && CustomNetworkManager.Instance._isServer)
            {
                GameManager.Instance.ResetRoundTime();
            }

            return;
        }

        //Check if running in batchmode (headless server)
        if (CheckHeadlessState())
        {
//			float calcFrameRate = 1f / Time.deltaTime;
//			Application.targetFrameRate = (int) calcFrameRate;
//			Logger.Log($"Starting server in HEADLESS mode. Target framerate is {Application.targetFrameRate}",
//				Category.Server);

            Logger.Log($"FrameRate limiting has been disabled on Headless Server",
                       Category.Server);
            IsHeadlessServer = true;
            StartCoroutine(WaitToStartServer());

            if (rconManager == null)
            {
                GameObject rcon = Instantiate(Resources.Load("Rcon/RconManager") as GameObject, null) as GameObject;
                rconManager = rcon.GetComponent <RconManager>();
                Logger.Log("Start rcon server", Category.Rcon);
            }
        }
    }
示例#5
0
    protected override void OnMessage(MessageEventArgs e)
    {
        if (e.Data == "lastlog")
        {
            Send(RconManager.GetLastLog());
        }

        if (e.Data == "logfull")
        {
            Send(RconManager.GetFullLog());
        }

        if (e.Data[0].Equals('1'))
        {
            RconManager.Instance.ReceiveRconCommand(e.Data);
        }
    }
示例#6
0
    public static void AmendLog(string msg)
    {
        if (RconManager.Instance != null)
        {
            RconManager.AddLog(msg);
        }

        DebugLog += msg + "\n";
        LastLog   = msg;
        if (DebugLog.Length > 10000)
        {
            DebugLog = DebugLog.Substring(9000);
        }

        //if it is null it means the object is still disabled and is about be enabled
        if (Instance != null)
        {
            Instance.RefreshLogDisplay();
        }
    }
示例#7
0
    public void PropagateChatToClients(ChatEvent chatEvent)
    {
        List <ConnectedPlayer> players = PlayerList.Instance.AllPlayers;

        //Local chat range checks:
        if (chatEvent.channels.HasFlag(ChatChannel.Local) ||
            chatEvent.channels.HasFlag(ChatChannel.Combat) ||
            chatEvent.channels.HasFlag(ChatChannel.Action))
        {
            for (int i = players.Count - 1; i >= 0; i--)
            {
                if (players[i].Script == null)
                {
                    //joined viewer, don't message them
                    players.RemoveAt(i);
                    continue;
                }

                if (players[i].Script.gameObject == chatEvent.originator)
                {
                    //Always send the originator chat to themselves
                    continue;
                }

                if (players[i].Script.IsGhost && players[i].Script.IsPlayerSemiGhost == false)
                {
                    //send all to ghosts
                    continue;
                }

                if (chatEvent.position == TransformState.HiddenPos)
                {
                    //show messages with no provided position to everyone
                    continue;
                }

                //Send chat to PlayerChatLocation pos, usually just the player object but for AI is its vessel
                var playerPosition = players[i].Script.PlayerChatLocation.OrNull()?.AssumedWorldPosServer()
                                     ?? players[i].Script.gameObject.AssumedWorldPosServer();

                //Do player position to originator distance check
                if (DistanceCheck(playerPosition) == false)
                {
                    //Distance check failed so if we are Ai, then try send action and combat messages to their camera location
                    //as well as if possible
                    if (chatEvent.channels.HasFlag(ChatChannel.Local) == false &&
                        players[i].Script.PlayerState == PlayerScript.PlayerStates.Ai &&
                        players[i].Script.TryGetComponent <AiPlayer>(out var aiPlayer) &&
                        aiPlayer.IsCarded == false)
                    {
                        playerPosition = players[i].Script.gameObject.AssumedWorldPosServer();

                        //Check camera pos
                        if (DistanceCheck(playerPosition))
                        {
                            //Camera can see player, allow Ai to see action/combat messages
                            continue;
                        }
                    }

                    //Player failed distance checks remove them
                    players.RemoveAt(i);
                }

                bool DistanceCheck(Vector3 playerPos)
                {
                    //TODO maybe change this to (chatEvent.position - playerPos).sqrMagnitude > 196f to avoid square root for performance?
                    if (Vector2.Distance(chatEvent.position, playerPos) > 14f)
                    {
                        //Player in the list is too far away for local chat, remove them:
                        return(false);
                    }

                    //Within range, but check if they are in another room or hiding behind a wall
                    if (MatrixManager.Linecast(chatEvent.position, LayerTypeSelection.Walls,
                                               layerMask, playerPos).ItHit)
                    {
                        //If it hit a wall remove that player
                        return(false);
                    }

                    //Player can see the position
                    return(true);
                }
            }

            //Get NPCs in vicinity
            var npcs = Physics2D.OverlapCircleAll(chatEvent.position, 14f, npcMask);
            foreach (Collider2D coll in npcs)
            {
                var npcPosition = coll.gameObject.AssumedWorldPosServer();
                if (MatrixManager.Linecast(chatEvent.position, LayerTypeSelection.Walls,
                                           layerMask, npcPosition).ItHit == false)
                {
                    //NPC is in hearing range, pass the message on:
                    var mobAi = coll.GetComponent <MobAI>();
                    if (mobAi != null)
                    {
                        mobAi.LocalChatReceived(chatEvent);
                    }
                }
            }
        }

        for (var i = 0; i < players.Count; i++)
        {
            ChatChannel channels = chatEvent.channels;

            if (channels.HasFlag(ChatChannel.Combat) || channels.HasFlag(ChatChannel.Local) ||
                channels.HasFlag(ChatChannel.System) || channels.HasFlag(ChatChannel.Examine) ||
                channels.HasFlag(ChatChannel.Action))
            {
                //Binary check here to avoid speaking in local when speaking on binary
                if (!channels.HasFlag(ChatChannel.Binary) || (players[i].Script.IsGhost && players[i].Script.IsPlayerSemiGhost == false))
                {
                    UpdateChatMessage.Send(players[i].GameObject, channels, chatEvent.modifiers, chatEvent.message, chatEvent.messageOthers,
                                           chatEvent.originator, chatEvent.speaker, chatEvent.stripTags);

                    continue;
                }
            }

            if (players[i].Script == null)
            {
                channels &= ChatChannel.OOC;
            }
            else
            {
                channels &= players[i].Script.GetAvailableChannelsMask(false);
            }

            //if the mask ends up being a big fat 0 then don't do anything
            if (channels != ChatChannel.None)
            {
                UpdateChatMessage.Send(players[i].GameObject, channels, chatEvent.modifiers, chatEvent.message, chatEvent.messageOthers,
                                       chatEvent.originator, chatEvent.speaker, chatEvent.stripTags);
            }
        }

        if (rconManager != null)
        {
            string name = "";
            if ((namelessChannels & chatEvent.channels) != chatEvent.channels)
            {
                name = "<b>[" + chatEvent.channels + "]</b> ";
            }

            RconManager.AddChatLog(name + chatEvent.message);
        }
    }
示例#8
0
    private void PropagateChatToClients(ChatEvent chatEvent)
    {
        List <ConnectedPlayer> players = PlayerList.Instance.AllPlayers;

        //Local chat range checks:
        if (chatEvent.channels.HasFlag(ChatChannel.Local) ||
            chatEvent.channels.HasFlag(ChatChannel.Combat) ||
            chatEvent.channels.HasFlag(ChatChannel.Action))
        {
            for (int i = players.Count - 1; i >= 0; i--)
            {
                if (players[i].Script == null)
                {
                    //joined viewer, don't message them
                    players.RemoveAt(i);
                    continue;
                }

                if (players[i].Script.IsGhost)
                {
                    //send all to ghosts
                    continue;
                }

                if (chatEvent.position == TransformState.HiddenPos)
                {
                    //show messages with no provided position to everyone
                    continue;
                }

                var playerPosition = players[i].GameObject.AssumedWorldPosServer();
                if (Vector2.Distance(chatEvent.position, playerPosition) > 14f)
                {
                    //Player in the list is too far away for local chat, remove them:
                    players.RemoveAt(i);
                }
                else
                {
                    //within range, but check if they are in another room or hiding behind a wall
                    if (MatrixManager.Linecast(chatEvent.position, LayerTypeSelection.Walls
                                               , layerMask, playerPosition).ItHit)
                    {
                        //if it hit a wall remove that player
                        players.RemoveAt(i);
                    }
                }
            }

            //Get NPCs in vicinity
            var npcs = Physics2D.OverlapCircleAll(chatEvent.position, 14f, npcMask);
            foreach (Collider2D coll in npcs)
            {
                var npcPosition = coll.gameObject.AssumedWorldPosServer();
                if (MatrixManager.Linecast(chatEvent.position, LayerTypeSelection.Walls,
                                           layerMask, npcPosition).ItHit == false)
                {
                    //NPC is in hearing range, pass the message on:
                    var mobAi = coll.GetComponent <MobAI>();
                    if (mobAi != null)
                    {
                        mobAi.LocalChatReceived(chatEvent);
                    }
                }
            }
        }

        for (var i = 0; i < players.Count; i++)
        {
            ChatChannel channels = chatEvent.channels;

            if (channels.HasFlag(ChatChannel.Combat) || channels.HasFlag(ChatChannel.Local) ||
                channels.HasFlag(ChatChannel.System) || channels.HasFlag(ChatChannel.Examine) ||
                channels.HasFlag(ChatChannel.Action))
            {
                if (!channels.HasFlag(ChatChannel.Binary) || players[i].Script.IsGhost)
                {
                    UpdateChatMessage.Send(players[i].GameObject, channels, chatEvent.modifiers, chatEvent.message, chatEvent.messageOthers,
                                           chatEvent.originator, chatEvent.speaker);

                    continue;
                }
            }

            if (players[i].Script == null)
            {
                channels &= ChatChannel.OOC;
            }
            else
            {
                channels &= players[i].Script.GetAvailableChannelsMask(false);
            }

            //if the mask ends up being a big fat 0 then don't do anything
            if (channels != ChatChannel.None)
            {
                UpdateChatMessage.Send(players[i].GameObject, channels, chatEvent.modifiers, chatEvent.message, chatEvent.messageOthers,
                                       chatEvent.originator, chatEvent.speaker);
            }
        }

        if (rconManager != null)
        {
            string name = "";
            if ((namelessChannels & chatEvent.channels) != chatEvent.channels)
            {
                name = "<b>[" + chatEvent.channels + "]</b> ";
            }

            RconManager.AddChatLog(name + chatEvent.message);
        }
    }
示例#9
0
        /// <summary>
        /// A debug entry is received
        /// </summary>
        /// <param name="logString">The Debug.Log/LogError/LogWarning/LogException/LogAssertion string</param>
        /// <param name="stackTrace">The debug entry trace</param>
        /// <param name="logType">Error, warning, informational message</param>
        private void ReceivedLog(string logString, string stackTrace, LogType logType)
        {
            DebugLogEntry logEntry = new DebugLogEntry(logString, stackTrace, null);

            // Check if this entry is a duplicate (i.e. has been received before)
            int  logEntryIndex;
            bool isEntryInCollapsedEntryList = collapsedLogEntriesMap.TryGetValue(logEntry, out logEntryIndex);

            if (isEntryInCollapsedEntryList == false)
            {
                // It is not a duplicate,
                // add it to the list of unique debug entries
                logEntry.logTypeSpriteRepresentation = logSpriteRepresentations[logType];

                if (RconManager.Instance != null)
                {
                    RconManager.AddLog(logString);
                }

                logEntryIndex = collapsedLogEntries.Count;
                collapsedLogEntries.Add(logEntry);
                collapsedLogEntriesMap[logEntry] = logEntryIndex;
            }
            else
            {
                // It is a duplicate,
                // increment the original debug item's collapsed count
                logEntry = collapsedLogEntries[logEntryIndex];
                logEntry.count++;
            }

            // Add the index of the unique debug entry to the list
            // that stores the order the debug entries are received
            uncollapsedLogEntriesIndices.Add(logEntryIndex);

            // If this debug entry matches the current filters,
            // add it to the list of debug entries to show
            Sprite logTypeSpriteRepresentation = logEntry.logTypeSpriteRepresentation;

            if (isCollapseOn && isEntryInCollapsedEntryList)
            {
                if (isLogWindowVisible)
                {
                    recycledListView.OnCollapsedLogEntryAtIndexUpdated(logEntryIndex);
                }
            }
            else if (logFilter == DebugLogFilter.All ||
                     (logTypeSpriteRepresentation == infoLog && ((logFilter & DebugLogFilter.Info) == DebugLogFilter.Info)) ||
                     (logTypeSpriteRepresentation == warningLog && ((logFilter & DebugLogFilter.Warning) == DebugLogFilter.Warning)) ||
                     (logTypeSpriteRepresentation == errorLog && ((logFilter & DebugLogFilter.Error) == DebugLogFilter.Error)))
            {
                indicesOfListEntriesToShow.Add(logEntryIndex);

                if (isLogWindowVisible)
                {
                    recycledListView.OnLogEntriesUpdated(false);
                }
            }

            if (logType == LogType.Log)
            {
                infoEntryCount++;
                infoEntryCountText.text = infoEntryCount.ToString();

                // If debug popup is visible, notify it of the new debug entry
                if (isLogWindowVisible == false)
                {
                    popupManager.NewInfoLogArrived();
                }
            }
            else if (logType == LogType.Warning)
            {
                warningEntryCount++;
                warningEntryCountText.text = warningEntryCount.ToString();

                // If debug popup is visible, notify it of the new debug entry
                if (isLogWindowVisible == false)
                {
                    popupManager.NewWarningLogArrived();
                }
            }
            else
            {
                errorEntryCount++;
                errorEntryCountText.text = errorEntryCount.ToString();

                // If debug popup is visible, notify it of the new debug entry
                if (isLogWindowVisible == false)
                {
                    popupManager.NewErrorLogArrived();
                }
            }
        }
示例#10
0
    private static void TryLog(string message, Level messageLevel, Category category = Category.Unknown, params object[] args)
    {
        Level referenceLevel = LogLevel;

        if (LogOverrides.ContainsKey(category))
        {
            referenceLevel = LogOverrides[category];
        }

        if (referenceLevel < messageLevel)
        {
            return;
        }

        string categoryPrefix = category == Category.Unknown ? "" : "[" + category + "] ";

        string msg = categoryPrefix + message;

        if (args.Length > 0)
        {
            switch (messageLevel)
            {
            case Level.Off:
                break;

            case Level.Error:
                Debug.LogErrorFormat(msg, args);
                break;

            case Level.Warning:
                Debug.LogWarningFormat(msg, args);
                break;

            case Level.Info:
                Debug.LogFormat(msg, args);
                break;

            case Level.Trace:
                Debug.LogFormat(msg, args);
                break;
            }
        }
        else
        {
            switch (messageLevel)
            {
            case Level.Off:
                break;

            case Level.Error:
                Debug.LogError(msg);
                break;

            case Level.Warning:
                Debug.LogWarning(msg);
                break;

            case Level.Info:
                Debug.Log(msg);
                break;

            case Level.Trace:
                Debug.Log(msg);
                break;
            }
        }

        if (RconManager.Instance != null)
        {
            RconManager.AddLog(msg);
        }

        DebugConsole.AmendLog(msg);
    }
示例#11
0
    private void PropagateChatToClients(ChatEvent chatEvent)
    {
        List <ConnectedPlayer> players;

        if (chatEvent.matrix != MatrixInfo.Invalid)
        {
            //get players only on provided matrix
            players = PlayerList.Instance.GetPlayersOnMatrix(chatEvent.matrix);
        }
        else
        {
            players = PlayerList.Instance.AllPlayers;
        }

        //Local chat range checks:
        if (chatEvent.channels == ChatChannel.Local || chatEvent.channels == ChatChannel.Combat ||
            chatEvent.channels == ChatChannel.Action)
        {
            //			var speaker = PlayerList.Instance.Get(chatEvent.speaker);
            LayerMask layerMask = LayerMask.GetMask("Walls", "Door Closed");
            for (int i = 0; i < players.Count(); i++)
            {
                if (players[i].Script == null)
                {
                    //joined viewer, don't message them
                    players.Remove(players[i]);
                    continue;
                }

                if (players[i].Script.IsGhost)
                {
                    //send all to ghosts
                    continue;
                }

                if (Vector2.Distance(chatEvent.position,                 //speaker.GameObject.transform.position,
                                     players[i].GameObject.transform.position) > 14f)
                {
                    //Player in the list is too far away for local chat, remove them:
                    players.Remove(players[i]);
                }
                else
                {
                    //within range, but check if they are in another room or hiding behind a wall
                    if (Physics2D.Linecast(chatEvent.position,                     //speaker.GameObject.transform.position,
                                           players[i].GameObject.transform.position, layerMask))
                    {
                        //if it hit a wall remove that player
                        players.Remove(players[i]);
                    }
                }
            }

            //Get NPCs in vicinity
            var npcMask = LayerMask.GetMask("NPC");
            var npcs    = Physics2D.OverlapCircleAll(chatEvent.position, 14f, npcMask);
            foreach (Collider2D coll in npcs)
            {
                if (!Physics2D.Linecast(chatEvent.position,
                                        coll.transform.position, layerMask))
                {
                    //NPC is in hearing range, pass the message on:
                    var mobAi = coll.GetComponent <MobAI>();
                    if (mobAi != null)
                    {
                        mobAi.LocalChatReceived(chatEvent);
                    }
                }
            }
        }

        for (var i = 0; i < players.Count; i++)
        {
            ChatChannel channels = chatEvent.channels;

            if (channels.HasFlag(ChatChannel.Combat) || channels.HasFlag(ChatChannel.Local) ||
                channels.HasFlag(ChatChannel.System) || channels.HasFlag(ChatChannel.Examine) ||
                channels.HasFlag(ChatChannel.Action))
            {
                if (!channels.HasFlag(ChatChannel.Binary) || players[i].Script.IsGhost)
                {
                    UpdateChatMessage.Send(players[i].GameObject, channels, chatEvent.modifiers, chatEvent.message, chatEvent.messageOthers,
                                           chatEvent.originator, chatEvent.speaker);
                    continue;
                }
            }

            if (players[i].Script == null)
            {
                channels &= ChatChannel.OOC;
            }
            else
            {
                channels &= players[i].Script.GetAvailableChannelsMask(false);
            }

            //if the mask ends up being a big fat 0 then don't do anything
            if (channels != ChatChannel.None)
            {
                UpdateChatMessage.Send(players[i].GameObject, channels, chatEvent.modifiers, chatEvent.message, chatEvent.messageOthers,
                                       chatEvent.originator, chatEvent.speaker);
            }
        }

        if (RconManager.Instance != null)
        {
            string name = "";
            if ((namelessChannels & chatEvent.channels) != chatEvent.channels)
            {
                name = "<b>[" + chatEvent.channels + "]</b> ";
            }

            RconManager.AddChatLog(name + chatEvent.message);
        }
    }
示例#12
0
        private async void Startup()
        {
            // Print exception messages in English
            Thread.CurrentThread.CurrentUICulture     = CultureInfo.InvariantCulture;
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;

            // Set the AppDomain working directory to the current resource root
            Environment.CurrentDirectory = Path.GetFullPath(API.GetResourcePath(API.GetCurrentResourceName()));

            new Logger().Info($"NFive {typeof(Program).Assembly.GetCustomAttributes<AssemblyInformationalVersionAttribute>().First().InformationalVersion}");

            // TODO: Check and warn if local CitizenFX.Core.Server.dll is found

            var config = ConfigurationManager.Load <CoreConfiguration>("core.yml");

            // Use configured culture for output
            Thread.CurrentThread.CurrentCulture     = config.Locale.Culture.First();
            CultureInfo.DefaultThreadCurrentCulture = config.Locale.Culture.First();

            ServerConfiguration.Locale    = config.Locale;
            ServerLogConfiguration.Output = config.Log.Output;

            var logger = new Logger(config.Log.Core);

            API.SetGameType(config.Display.Game);
            API.SetMapName(config.Display.Map);

            // Setup RPC handlers
            RpcManager.Configure(config.Log.Comms, this.EventHandlers, this.Players);

            var events = new EventManager(config.Log.Comms);
            var comms  = new CommunicationManager(events);
            var rcon   = new RconManager(comms);

            // Load core controllers
            try
            {
                var dbController = new DatabaseController(new Logger(config.Log.Core, "Database"), ConfigurationManager.Load <DatabaseConfiguration>("database.yml"), comms);
                await dbController.Loaded();

                this.controllers.Add(new Name("NFive/Database"), new List <Controller> {
                    dbController
                });
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Database connection error");
                logger.Warn("Fatal error, exiting");
                Environment.Exit(1);
            }

            var eventController = new EventController(new Logger(config.Log.Core, "FiveM"), comms);
            await eventController.Loaded();

            this.controllers.Add(new Name("NFive/RawEvents"), new List <Controller> {
                eventController
            });

            var sessionController = new SessionController(new Logger(config.Log.Core, "Session"), ConfigurationManager.Load <SessionConfiguration>("session.yml"), comms);
            await sessionController.Loaded();

            this.controllers.Add(new Name("NFive/Session"), new List <Controller> {
                sessionController
            });

            // Resolve dependencies
            var graph = DefinitionGraph.Load();

            // IoC
            var assemblies = new List <Assembly>();

            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Include != null).SelectMany(p => p.Server.Include.Select(i => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{i}.net.dll")))));
            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Main != null).SelectMany(p => p.Server.Main.Select(m => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{m}.net.dll")))));

            var registrar = new ContainerRegistrar();

            registrar.RegisterService <ILogger>(s => new Logger());
            registrar.RegisterInstance <IRconManager>(rcon);
            registrar.RegisterInstance <IBaseScriptProxy>(new BaseScriptProxy(this.EventHandlers, this.Exports, this.Players));
            registrar.RegisterInstance <ICommunicationManager>(comms);
            registrar.RegisterInstance <IClientList>(new ClientList(new Logger(config.Log.Core, "ClientList"), comms));
            registrar.RegisterPluginComponents(assemblies.Distinct());

            // DI
            var container = registrar.Build();

            var pluginDefaultLogLevel = config.Log.Plugins.ContainsKey("default") ? config.Log.Plugins["default"] : LogLevel.Info;

            // Load plugins into the AppDomain
            foreach (var plugin in graph.Plugins)
            {
                logger.Info($"Loading {plugin.FullName}");

                // Load include files
                foreach (var includeName in plugin.Server?.Include ?? new List <string>())
                {
                    var includeFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{includeName}.net.dll");
                    if (!File.Exists(includeFile))
                    {
                        throw new FileNotFoundException(includeFile);
                    }

                    AppDomain.CurrentDomain.Load(File.ReadAllBytes(includeFile));
                }

                // Load main files
                foreach (var mainName in plugin.Server?.Main ?? new List <string>())
                {
                    var mainFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{mainName}.net.dll");
                    if (!File.Exists(mainFile))
                    {
                        throw new FileNotFoundException(mainFile);
                    }

                    var asm = Assembly.LoadFrom(mainFile);

                    var sdkVersion = asm.GetCustomAttribute <ServerPluginAttribute>();

                    if (sdkVersion == null)
                    {
                        throw new Exception("Unable to load outdated SDK plugin");                         // TODO
                    }

                    if (sdkVersion.Target != SDK.Server.SDK.Version)
                    {
                        throw new Exception("Unable to load outdated SDK plugin");
                    }

                    var types = Assembly.LoadFrom(mainFile).GetTypes().Where(t => !t.IsAbstract && t.IsClass).ToList();

                    // Find migrations
                    foreach (var migrationType in types.Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(MigrationConfiguration <>)))
                    {
                        var configuration = (DbMigrationsConfiguration)Activator.CreateInstance(migrationType);
                        var migrator      = new DbMigrator(configuration);

                        if (!migrator.GetPendingMigrations().Any())
                        {
                            continue;
                        }

                        if (!ServerConfiguration.AutomaticMigrations)
                        {
                            throw new MigrationsPendingException($"Plugin {plugin.FullName} has pending migrations but automatic migrations are disabled");
                        }

                        foreach (var migration in migrator.GetPendingMigrations())
                        {
                            new Logger(config.Log.Core, "Database").Debug($"[{mainName}] Running migration: {migration}");

                            migrator.Update(migration);
                        }
                    }

                    // Find controllers
                    foreach (var controllerType in types.Where(t => t.IsSubclassOf(typeof(Controller)) || t.IsSubclassOf(typeof(ConfigurableController <>))))
                    {
                        var logLevel = config.Log.Plugins.ContainsKey(plugin.Name) ? config.Log.Plugins[plugin.Name] : pluginDefaultLogLevel;

                        var constructorArgs = new List <object>
                        {
                            new Logger(logLevel, plugin.Name)
                        };

                        // Check if controller is configurable
                        if (controllerType.BaseType != null && controllerType.BaseType.IsGenericType && controllerType.BaseType.GetGenericTypeDefinition() == typeof(ConfigurableController <>))
                        {
                            // Initialize the controller configuration
                            constructorArgs.Add(ConfigurationManager.InitializeConfig(plugin.Name, controllerType.BaseType.GetGenericArguments()[0]));
                        }

                        // Resolve IoC arguments
                        constructorArgs.AddRange(controllerType.GetConstructors()[0].GetParameters().Skip(constructorArgs.Count).Select(p => container.Resolve(p.ParameterType)));

                        Controller controller = null;

                        try
                        {
                            // Construct controller instance
                            controller = (Controller)Activator.CreateInstance(controllerType, constructorArgs.ToArray());
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception in plugin {plugin.FullName}");
                        }

                        if (controller == null)
                        {
                            continue;
                        }

                        try
                        {
                            await controller.Loaded();

                            if (!this.controllers.ContainsKey(plugin.Name))
                            {
                                this.controllers.Add(plugin.Name, new List <Controller>());
                            }
                            this.controllers[plugin.Name].Add(controller);
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception loading plugin {plugin.FullName}");
                        }
                    }
                }
            }

            await Task.WhenAll(this.controllers.SelectMany(c => c.Value).Select(s => s.Started()));

            rcon.Controllers = this.controllers;

            comms.Event(CoreEvents.ClientPlugins).FromClients().OnRequest(e => e.Reply(graph.Plugins));

            logger.Debug($"{graph.Plugins.Count.ToString(CultureInfo.InvariantCulture)} plugin(s) loaded, {this.controllers.Count.ToString(CultureInfo.InvariantCulture)} controller(s) created");

            comms.Event(ServerEvents.ServerInitialized).ToServer().Emit();

            logger.Info("Server ready");
        }
示例#13
0
        public Program()
        {
            // Set the AppDomain working directory to the current resource root
            Environment.CurrentDirectory = FileManager.ResolveResourcePath();

            var config = ConfigurationManager.Load <CoreConfiguration>("nfive.yml");

            var logger = new Logger(config.Log.Core);

            //ServerConfiguration.LogLevel = config.Log.Level;
            API.SetGameType(config.Display.Game);
            API.SetMapName(config.Display.Map);

            // Setup RPC handlers
            RpcManager.Configure(config.Log.Rpc, this.EventHandlers);

            var events = new EventManager(config.Log.Events);
            var rcon   = new RconManager(new RpcHandler());

            // Load core controllers
            this.controllers.Add(new Name("NFive/Server"), new List <Controller>());

            var dbController = new DatabaseController(new Logger(config.Log.Core, "Database"), events, new RpcHandler(), rcon, ConfigurationManager.Load <DatabaseConfiguration>("database.yml"));

            this.controllers[new Name("NFive/Server")].Add(dbController);

            // Resolve dependencies
            var graph = DefinitionGraph.Load();

            var pluginDefaultLogLevel = config.Log.Plugins.ContainsKey("default") ? config.Log.Plugins["default"] : LogLevel.Info;

            // Load plugins into the AppDomain
            foreach (var plugin in graph.Plugins)
            {
                logger.Info($"Loading {plugin.FullName}");

                // Load include files
                foreach (var includeName in plugin.Server?.Include ?? new List <string>())
                {
                    var includeFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{includeName}.net.dll");
                    if (!File.Exists(includeFile))
                    {
                        throw new FileNotFoundException(includeFile);
                    }

                    AppDomain.CurrentDomain.Load(File.ReadAllBytes(includeFile));
                }

                // Load main files
                foreach (var mainName in plugin.Server?.Main ?? new List <string>())
                {
                    var mainFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{mainName}.net.dll");
                    if (!File.Exists(mainFile))
                    {
                        throw new FileNotFoundException(mainFile);
                    }

                    var types = Assembly.LoadFrom(mainFile).GetTypes().Where(t => !t.IsAbstract && t.IsClass).ToList();

                    //logger.Debug($"{mainName}: {types.Count} {string.Join(Environment.NewLine, types)}");

                    // Find migrations
                    foreach (var migrationType in types.Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(MigrationConfiguration <>)))
                    {
                        var configuration = (DbMigrationsConfiguration)Activator.CreateInstance(migrationType);
                        var migrator      = new DbMigrator(configuration);

                        if (!migrator.GetPendingMigrations().Any())
                        {
                            continue;
                        }

                        if (!ServerConfiguration.AutomaticMigrations)
                        {
                            throw new MigrationsPendingException($"Plugin {plugin.FullName} has pending migrations but automatic migrations are disabled");
                        }

                        logger.Debug($"{mainName}: Running migrations {string.Join(", ", migrator.GetPendingMigrations())}");

                        migrator.Update();
                    }

                    // Find controllers
                    foreach (var controllerType in types.Where(t => t.IsSubclassOf(typeof(Controller)) || t.IsSubclassOf(typeof(ConfigurableController <>))))
                    {
                        var logLevel = config.Log.Plugins.ContainsKey(plugin.Name) ? config.Log.Plugins[plugin.Name] : pluginDefaultLogLevel;

                        var constructorArgs = new List <object>
                        {
                            new Logger(logLevel, plugin.Name),
                            events,
                            new RpcHandler(),
                            rcon
                        };

                        // Check if controller is configurable
                        if (controllerType.BaseType != null && controllerType.BaseType.IsGenericType && controllerType.BaseType.GetGenericTypeDefinition() == typeof(ConfigurableController <>))
                        {
                            // Initialize the controller configuration
                            constructorArgs.Add(ConfigurationManager.InitializeConfig(plugin.Name, controllerType.BaseType.GetGenericArguments()[0]));
                        }

                        // Construct controller instance
                        var controller = (Controller)Activator.CreateInstance(controllerType, constructorArgs.ToArray());

                        if (!this.controllers.ContainsKey(plugin.Name))
                        {
                            this.controllers.Add(plugin.Name, new List <Controller>());
                        }
                        this.controllers[plugin.Name].Add(controller);
                    }
                }
            }

            rcon.Controllers = this.controllers;

            new RpcHandler().Event(SDK.Core.Rpc.RpcEvents.ClientPlugins).On(e => e.Reply(graph.Plugins));

            events.Raise(SDK.Server.Events.ServerEvents.ServerInitialized);

            logger.Info($"{graph.Plugins.Count} plugins loaded, {this.controllers.Count} controller(s) created");
        }
示例#14
0
        private async void Startup()
        {
            // Set the AppDomain working directory to the current resource root
            Environment.CurrentDirectory = Path.GetFullPath(API.GetResourcePath(API.GetCurrentResourceName()));

            Logger.Initialize();
            new Logger().Info($"NFive {typeof(Program).Assembly.GetCustomAttributes<AssemblyInformationalVersionAttribute>().First().InformationalVersion}");

            var config = ConfigurationManager.Load <CoreConfiguration>("nfive.yml");

            ServerLogConfiguration.Output = config.Log.Output;
            //ServerConfiguration.LogLevel = config.Log.Level;

            var logger = new Logger(config.Log.Core);

            API.SetGameType(config.Display.Game);
            API.SetMapName(config.Display.Map);

            // Setup RPC handlers
            RpcManager.Configure(config.Log.Rpc, this.EventHandlers);

            // Client log mirroring
            new RpcHandler().Event("nfive:log:mirror").On(new Action <IRpcEvent, DateTime, LogLevel, string, string>((e, dt, level, prefix, message) =>
            {
                new Logger(LogLevel.Trace, $"Client#{e.Client.Handle}|{prefix}").Log(message, level);
            }));

            var events = new EventManager(config.Log.Events);
            var rcon   = new RconManager(new RpcHandler());

            // Load core controllers
            var dbController = new DatabaseController(new Logger(config.Log.Core, "Database"), events, new RpcHandler(), rcon, ConfigurationManager.Load <DatabaseConfiguration>("database.yml"));
            await dbController.Loaded();

            this.controllers.Add(new Name("NFive/Database"), new List <Controller> {
                dbController
            });

            var sessionController = new SessionController(new Logger(config.Log.Core, "Session"), events, new RpcHandler(), rcon, ConfigurationManager.Load <SessionConfiguration>("session.yml"));
            await sessionController.Loaded();

            this.controllers.Add(new Name("NFive/Session"), new List <Controller> {
                sessionController
            });

            // Resolve dependencies
            var graph = DefinitionGraph.Load();

            var pluginDefaultLogLevel = config.Log.Plugins.ContainsKey("default") ? config.Log.Plugins["default"] : LogLevel.Info;

            // IoC
            var assemblies = new List <Assembly>();

            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Include != null).SelectMany(p => p.Server.Include.Select(i => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{i}.net.dll")))));
            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Main != null).SelectMany(p => p.Server.Main.Select(m => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{m}.net.dll")))));

            var registrar = new ContainerRegistrar();

            registrar.RegisterService <ILogger>(s => new Logger());
            registrar.RegisterType <IRpcHandler, RpcHandler>();
            registrar.RegisterInstance <IEventManager>(events);
            registrar.RegisterInstance <IRconManager>(rcon);
            registrar.RegisterInstance <IClientList>(new ClientList(new Logger(config.Log.Core, "ClientList"), new RpcHandler()));
            registrar.RegisterSdkComponents(assemblies.Distinct());

            // DI
            var container = registrar.Build();

            // Load plugins into the AppDomain
            foreach (var plugin in graph.Plugins)
            {
                logger.Info($"Loading {plugin.FullName}");

                // Load include files
                foreach (var includeName in plugin.Server?.Include ?? new List <string>())
                {
                    var includeFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{includeName}.net.dll");
                    if (!File.Exists(includeFile))
                    {
                        throw new FileNotFoundException(includeFile);
                    }

                    AppDomain.CurrentDomain.Load(File.ReadAllBytes(includeFile));
                }

                // Load main files
                foreach (var mainName in plugin.Server?.Main ?? new List <string>())
                {
                    var mainFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{mainName}.net.dll");
                    if (!File.Exists(mainFile))
                    {
                        throw new FileNotFoundException(mainFile);
                    }

                    var types = Assembly.LoadFrom(mainFile).GetTypes().Where(t => !t.IsAbstract && t.IsClass).ToList();

                    // Find migrations
                    foreach (var migrationType in types.Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(MigrationConfiguration <>)))
                    {
                        var configuration = (DbMigrationsConfiguration)Activator.CreateInstance(migrationType);
                        var migrator      = new DbMigrator(configuration);

                        if (!migrator.GetPendingMigrations().Any())
                        {
                            continue;
                        }

                        if (!ServerConfiguration.AutomaticMigrations)
                        {
                            throw new MigrationsPendingException($"Plugin {plugin.FullName} has pending migrations but automatic migrations are disabled");
                        }

                        foreach (var migration in migrator.GetPendingMigrations())
                        {
                            new Logger(config.Log.Core, "Database").Debug($"[{mainName}] Running migration: {migration}");

                            migrator.Update(migration);
                        }
                    }

                    // Find controllers
                    foreach (var controllerType in types.Where(t => t.IsSubclassOf(typeof(Controller)) || t.IsSubclassOf(typeof(ConfigurableController <>))))
                    {
                        var logLevel = config.Log.Plugins.ContainsKey(plugin.Name) ? config.Log.Plugins[plugin.Name] : pluginDefaultLogLevel;

                        var constructorArgs = new List <object>
                        {
                            new Logger(logLevel, plugin.Name),
                            events,
                            new RpcHandler(),
                            rcon
                        };

                        // Check if controller is configurable
                        if (controllerType.BaseType != null && controllerType.BaseType.IsGenericType && controllerType.BaseType.GetGenericTypeDefinition() == typeof(ConfigurableController <>))
                        {
                            // Initialize the controller configuration
                            constructorArgs.Add(ConfigurationManager.InitializeConfig(plugin.Name, controllerType.BaseType.GetGenericArguments()[0]));
                        }

                        // Resolve IoC arguments
                        constructorArgs.AddRange(controllerType.GetConstructors()[0].GetParameters().Skip(constructorArgs.Count).Select(p => container.Resolve(p.ParameterType)));

                        Controller controller = null;

                        try
                        {
                            // Construct controller instance
                            controller = (Controller)Activator.CreateInstance(controllerType, constructorArgs.ToArray());
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception in plugin {plugin.FullName}");
                        }

                        if (controller == null)
                        {
                            continue;
                        }

                        try
                        {
                            await controller.Loaded();

                            if (!this.controllers.ContainsKey(plugin.Name))
                            {
                                this.controllers.Add(plugin.Name, new List <Controller>());
                            }
                            this.controllers[plugin.Name].Add(controller);
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception loading plugin {plugin.FullName}");
                        }
                    }
                }
            }

#pragma warning disable 4014
            foreach (var controller in this.controllers.SelectMany(c => c.Value))
            {
                controller.Started();
            }
#pragma warning restore 4014

            rcon.Controllers = this.controllers;

            new RpcHandler().Event(SDK.Core.Rpc.RpcEvents.ClientPlugins).On(e => e.Reply(graph.Plugins));

            events.Raise(ServerEvents.ServerInitialized);

            logger.Debug($"{graph.Plugins.Count} plugin(s) loaded, {this.controllers.Count} controller(s) created");
        }
示例#15
0
        private void InitEvents()
        {
            PlayerLife.OnTellHealth_Global          += BasePlayerEvents.InternalOnTellHealth;
            PlayerLife.OnTellFood_Global            += BasePlayerEvents.InternalOnTellFood;
            PlayerLife.OnTellWater_Global           += BasePlayerEvents.InternalOnTellWater;
            PlayerLife.OnTellVirus_Global           += BasePlayerEvents.InternalOnTellVirus;
            PlayerLife.OnTellBleeding_Global        += BasePlayerEvents.InternalOnTellBleeding;
            PlayerLife.OnTellBroken_Global          += BasePlayerEvents.InternalOnTellBroken;
            PlayerLife.OnRevived_Global             += BasePlayerEvents.InternalOnRevived;
            PlayerLife.onPlayerDied                 += BasePlayerEvents.InternalOnPlayerDied;
            PlayerAnimator.OnGestureChanged_Global  += BasePlayerEvents.InternalOnGestureChanged;
            PlayerSkills.OnExperienceChanged_Global += BasePlayerEvents.InternalOnExperienceChanged;
            PlayerStance.OnStanceChanged_Global     += BasePlayerEvents.InternalOnStanceChanged;

            CommandWindow.onCommandWindowInputted += (string text, ref bool exe) =>
            {
                if (!text.StartsWith("/"))
                {
                    return;
                }
                CommandManager.ExecuteCommand(ConsolePlayer.DefaultPlayer, text);
                exe = false;
            };

            CommandWindow.onCommandWindowOutputted += (obj, color) =>
            {
                if (!SettingsManager.RemoteSetting.Enabled || !RconManager.IsInit)
                {
                    return;
                }
            };

            Provider.onCheckValid += (ValidateAuthTicketResponse_t callback, ref bool valid) =>
            {
                var(prefix, postfix) = callback.m_SteamID.GetPrefixAndSuffix();

                if (prefix == "" && postfix == "")
                {
                    return;
                }

                var pending = callback.m_SteamID.GetPending();

                if (pending == null)
                {
                    return;
                }

                if (prefix != "" && !pending.playerID.characterName.StartsWith(prefix))
                {
                    pending.playerID.characterName = $"{prefix}{pending.playerID.characterName}";
                }

                if (postfix != "" && !pending.playerID.characterName.EndsWith(postfix))
                {
                    pending.playerID.characterName = $"{pending.playerID.characterName}{postfix}";
                }
            };

            ChatManager.onCheckPermissions += (SteamPlayer player, string text, ref bool exe, ref bool list) =>
            {
                if (!text.StartsWith("/"))
                {
                    exe = false;
                    return;
                }

                CommandManager.ExecuteCommand(player.ToBasePlayer(), text);
                list = false;
            };

            Provider.onServerHosted += OnServerHosted;

            if (SettingsManager.RemoteSetting.Enabled)
            {
                RconManager.Init();
            }
        }