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(); }
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)); }