public void Execute(IRocketPlayer caller, string[] command)
        {
            var args           = command.ToList();
            var pluginInstance = BaseClusteringPlugin.Instance;

            if (pluginInstance == null)
            {
                throw new NullReferenceException("BaseClusteringPlugin.Instance is null. Cannot execute command.");
            }


            var plants = args.CheckArgsIncludeString("v", out var index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var builds = BuildableDirectory.GetBuildables(includePlants: plants);

            var topBuilders = builds.GroupBy(k => k.Owner).OrderByDescending(k => k.Count()).Take(5).ToList();

            for (var i = 0; i < topBuilders.Count; i++)
            {
                var builder = topBuilders.ElementAt(i);

                UnturnedChat.Say(caller,
                                 pluginInstance.Translate("top_builder_format", i + 1, builder.Key, builder.Count()));
            }
        }
        public void Execute(IRocketPlayer caller, string[] command)
        {
            var pluginInstance = BaseClusteringPlugin.Instance;

            if (pluginInstance == null)
            {
                throw new NullReferenceException("BaseClusteringPlugin.Instance is null. Cannot execute command.");
            }

            if (!(caller is UnturnedPlayer player))
            {
                return;
            }

            if (!Physics.Raycast(new Ray(player.Player.look.aim.position, player.Player.look.aim.forward), out var hit,
                                 player.Player.look.perspective == EPlayerPerspective.THIRD ? 6 : 4,
                                 RayMasks.BARRICADE_INTERACT | RayMasks.BARRICADE | RayMasks.STRUCTURE |
                                 RayMasks.STRUCTURE_INTERACT) ||
                hit.transform == null)
            {
                UnturnedChat.Say(caller, pluginInstance.Translate("not_looking_buildable"));
                return;
            }

            var buildable = BuildableDirectory.GetBuildable(hit.transform);

            if (buildable == null)
            {
                UnturnedChat.Say(caller, pluginInstance.Translate("not_looking_buildable"));
                return;
            }

            buildable.SafeDestroy();
        }
        /// <summary>
        /// Unloads and de-initializes the plugin.
        /// </summary>
        protected override void Unload()
        {
            Instance = null;

            Provider.onCommenceShutdown -= SaveManager.save;
            Level.onLevelLoaded         -= OnLevelLoaded;

            if (BaseClusterDirectory != null)
            {
                BaseClusterDirectory.Unload();
                BaseClusterDirectory = null;
            }

            if (BuildableDirectory != null)
            {
                BuildableDirectory.Unload();
                BuildableDirectory = null;
            }

            if (m_Harmony != null)
            {
                m_Harmony.UnpatchAll();
                m_Harmony = null;
            }

            Logging.PluginUnloaded(this);
        }
        /// <summary>
        /// Loads and initializes the plugin.
        /// </summary>
        protected override void Load()
        {
            m_Harmony = new Harmony("xyz.pustalorc.baseClustering");
            m_Harmony.PatchAll();

            BuildableDirectory = new BuildableDirectory(Configuration.Instance);

            if (Configuration.Instance.EnableClustering)
            {
                BaseClusterDirectory = new BaseClusterDirectory(this, Configuration.Instance, BuildableDirectory);
            }

            if (Level.isLoaded)
            {
                OnLevelLoaded(0);
            }
            else
            {
                Level.onLevelLoaded += OnLevelLoaded;
            }

            Provider.onCommenceShutdown += SaveManager.save;

            Instance = this;
            Logging.PluginLoaded(this);
        }
        /// <summary>
        /// Creates a new instance of the BaseCluster Directory.
        /// </summary>
        /// <param name="plugin">The instance of the plugin.</param>
        /// <param name="pluginConfiguration">The configuration of the plugin.</param>
        /// <param name="buildableDirectory">The buildable directory, which should've been initialized beforehand.</param>
        public BaseClusterDirectory(BaseClusteringPlugin plugin, BaseClusteringPluginConfiguration pluginConfiguration,
                                    BuildableDirectory buildableDirectory)
        {
            m_Plugin = plugin;
            m_PluginConfiguration = pluginConfiguration;
            m_BuildableDirectory  = buildableDirectory;
            m_ClusterPool         = new ConcurrentBag <BaseCluster>();
            m_Clusters            = new List <BaseCluster>();

            PatchBuildableTransforms.OnBuildableTransformed += BuildableTransformed;
            buildableDirectory.OnBuildablesAdded            += BuildablesSpawned;
            buildableDirectory.OnBuildablesRemoved          += BuildablesDestroyed;
            SaveManager.onPostSave += Save;
        }
            internal static void ReceiveTransformStructure(byte x, byte y, uint instanceID)
            {
                var buildable = BuildableDirectory.GetBuildable(instanceID, true);

                if (buildable == null)
                {
                    if (!StructureManager.tryGetRegion(x, y, out var region))
                    {
                        return;
                    }

                    var data = region.structures.FirstOrDefault(k => k.instanceID == instanceID);
                    var drop = region.drops.FirstOrDefault(k => k.instanceID == instanceID);

                    if (data == null || drop == null)
                    {
                        return;
                    }

                    buildable = new StructureBuildable(data, drop);
                }

                OnBuildableTransformed?.Invoke(buildable !);
            }
            internal static void ReceiveTransformBarricade(byte x, byte y, ushort plant, uint instanceID)
            {
                var buildable = BuildableDirectory.GetBuildable(instanceID, false);

                if (buildable == null)
                {
                    if (!BarricadeManager.tryGetRegion(x, y, plant, out var region))
                    {
                        return;
                    }

                    var data = region.barricades.FirstOrDefault(k => k.instanceID == instanceID);
                    var drop = region.drops.FirstOrDefault(k => k.instanceID == instanceID);

                    if (data == null || drop == null)
                    {
                        return;
                    }

                    buildable = new BarricadeBuildable(data, drop);
                }

                OnBuildableTransformed?.Invoke(buildable !);
            }
        internal void GenerateAndLoadAllClusters(bool loadSaveFile = true)
        {
            var stopwatch = Stopwatch.StartNew();

            var allBuildables = BuildableDirectory.GetBuildables(includePlants: true).ToList();

            Logging.Write(m_Plugin,
                          $"Loaded {allBuildables.Count} buildables from the map. Took {stopwatch.ElapsedMilliseconds}ms",
                          ConsoleColor.Cyan);

            foreach (var c in m_Clusters)
            {
                Return(c);
            }

            var successfulLoad = false;

            if (loadSaveFile && LevelSavedata.fileExists("/Bases.dat"))
            {
                successfulLoad = LoadClusters(allBuildables);
            }

            if (!successfulLoad)
            {
                Logging.Write(m_Plugin,
                              "Generating new clusters. This can take a LONG time. How long will depend on the following factors (but not limited to): CPU usage, CPU cores/threads, Buildables in the map. This generation only needs to be ran once from raw.");
                m_Clusters.AddRange(ClusterElements(allBuildables, true));
            }

            stopwatch.Stop();
            Logging.Write(m_Plugin,
                          $"Clusters Loaded: {Clusters.Count}. Took {stopwatch.ElapsedMilliseconds}ms.",
                          ConsoleColor.Cyan);

            OnClustersGenerated?.Invoke();
        }
Esempio n. 9
0
        public void Execute(IRocketPlayer caller, string[] command)
        {
            var cId  = caller.Id;
            var args = command.ToList();
            var baseClusteringPlugin = BaseClusteringPlugin.Instance;

            if (baseClusteringPlugin == null)
            {
                throw new NullReferenceException("BaseClusteringPlugin.Instance is null. Cannot execute command.");
            }

            if (args.Count == 0)
            {
                UnturnedChat.Say(caller, baseClusteringPlugin.Translate("not_enough_args"));
                return;
            }

            var abort = args.CheckArgsIncludeString("abort", out var index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var confirm = args.CheckArgsIncludeString("confirm", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var plants = args.CheckArgsIncludeString("v", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var barricades = args.CheckArgsIncludeString("b", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var structs = args.CheckArgsIncludeString("s", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var target = args.GetIRocketPlayer(out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var itemAssetInput = baseClusteringPlugin.Translate("not_available");
            var itemAssets     = args.GetMultipleItemAssets(out index);
            var assetCount     = itemAssets.Count;

            if (index > -1)
            {
                itemAssetInput = args[index];
                args.RemoveAt(index);
            }

            var radius = args.GetFloat(out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            if (abort)
            {
                if (m_WreckActions.TryGetValue(cId, out _))
                {
                    m_WreckActions.Remove(cId);
                    UnturnedChat.Say(caller, baseClusteringPlugin.Translate("action_cancelled"));
                    return;
                }

                UnturnedChat.Say(caller, baseClusteringPlugin.Translate("no_action_queued"));
                return;
            }

            if (confirm)
            {
                if (!m_WreckActions.TryGetValue(cId, out var action))
                {
                    UnturnedChat.Say(caller, baseClusteringPlugin.Translate("no_action_queued"));
                    return;
                }

                m_WreckActions.Remove(cId);

                var remove = BuildableDirectory.GetBuildables(includePlants: action.IncludeVehicles);

                if (action.TargetPlayer != null)
                {
                    remove = remove.Where(k => k.Owner.ToString().Equals(action.TargetPlayer.Id));
                }

                if (action.FilterForBarricades)
                {
                    remove = remove.Where(k => k.Asset is ItemBarricadeAsset);
                }
                else if (action.FilterForStructures)
                {
                    remove = remove.Where(k => k.Asset is ItemStructureAsset);
                }

                if (action.ItemAssets.Count > 0)
                {
                    remove = remove.Where(k => action.ItemAssets.Exists(l => k.AssetId == l.id));
                }

                if (!action.Center.IsNegativeInfinity())
                {
                    remove = remove.Where(k =>
                                          (k.Position - action.Center).sqrMagnitude <= Mathf.Pow(action.Radius, 2));
                }

                var buildables = remove.ToList();
                if (!buildables.Any())
                {
                    UnturnedChat.Say(caller, baseClusteringPlugin.Translate("cannot_wreck_no_builds"));
                    return;
                }

                foreach (var build in buildables)
                {
                    build.SafeDestroy();
                }

                UnturnedChat.Say(caller,
                                 baseClusteringPlugin.Translate("wrecked", buildables.Count, action.ItemAssetName,
                                                                !float.IsNegativeInfinity(action.Radius)
                            ? action.Radius.ToString(CultureInfo.CurrentCulture)
                            : baseClusteringPlugin.Translate("not_available"),
                                                                action.TargetPlayer != null
                            ? action.TargetPlayer.DisplayName
                            : baseClusteringPlugin.Translate("not_available"), action.IncludeVehicles,
                                                                action.FilterForBarricades, action.FilterForStructures));
                return;
            }

            var builds = BuildableDirectory.GetBuildables(includePlants: plants);

            if (target != null)
            {
                builds = builds.Where(k => k.Owner.ToString().Equals(target.Id));
            }

            if (barricades)
            {
                builds = builds.Where(k => k.Asset is ItemBarricadeAsset);
            }
            else if (structs)
            {
                builds = builds.Where(k => k.Asset is ItemStructureAsset);
            }

            if (assetCount > 0)
            {
                builds = builds.Where(k => itemAssets.Exists(l => k.AssetId == l.id));
            }

            var center = Vector3.negativeInfinity;

            if (!float.IsNegativeInfinity(radius))
            {
                if (!(caller is UnturnedPlayer cPlayer))
                {
                    UnturnedChat.Say(caller, baseClusteringPlugin.Translate("cannot_be_executed_from_console"));
                    return;
                }

                center = cPlayer.Position;
                builds = builds.Where(k => (k.Position - center).sqrMagnitude <= Mathf.Pow(radius, 2));
            }

            var itemAssetName = baseClusteringPlugin.Translate("not_available");

            if (assetCount == 1)
            {
                itemAssetName = itemAssets.First().itemName;
            }
            else if (assetCount > 1)
            {
                itemAssetName = itemAssetInput;
            }

            var count = builds.Count();

            if (count <= 0)
            {
                UnturnedChat.Say(caller, baseClusteringPlugin.Translate("cannot_wreck_no_builds"));
                return;
            }

            if (m_WreckActions.TryGetValue(cId, out _))
            {
                m_WreckActions[cId] = new WreckAction(plants, barricades, structs, target, center, itemAssets, radius,
                                                      itemAssetName);
                UnturnedChat.Say(caller,
                                 baseClusteringPlugin.Translate("wreck_action_queued_new", itemAssetName,
                                                                baseClusteringPlugin.Translate("not_available"),
                                                                !float.IsNegativeInfinity(radius)
                            ? radius.ToString(CultureInfo.CurrentCulture)
                            : baseClusteringPlugin.Translate("not_available"),
                                                                target != null ? target.DisplayName : baseClusteringPlugin.Translate("not_available"),
                                                                plants, barricades, structs, count));
            }
            else
            {
                m_WreckActions.Add(cId,
                                   new WreckAction(plants, barricades, structs, target, center, itemAssets, radius, itemAssetName));
                UnturnedChat.Say(caller,
                                 baseClusteringPlugin.Translate("wreck_action_queued", itemAssetName,
                                                                !float.IsNegativeInfinity(radius)
                            ? radius.ToString(CultureInfo.CurrentCulture)
                            : baseClusteringPlugin.Translate("not_available"),
                                                                target != null ? target.DisplayName : baseClusteringPlugin.Translate("not_available"),
                                                                plants, barricades, structs, count));
            }
        }
        public void Execute(IRocketPlayer caller, string[] command)
        {
            var pluginInstance = BaseClusteringPlugin.Instance;

            if (pluginInstance == null)
            {
                throw new NullReferenceException("BaseClusteringPlugin.Instance is null. Cannot execute command.");
            }

            if (!(caller is UnturnedPlayer player))
            {
                return;
            }

            var args = command.ToList();

            var barricades = args.CheckArgsIncludeString("b", out var index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var structs = args.CheckArgsIncludeString("s", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var plants = args.CheckArgsIncludeString("v", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var target = args.GetIRocketPlayer(out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var itemAssetInput = pluginInstance.Translate("not_available");
            var itemAssets     = args.GetMultipleItemAssets(out index);
            var assetCount     = itemAssets.Count;

            if (index > -1)
            {
                itemAssetInput = args[index];
                args.RemoveAt(index);
            }

            var builds = BuildableDirectory.GetBuildables(includePlants: plants);

            builds = target != null
                ? builds.Where(k => k.Owner.ToString().Equals(target.Id))
                : builds.Where(k => (k.Position - player.Position).sqrMagnitude > 400);

            if (barricades)
            {
                builds = builds.Where(k => k.Asset is ItemBarricadeAsset);
            }
            else if (structs)
            {
                builds = builds.Where(k => k.Asset is ItemStructureAsset);
            }

            if (assetCount > 0)
            {
                builds = builds.Where(k => itemAssets.Exists(l => l.id == k.AssetId));
            }

            var itemAssetName = pluginInstance.Translate("not_available");

            if (assetCount == 1)
            {
                itemAssetName = itemAssets.First().itemName;
            }
            else if (assetCount > 1)
            {
                itemAssetName = itemAssetInput;
            }

            var buildsL = builds.ToList();

            if (!buildsL.Any())
            {
                UnturnedChat.Say(caller,
                                 pluginInstance.Translate("cannot_teleport_no_builds", itemAssetName,
                                                          target != null ? target.DisplayName : pluginInstance.Translate("not_available"), plants,
                                                          barricades, structs));
                return;
            }

            var build = buildsL[Random.Range(0, buildsL.Count - 1)];

            if (build != null)
            {
                var offset = new Vector3(0, plants ? 4 : 2, 0);

                while (!player.Player.stance.wouldHaveHeightClearanceAtPosition(build.Position + offset, 0.5f))
                {
                    offset.y++;
                }

                player.Teleport(build.Position + offset, player.Rotation);
            }
            else
            {
                UnturnedChat.Say(caller,
                                 pluginInstance.Translate("cannot_teleport_builds_too_close", itemAssetName,
                                                          target != null ? target.DisplayName : pluginInstance.Translate("not_available"), plants,
                                                          barricades, structs));
            }
        }
 private void OnLevelLoaded(int level)
 {
     BuildableDirectory?.LevelLoaded();
     BaseClusterDirectory?.LevelLoaded();
     OnPluginFullyLoaded?.Invoke();
 }
        public void Execute(IRocketPlayer caller, string[] command)
        {
            var pluginInstance = BaseClusteringPlugin.Instance;

            if (pluginInstance == null)
            {
                throw new NullReferenceException("BaseClusteringPlugin.Instance is null. Cannot execute command.");
            }

            var args = command.ToList();

            var barricades = args.CheckArgsIncludeString("b", out var index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var structs = args.CheckArgsIncludeString("s", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var plants = args.CheckArgsIncludeString("v", out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var target = args.GetIRocketPlayer(out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var itemAssetInput = pluginInstance.Translate("not_available");
            var itemAssets     = args.GetMultipleItemAssets(out index);
            var assetCount     = itemAssets.Count;

            if (index > -1)
            {
                itemAssetInput = args[index];
                args.RemoveAt(index);
            }

            var radius = args.GetFloat(out index);

            if (index > -1)
            {
                args.RemoveAt(index);
            }

            var builds = BuildableDirectory.GetBuildables(includePlants: plants);

            if (target != null)
            {
                builds = builds.Where(k => k.Owner.ToString().Equals(target.Id));
            }

            if (barricades)
            {
                builds = builds.Where(k => k.Asset is ItemBarricadeAsset);
            }
            else if (structs)
            {
                builds = builds.Where(k => k.Asset is ItemStructureAsset);
            }

            if (assetCount > 0)
            {
                builds = builds.Where(k => itemAssets.Exists(l => k.AssetId == l.id));
            }

            if (!float.IsNegativeInfinity(radius))
            {
                if (!(caller is UnturnedPlayer cPlayer))
                {
                    UnturnedChat.Say(caller, pluginInstance.Translate("cannot_be_executed_from_console"));
                    return;
                }

                builds = builds.Where(k => (k.Position - cPlayer.Position).sqrMagnitude <= Mathf.Pow(radius, 2));
            }

            var itemAssetName = pluginInstance.Translate("not_available");

            if (assetCount == 1)
            {
                itemAssetName = itemAssets.First().itemName;
            }
            else if (assetCount > 1)
            {
                itemAssetName = itemAssetInput;
            }

            UnturnedChat.Say(caller,
                             pluginInstance.Translate("build_count", builds.Count(), itemAssetName,
                                                      !float.IsNegativeInfinity(radius)
                        ? radius.ToString(CultureInfo.CurrentCulture)
                        : pluginInstance.Translate("not_available"),
                                                      target != null ? target.DisplayName : pluginInstance.Translate("not_available"), plants, barricades,
                                                      structs));
        }