private static void CreateSceneObject()
        {
            if (GameObject.Find(SceneObjectName) != null)
            {
                Logger.Error("Another version of the library is already loaded. The HugsLib assembly should be loaded as a standalone mod.");
                return;
            }
            var obj = new GameObject(SceneObjectName);

            GameObject.DontDestroyOnLoad(obj);
            obj.AddComponent <UnityProxyComponent>();
        }
 private static void CreateSceneObject()
 {
     // this must execute in the main thread
     LongEventHandler.ExecuteWhenFinished(() => {
         if (GameObject.Find(SceneObjectName) != null)
         {
             Logger.Error("Another version of the library is already loaded. The HugsLib assembly should be loaded as a standalone mod.");
             return;
         }
         var obj = new GameObject(SceneObjectName);
         GameObject.DontDestroyOnLoad(obj);
         obj.AddComponent <UnityProxyComponent>();
     });
 }
        protected override void InitializeMonitor()
        {
            ModLogger.Debug("Initializing prop monitor");

            try
            {
                // Clear any existing data from the overwatch container
                OverwatchPropContainer.Instance.ClearCache();

                // Process the list of existing props when initializing to make sure the list is up-to-date
                var capacity = Singleton <PropManager> .instance.m_props.m_buffer.Count();

                Enumerable.Range(0, capacity).DoAll(i => ProcessProp((ushort)i));

                // Store a reference to the current frame index so we know from which frame we need to process on the next update cycle
                MarkFrame();

                // Mark the monitor as initialized and spinning
                MarkInitialized();
                OverwatchControl.Instance.PropMonitorSpun = true;

                ModLogger.Debug("Prop monitor initialized");
            }
            catch (Exception ex)
            {
                ModLogger.Error("An error occured while initializing the prop monitor");
                ModLogger.Exception(ex);
                MarkTerminated();
            }
        }
Example #4
0
        public override void Start()
        {
            base.Start();

            if (Parent == null)
            {
                ModLogger.Error(String.Format("Parent not set in {0}", this.GetType().Name));
                return;
            }

            width            = Parent.width;
            relativePosition = Vector3.zero;
            isVisible        = true;
            canFocus         = true;
            isInteractive    = true;

            _drag.width            = width - UIConstants.DragHandleWidthOffset;
            _drag.height           = height;
            _drag.relativePosition = Vector3.zero;
            _drag.target           = Parent;

            _icon.spriteName       = IconSprite;
            _icon.relativePosition = UIConstants.TitleIconRelativePosition;

            _title.relativePosition = UIConstants.TitleRelativePosition;
            _title.text             = TitleText;

            _close.relativePosition = new Vector3(width - UIConstants.CloseButtonRelativePositionOffset, 2);
            _close.normalBgSprite   = UIConstants.CloseButtonNormalBgSprite;
            _close.hoveredBgSprite  = UIConstants.CloseButtonHoveredBgSprite;
            _close.pressedBgSprite  = UIConstants.CloseButtonPressedBgSprite;
            _close.eventClick      += (component, param) => Parent.Hide();
        }
        public override void OnLevelUnloading()
        {
            // Don't unload in asset and map editor
            if (_mode != LoadMode.LoadGame && _mode != LoadMode.NewGame)
            {
                return;
            }

            try
            {
                ModLogger.Debug("Destroying main window");

                // Destroy the mainwindow when unloading to make sure a fresh new window is used for the next game
                if (_mainWindow != null)
                {
                    GameObject.Destroy(_mainWindow.gameObject);
                }

                ModLogger.Debug("Main window destroyed");
            }
            catch (Exception ex)
            {
                ModLogger.Error("An error occured while destroying the main window");
                ModLogger.Exception(ex);
            }
        }
        public sealed override void OnLevelLoaded(LoadMode mode)
        {
            _mode = mode;

            // Don't load in asset and map editor
            if (mode != LoadMode.LoadGame && mode != LoadMode.NewGame)
            {
                return;
            }

            try
            {
                ModLogger.Debug("Creating main window");

                // Get a handle to the main game view
                UIView aView = UIView.GetAView();

                // Create the gameobject and attach a mainwindow instance
                GameObject goMainWindow = new GameObject(WorkshopMonitorMainWindowGameObjectName);
                _mainWindow = goMainWindow.AddComponent <UIMainWindow>();
                _mainWindow.transform.parent = aView.transform;

                ModLogger.Debug("Main window created");
            }
            catch (Exception ex)
            {
                ModLogger.Error("An error occured while creating the main window");
                ModLogger.Exception(ex);
            }
        }
