### Summary - Fixes `[AdvancedSearch` being accessible by players 😱 - Adds `[GenCommands` to generate the same commands html page on https://muo.gg/commands. - Fixes `[helpinfo` so all commands properly show up! > [!WARNING] > ### Developer Warning: > Commands must now be registered in the `Configure` bootup phase. > If a command is not registered early enough, it may not be available to systems like [helpinfo > that cache their information. > [!NOTE] > ### Developer Note: > Various commands related to generating content have been changed to _Developer_ and above access level. ### Screenshots <img width="673" alt="image" src="https://github.com/modernuo/ModernUO/assets/3953314/b105b5c9-5eb4-4ace-93ff-1bfb31e7132f"> <img width="547" alt="image" src="https://github.com/modernuo/ModernUO/assets/3953314/e97487e8-47a5-4aa7-89cc-9fe3deda584d">
158 lines
5.2 KiB
C#
158 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text.Json.Serialization;
|
|
using Server.Collections;
|
|
using Server.Items;
|
|
using Server.Json;
|
|
using Server.Network;
|
|
|
|
namespace Server.Commands
|
|
{
|
|
public struct TeleporterDefinition
|
|
{
|
|
[JsonPropertyName("src")]
|
|
public WorldLocation Source { get; set; }
|
|
|
|
[JsonPropertyName("dst")]
|
|
public WorldLocation Destination { get; set; }
|
|
|
|
[JsonPropertyName("back")]
|
|
public bool Back { get; set; }
|
|
|
|
public override string ToString() => $"{{{Source},{Destination},{Back}}}";
|
|
}
|
|
|
|
public static class GenTeleporter
|
|
{
|
|
private const int SuccessHue = 72, WarningHue = 53, ErrorHue = 33;
|
|
private static readonly string TeleporterJsonDataPath = Path.Combine(Core.BaseDirectory, "Data/teleporters.json");
|
|
|
|
public static void Configure()
|
|
{
|
|
CommandSystem.Register("TelGen", AccessLevel.Developer, GenTeleporter_OnCommand);
|
|
CommandSystem.Register("TelGenDelete", AccessLevel.Developer, TelGenDelete_OnCommand);
|
|
}
|
|
|
|
[Usage("TelGenDelete")]
|
|
[Description("Destroys world/dungeon teleporters for all facets.")]
|
|
public static void TelGenDelete_OnCommand(CommandEventArgs e)
|
|
{
|
|
var from = e.Mobile;
|
|
|
|
from.SendMessage("Removing teleporters, please wait.");
|
|
var count = 0;
|
|
|
|
void ProcessDeletion(TeleporterDefinition x)
|
|
{
|
|
count += TeleportersCreator.DeleteTeleporters(x.Source);
|
|
if (x.Back)
|
|
{
|
|
count += TeleportersCreator.DeleteTeleporters(x.Destination);
|
|
}
|
|
}
|
|
|
|
if (!ProcessTeleporterData(from, ProcessDeletion))
|
|
{
|
|
if (count > 0)
|
|
{
|
|
from.SendMessage(WarningHue, $"Partial Completion, {count} Teleporters Removed.");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
from.SendMessage(WarningHue, $"{count} Teleporters Removed.");
|
|
}
|
|
|
|
[Usage("TelGen")]
|
|
[Description("Generates world/dungeon teleporters for all facets.")]
|
|
public static void GenTeleporter_OnCommand(CommandEventArgs e)
|
|
{
|
|
var from = e.Mobile;
|
|
|
|
from.SendMessage("Generating teleporters, please wait.");
|
|
|
|
NetState.FlushAll();
|
|
|
|
var c = new TeleportersCreator();
|
|
|
|
if (!ProcessTeleporterData(from, c.CreateTeleporter))
|
|
{
|
|
if (c.DelCount > 0)
|
|
{
|
|
from.SendMessage(WarningHue, $"Partial Completion: {c.DelCount} Teleporters Removed.");
|
|
}
|
|
|
|
if (c.Count > 0)
|
|
{
|
|
from.SendMessage(WarningHue, $"Partial Completion: {c.Count} Teleporters Added.");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
from.SendMessage(SuccessHue, "Teleporter generating complete.");
|
|
from.SendMessage(WarningHue, $"{c.DelCount} Teleporters Removed.");
|
|
from.SendMessage(SuccessHue, $"{c.Count} Teleporters Added.");
|
|
}
|
|
|
|
private static bool ProcessTeleporterData(Mobile m, Action<TeleporterDefinition> processor)
|
|
{
|
|
try
|
|
{
|
|
JsonConfig.Deserialize<List<TeleporterDefinition>>(TeleporterJsonDataPath).ForEach(processor);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.ToString());
|
|
m.SendMessage(ErrorHue, $"Failed to load/process data file '{TeleporterJsonDataPath}'");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private class TeleportersCreator
|
|
{
|
|
public int Count { get; private set; }
|
|
public int DelCount { get; private set; }
|
|
|
|
private static bool IsWithinZ(int delta) => delta >= -12 && delta <= 12;
|
|
|
|
public static int DeleteTeleporters(WorldLocation worldLocation)
|
|
{
|
|
using var queue = PooledRefQueue<Item>.Create();
|
|
foreach (var item in worldLocation.Map.GetItemsAt<Teleporter>(worldLocation))
|
|
{
|
|
if (item is not (KeywordTeleporter or SkillTeleporter) && IsWithinZ(item.Z - worldLocation.Z))
|
|
{
|
|
queue.Enqueue(item);
|
|
}
|
|
}
|
|
|
|
var count = queue.Count;
|
|
while (queue.Count > 0)
|
|
{
|
|
queue.Dequeue().Delete();
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public void CreateTeleporter(TeleporterDefinition telDef)
|
|
{
|
|
DelCount += DeleteTeleporters(telDef.Source);
|
|
Count++;
|
|
new Teleporter(telDef.Destination, telDef.Destination.Map).MoveToWorld(telDef.Source, telDef.Source.Map);
|
|
if (!telDef.Back)
|
|
{
|
|
return;
|
|
}
|
|
|
|
DelCount += DeleteTeleporters(telDef.Destination);
|
|
Count++;
|
|
new Teleporter(telDef.Source, telDef.Source.Map).MoveToWorld(telDef.Destination, telDef.Destination.Map);
|
|
}
|
|
}
|
|
}
|
|
}
|