Example #7
0
 public void Error(string error)
 {
     if (_logger is ModLogger)
     {
         _logger.Error(error);
     }
 }
Example #8
0
        private void RunUpdateCycle()
        {
            try
            {
                // Get a reference to the current frame
                int end = GetFrame();

                // Process all frames between the previous frame marker and the current frame
                while (_lastProcessedFrame != end)
                {
                    _lastProcessedFrame = GetFrame(_lastProcessedFrame + 1);

                    int[] boundaries = GetFrameBoundaries(_lastProcessedFrame);

                    for (int i = boundaries[0]; i <= boundaries[1]; i++)
                    {
                        CheckAssetExistence((ushort)i);
                    }
                }
            }
            catch (Exception ex)
            {
                ModLogger.Error("An unexpected error occured while running an update cycle in the building monitor");
                ModLogger.Exception(ex);
                MarkTerminated();
            }
        }
        public override void OnBeforeSimulationTick()
        {
            // Exit if the monitor was terminated because of an error occured when updating overwatch data
            if (Terminated)
            {
                return;
            }

            // Exit if the prop monitor has not been loaded yet by the overwatch loader (prevents issues when the loader is not started yet but the monitor is)
            if (!OverwatchControl.Instance.PropMonitorSpun)
            {
                MarkUninitialized();
                return;
            }

            // Exit if the prop monitor has not been initialized yet (initialization happens in OnUpdate)
            if (!Initialized)
            {
                return;
            }

            // Exit if no prop changes occured since the previous tick
            if (!Singleton <PropManager> .instance.m_propsUpdated)
            {
                return;
            }

            try
            {
                for (int i = 0; i < Singleton <PropManager> .instance.m_updatedProps.Length; i++)
                {
                    ulong updatedPropId = Singleton <PropManager> .instance.m_updatedProps[i];
                    if (updatedPropId != 0)
                    {
                        for (int j = 0; j < 64; j++)
                        {
                            if ((updatedPropId & (ulong)1 << j) != 0)
                            {
                                ushort id = (ushort)(i << 6 | j);
                                ProcessProp(id);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ModLogger.Error("An error occured while updating prop information");
                ModLogger.Exception(ex);
                MarkTerminated();
            }

            base.OnBeforeSimulationTick();
        }
        public void Update()
        {
            try
            {
                int workshopAssetCount = _workshopAssets.Count();

                ModLogger.Debug("WorkshopAssetMonitor is updating {0} workshop assets", workshopAssetCount);
                foreach (var item in _workshopAssets)
                {
                    item.UpdateInstanceCount();
                }
                ModLogger.Debug("WorkshopMonitor updated {0} workshop assets", workshopAssetCount);
            }
            catch (Exception ex)
            {
                ModLogger.Error("An error occured while updating the workshop item list, the numbers displayed could be incorrect");
                ModLogger.Exception(ex);
            }
        }
Example #11
0
        protected ModBase()
        {
            modContentPackInt = CurrentlyProcessedContentPack;
            Logger            = new ModLogger(LogIdentifierSafe);
            var settingsPackId = SettingsIdentifier;

            if (!string.IsNullOrEmpty(settingsPackId))
            {
                if (PersistentDataManager.IsValidElementName(settingsPackId))
                {
                    Settings = HugsLibController.Instance.Settings.GetModSettings(settingsPackId, modContentPackInt?.Name);
                }
                else
                {
                    Logger.Error($"string \"{settingsPackId}\" cannot be used as a settings identifier. " +
                                 $"Override {nameof(ModBase)}.{nameof(SettingsIdentifier)} to manually specify one. " +
                                 $"See {nameof(SettingsIdentifier)} autocomplete documentation for expected format.");
                }
            }
        }
Example #12
0
        public override void OnLevelUnloading()
        {
            // Don't stop in asset and map editor
            if (_mode != LoadMode.LoadGame && _mode != LoadMode.NewGame)
            {
                return;
            }

            try
            {
                ModLogger.Debug("Stopping WorkshopAssetMonitor");
                WorkshopAssetMonitor.Instance.Stop();
                ModLogger.Debug("WorkshopAssetMonitor stopped");
            }
            catch (Exception ex)
            {
                ModLogger.Error("An error occured while stopping the WorkshopAssetMonitor");
                ModLogger.Exception(ex);
            }
        }
Example #13
0
        public override void OnUpdate(float realTimeDelta, float simulationTimeDelta)
        {
            // Exit if the monitor was terminated because of an error occured when updating overwatch data
            if (_terminated)
            {
                return;
            }

            // Exit if the monitor has not been loaded yet by the overwatch loader when a game is loaded (prevents issues when the loader is not started yet but the monitor is)
            if (!OverwatchControl.Instance.GameLoaded)
            {
                return;
            }

            try
            {
                // Initialize the monitor if it wasn't initialized yet
                if (!_initialized)
                {
                    InitializeMonitor();
                }
                // Run an update cycle if the simulation is not currently paused
                else if (!SimulationManager.instance.SimulationPaused)
                {
                    RunUpdateCycle();
                }
            }
            catch (Exception ex)
            {
                ModLogger.Error(string.Format("An unexpected error occured while updating the {0}", _monitorType));
                ModLogger.Exception(ex);
                _terminated = true;
            }

            base.OnUpdate(realTimeDelta, simulationTimeDelta);
        }
Example #14
0
            public bool Load()
            {
                if (mStarted)
                {
                    if (mErrorOnLoading)
                    {
                        return(false);
                    }
                    return(true);
                }
                mErrorOnLoading = false;
                Logger.Log($"Version '{Info.Version}'. Loading.");
                if (string.IsNullOrEmpty(Info.AssemblyName))
                {
                    mErrorOnLoading = true;
                    Logger.Error(string.Format("{0} is null.", "AssemblyName"));
                }
                if (string.IsNullOrEmpty(Info.EntryMethod))
                {
                    mErrorOnLoading = true;
                    Logger.Error(string.Format("{0} is null.", "EntryMethod"));
                }
                if (!string.IsNullOrEmpty(Info.ManagerVersion) && ManagerVersion > GetVersion())
                {
                    mErrorOnLoading = true;
                    Logger.Error($"Mod Manager must be version '{Info.ManagerVersion}' or higher.");
                }
                if (Requirements.Count > 0)
                {
                    foreach (KeyValuePair <string, Version> requirement in Requirements)
                    {
                        string   key      = requirement.Key;
                        ModEntry modEntry = FindMod(key);
                        if (modEntry == null || modEntry.Assembly == null)
                        {
                            mErrorOnLoading = true;
                            Logger.Error($"Required mod '{key}' not loaded.");
                        }
                        else if (!modEntry.Enabled)
                        {
                            mErrorOnLoading = true;
                            Logger.Error($"Required mod '{key}' disabled.");
                        }
                        else if (!modEntry.Active)
                        {
                            Logger.Log($"Required mod '{key}' inactive.");
                        }
                        else if (requirement.Value != null && requirement.Value > modEntry.Version)
                        {
                            mErrorOnLoading = true;
                            Logger.Error($"Required mod '{key}' must be version '{requirement.Value}' or higher.");
                        }
                    }
                }
                if (mErrorOnLoading)
                {
                    return(false);
                }
                string text = System.IO.Path.Combine(Path, Info.AssemblyName);

                if (File.Exists(text))
                {
                    try
                    {
                        if (mAssembly == null)
                        {
                            mAssembly = Assembly.LoadFile(text);
                        }
                    }
                    catch (Exception ex)
                    {
                        mErrorOnLoading = true;
                        Logger.Error($"Error loading file '{text}'.");
                        Logger.Error(ex.ToString());
                        return(false);
                    }
                    try
                    {
                        object[] param = new object[1]
                        {
                            this
                        };
                        Type[] types = new Type[1]
                        {
                            typeof(ModEntry)
                        };
                        if (FindMethod(Info.EntryMethod, types, showLog: false) == null)
                        {
                            param = null;
                            types = null;
                        }
                        if (!Invoke(Info.EntryMethod, out object result, param, types) || (result != null && !(bool)result))
                        {
                            mErrorOnLoading = true;
                            Logger.Log("Not loaded.");
                        }
                    }
                    catch (Exception ex2)
                    {
                        mErrorOnLoading = true;
                        Logger.Error($"Error loading file '{text}'.");
                        Logger.Error(ex2.ToString());
                        return(false);
                    }
                    mStarted = true;
                    if (!mErrorOnLoading && Enabled)
                    {
                        Active = true;
                        return(true);
                    }
                }
                else
                {
                    mErrorOnLoading = true;
                    Logger.Error($"'{text}' not found.");
                }
                return(false);
            }
        public void Start()
        {
            try
            {
                ModLogger.Debug("WorkshopAssetMonitor is loading workshop assets");

                // The package manager monitors the list of workshop assets, so retrieve the packageid from each item
                var workshopIds = PackageManager
                                  .FilterAssets(UserAssetType.CustomAssetMetaData)
                                  .Where(a => a.isWorkshopAsset)
                                  .Select(a => new { Asset = a, Metadata = a.Instantiate <CustomAssetMetaData>() })
                                  .Select(a => ulong.Parse(a.Asset.package.packageName))
                                  .Distinct();

                // The PrefabCollections monitor the list of all prefabs available in the game, which includes the default CS prefabs and the custom prefabs from workshop assets
                // Try to match the prefabs with the workshop packageid list to make sure only workshopassets are loaded.

                for (int i = 0; i < PrefabCollection <PropInfo> .PrefabCount(); i++)
                {
                    PropInfo propPrefab = PrefabCollection <PropInfo> .GetPrefab((uint)i);

                    if (propPrefab != null)
                    {
                        var workshopPropMatch = Regex.Match(propPrefab.name, RegexExpression.BuildingName, RegexOptions.IgnoreCase);
                        if (workshopPropMatch.Success)
                        {
                            var workshopPropId = ulong.Parse(workshopPropMatch.Groups["packageid"].Value);
                            if (workshopIds.Any(id => id == workshopPropId))
                            {
                                _workshopAssets.Add(new WorkshopProp(workshopPropId, workshopPropMatch.Groups["prefabname"].Value, propPrefab.name));
                            }
                        }
                    }
                }

                for (int i = 0; i < PrefabCollection <TreeInfo> .PrefabCount(); i++)
                {
                    TreeInfo treePrefab = PrefabCollection <TreeInfo> .GetPrefab((uint)i);

                    if (treePrefab != null)
                    {
                        var workshopTreeMatch = Regex.Match(treePrefab.name, RegexExpression.BuildingName, RegexOptions.IgnoreCase);
                        if (workshopTreeMatch.Success)
                        {
                            var workshopPropId = ulong.Parse(workshopTreeMatch.Groups["packageid"].Value);
                            if (workshopIds.Any(id => id == workshopPropId))
                            {
                                _workshopAssets.Add(new WorkshopTree(workshopPropId, workshopTreeMatch.Groups["prefabname"].Value, treePrefab.name));
                            }
                        }
                    }
                }

                for (int i = 0; i < PrefabCollection <BuildingInfo> .PrefabCount(); i++)
                {
                    BuildingInfo buildingPrefab = PrefabCollection <BuildingInfo> .GetPrefab((uint)i);

                    if (buildingPrefab != null)
                    {
                        var workshopBuildingMatch = Regex.Match(buildingPrefab.name, RegexExpression.BuildingName, RegexOptions.IgnoreCase);
                        if (workshopBuildingMatch.Success)
                        {
                            var workshopBuildingId = ulong.Parse(workshopBuildingMatch.Groups["packageid"].Value);
                            if (workshopIds.Any(id => id == workshopBuildingId))
                            {
                                _workshopAssets.Add(new WorkshopBuilding(workshopBuildingId, workshopBuildingMatch.Groups["prefabname"].Value, buildingPrefab.name, buildingPrefab.GetService().ToAssetType()));
                            }
                        }
                    }
                }



                ModLogger.Debug("WorkshopAssetMonitor loaded {0} workshop assets", GetWorkshopAssetCount());
            }
            catch (Exception ex)
            {
                ModLogger.Error("An error occured while starting the workshop monitor, no workshop assets where loaded");
                ModLogger.Exception(ex);
            }
        }