diff --git a/Plugin.sln b/Plugin.sln index af8293b70..888237a1d 100644 --- a/Plugin.sln +++ b/Plugin.sln @@ -232,7 +232,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DonotFuck", "src\DonotFuck\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lagrange.XocMat.Adapter", "src\Lagrange.XocMat.Adapter\Lagrange.XocMat.Adapter.csproj", "{AF5C3B5E-D8CD-4292-8047-EF129C839BB2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ItemBox", "src\ItemBox\ItemBox.csproj", "{F1C47139-1211-4951-B922-BBF4BCEE36FE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ItemBox", "src\ItemBox\ItemBox.csproj", "{F1C47139-1211-4951-B922-BBF4BCEE36FE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoAirItem", "src\AutoAirItem\AutoAirItem.csproj", "{E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1146,6 +1148,14 @@ Global {F1C47139-1211-4951-B922-BBF4BCEE36FE}.Release|Any CPU.Build.0 = Release|Any CPU {F1C47139-1211-4951-B922-BBF4BCEE36FE}.Release|x64.ActiveCfg = Release|Any CPU {F1C47139-1211-4951-B922-BBF4BCEE36FE}.Release|x64.Build.0 = Release|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Debug|x64.ActiveCfg = Debug|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Debug|x64.Build.0 = Debug|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Release|Any CPU.Build.0 = Release|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Release|x64.ActiveCfg = Release|Any CPU + {E08099EC-478F-4B1A-9EBF-9EA8A27C52C9}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 5ae45c28c..9363d00f1 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ | [AutoPluginManager](src/AutoPluginManager/README.md) | 一键自动更新插件 | 无 | | [AdditionalPylons](src/AdditionalPylons/README.md) | 放置更多晶塔 | 无 | | [AnnouncementBoxPlus](src/AnnouncementBoxPlus/README.md) | 广播盒功能强化 | 无 | +| [AutoAirItem](src/AutoAirItem/README.md) | 自动垃圾桶插件 | 无 | | [AutoBroadcast](src/AutoBroadcast/README.md) | 自动广播 | 无 | | [AutoClear](src/Autoclear/README.md) | 智能自动扫地 | 无 | | [AutoReset](src/AutoReset/README.md) | 完全自动重置 | 无 | diff --git a/README_en.md b/README_en.md index 0a63e79ff..d6e94fe39 100644 --- a/README_en.md +++ b/README_en.md @@ -61,6 +61,7 @@ | [AdditionalPylons](src/AdditionalPylons/README_EN.md) | Yes | Place more Pylons | No | | [AnnouncementBoxPlus](src/AnnouncementBoxPlus/README.md) | No | Enhance Broadcast Box Functionality | No | | [AutoBroadcast](src/AutoBroadcast/README_EN.md) | Yes | Automatic broadcast | No | +| [AutoAirItem](src/AutoAirItem/README_EN.md) | Yes | Automatic trash cans | No | | [AutoClear](src/Autoclear/README_EN.md) | Yes | Intelligent automatic cleaning | No | | [AutoReset](src/AutoReset/README_EN.md) | Yes | Fully automatic reset | No | | [AutoStoreItems](src/AutoStoreItems/README_EN.md) | Yes | Automatic storage | No | @@ -108,7 +109,7 @@ | [Economics.WeaponPlus](src/Economics.WeaponPlus/README.md) | No | Weapon enhancement | [EconomicsAPI](src/EconomicsAPI/README.md) | | [EconomicsAPI](src/EconomicsAPI/README.md) | No | Economic plugin prerequisite | No | | [EndureBoost](src/EndureBoost/README_EN.md) | Yes | Grant specified buff when the player has a certain number of items | No | -| [EssentialsPlus](src/EssentialsPlus/README.md) | No | Additional management commands | No | +| [EssentialsPlus](src/EssentialsPlus/README_EN.md) | Yes | Additional management commands | No | | [Ezperm](src/Ezperm/README.md) | No | Batch change permissions | No | | [FishShop](https://github.com/UnrealMultiple/TShockFishShop/blob/master/README.md) | No | Fish shop | No | | [GenerateMap](src/GenerateMap/README.md) | No | Generate map images | [CaiLib](src/CaiLib/README.md) | diff --git a/src/AutoAirItem/AutoAirItem.cs b/src/AutoAirItem/AutoAirItem.cs new file mode 100644 index 000000000..3b63ac9fd --- /dev/null +++ b/src/AutoAirItem/AutoAirItem.cs @@ -0,0 +1,209 @@ +using System.Text; +using Terraria; +using Terraria.ID; +using TerrariaApi.Server; +using TShockAPI; +using TShockAPI.Hooks; + +namespace AutoAirItem; + +[ApiVersion(2, 1)] +public class AutoAirItem : TerrariaPlugin +{ + #region 插件信息 + public override string Name => "自动垃圾桶"; + public override string Author => "羽学"; + public override Version Version => new Version(1, 1, 0); + public override string Description => "涡轮增压不蒸鸭"; + #endregion + + #region 注册与释放 + public AutoAirItem(Main game) : base(game) { } + internal static Configuration Config = new(); + internal static MyData data = new(); + public override void Initialize() + { + LoadConfig(); + GeneralHooks.ReloadEvent += LoadConfig; + ServerApi.Hooks.GameUpdate.Register(this, this.OnGameUpdate); + ServerApi.Hooks.ServerJoin.Register(this, OnJoin); + ServerApi.Hooks.ServerLeave.Register(this, OnLeave); + TShockAPI.Commands.ChatCommands.Add(new Command("AutoAir.use", Commands.AirCmd, "air", "垃圾")); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + GeneralHooks.ReloadEvent -= LoadConfig; + ServerApi.Hooks.GameUpdate.Deregister(this, this.OnGameUpdate); + ServerApi.Hooks.ServerJoin.Deregister(this, OnJoin); + ServerApi.Hooks.ServerLeave.Deregister(this, OnLeave); + TShockAPI.Commands.ChatCommands.RemoveAll(x => x.CommandDelegate == Commands.AirCmd); + } + base.Dispose(disposing); + } + #endregion + + #region 配置重载读取与写入方法 + private static void LoadConfig(ReloadEventArgs args = null!) + { + Config = Configuration.Read(); + Config.Write(); + TShock.Log.ConsoleInfo(GetString("[自动垃圾桶]重新加载配置完毕。")); + } + #endregion + + #region 玩家更新配置方法(计入记录时间并创建配置结构) + private void OnJoin(JoinEventArgs args) + { + var plr = TShock.Players[args.Who]; + var list = data.Items.FirstOrDefault(x => x.Name == plr.Name); + + if (!Config.Open) + { + return; + } + + //不是数据表里玩家则给他自动创建数据 + if (!data.Items.Any(item => item.Name == plr.Name)) + { + data.Items.Add(new MyData.ItemData() + { + Name = plr.Name, + Enabled = true, + IsActive = true, + Auto = true, + LogTime = DateTime.Now, + Mess = true, + ItemName = new List() + }); + } + else + { + list!.LogTime = DateTime.Now; + list.IsActive = true; + } + } + #endregion + + #region 玩家离开服务器更新记录时间,横比所有玩家的记录时间,如超过清理周期,则自动删除玩家数据 + private static int ClearCount = 0; //需要清理的玩家计数 + private void OnLeave(LeaveEventArgs args) + { + var plr = TShock.Players[args.Who]; + var list = data.Items.FirstOrDefault(x => x.Name == plr.Name); + + if (!Config.Open) + { + return; + } + + //离开服务器更新记录时间与活跃状态 + if (data.Items.Any(item => item.Name == plr.Name)) + { + list!.LogTime = DateTime.Now; + list.IsActive = false; + } + + if (Config.ClearData) + { + var Remove = data.Items.Where(list => list.LogTime != default && + (DateTime.Now - list.LogTime).TotalHours >= Config.timer).ToList(); + + //数据清理的播报内容 + var mess = new StringBuilder(); + mess.AppendLine(GetString($"[i:3455][c/AD89D5:自][c/D68ACA:动][c/DF909A:垃][c/E5A894:圾][c/E5BE94:桶][i:3454]")); + mess.AppendLine(GetString($"以下玩家 与 [c/ABD6C7:{plr.Name}] 离开时间\n【[c/A1D4C2:{DateTime.Now}]】\n") + + GetString($"超过 [c/E17D8C:{Config.timer}] 小时 已清理 [c/76D5B4:自动垃圾桶] 数据:")); + + foreach (var plr2 in Remove) + { + //只显示小时数 F0整数 F1保留1位小数 F2保留2位 如:24.01小时 + var hours = (DateTime.Now - plr2.LogTime).TotalHours; + FormattableString Hours = $"{hours:F0}"; + + //更新时间超过Config预设的时间,并该玩家更新状态为false则添加计数并移除数据 + if (hours >= Config.timer && !plr2.IsActive) + { + ClearCount++; + mess.AppendFormat(GetString("[c/A7DDF0:{0}]:[c/74F3C9:{1}小时], "), plr2.Name, Hours); + data.Items.Remove(plr2); + } + } + + //确保有一个玩家计数,只播报一次 + if (ClearCount > 0 && mess.Length > 0) + { + //广告开关 + if (Config.Enabled) + { + //自定义广告内容 + mess.AppendLine(Config.Advertisement); + } + + TShock.Utils.Broadcast(mess.ToString(), 247, 244, 150); + ClearCount = 0; + } + } + } + #endregion + + #region 触发自动垃圾桶 + public static long Timer = 0L; + private void OnGameUpdate(EventArgs args) + { + Timer++; + + if (!Config.Open) + { + return; + } + + foreach (var plr in TShock.Players.Where(plr => plr != null && plr.Active && plr.IsLoggedIn)) + { + var list = data.Items.FirstOrDefault(x => x.Name == plr.Name); + if (list != null && list.Enabled && Timer % Config.UpdateRate == 0) + { + AutoAirItems(plr, list.ItemName, list.Auto, list.Mess); + } + } + } + #endregion + + #region 自动清理物品方法 + public static bool AutoAirItems(TSPlayer player, List List, bool Auto, bool mess) + { + var plr = player.TPlayer; + + for (int i = 0; i < plr.inventory.Length; i++) + { + var item = plr.inventory[i]; + var id = TShock.Utils.GetItemById(item.type).netID; + + if (Auto) + { + if (!plr.trashItem.IsAir && !List.Contains(plr.trashItem.Name)) + { + List.Add(plr.trashItem.Name); + player.SendMessage(GetString($"已将 '[c/92C5EC:{plr.trashItem.Name}]'添加到自动垃圾桶|指令菜单:[c/A1D4C2:/air]"), 255, 246, 158); + } + } + + if (item != null && List.Contains(item.Name) && item.Name != plr.inventory[plr.selectedItem].Name) + { + item.TurnToAir(); + player.SendData(PacketTypes.PlayerSlot, null, player.Index, PlayerItemSlotID.Inventory0 + i); + + if (mess) + { + var itemName = Lang.GetItemNameValue(id); + player.SendMessage(GetString($"【自动垃圾桶】已将 '[c/92C5EC:{itemName}]'从您的背包中移除"), 255, 246, 158); + } + return true; + } + } + return false; + } + #endregion +} diff --git a/src/AutoAirItem/AutoAirItem.csproj b/src/AutoAirItem/AutoAirItem.csproj new file mode 100644 index 000000000..f489ab64e --- /dev/null +++ b/src/AutoAirItem/AutoAirItem.csproj @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/AutoAirItem/Commands.cs b/src/AutoAirItem/Commands.cs new file mode 100644 index 000000000..7c1da9ae1 --- /dev/null +++ b/src/AutoAirItem/Commands.cs @@ -0,0 +1,164 @@ +using Microsoft.Xna.Framework; +using Terraria; +using TShockAPI; + +namespace AutoAirItem; + +public class Commands +{ + public static void AirCmd(CommandArgs args) + { + var name = args.Player.Name; + var data = AutoAirItem.data.Items.FirstOrDefault(item => item.Name == name); + + if (!AutoAirItem.Config.Open) + { + return; + } + + if (data == null) + { + args.Player.SendInfoMessage(GetString("请用角色[c/D95065:重进服务器]后输入:/air 指令查看菜单\n羽学声明:本插件纯属[c/7E93DE:免费]请勿上当受骗"), 217,217,217); + return; + } + + if (args.Parameters.Count == 0) + { + HelpCmd(args.Player); + if (!data.Enabled) + { + args.Player.SendSuccessMessage(GetString($"请输入该指令开启→: [c/92C5EC:/air on] ")); + } + else + { + args.Player.SendSuccessMessage(GetString($"您的垃圾桶监听状态为:[c/92C5EC:{data.Auto}]")); + args.Player.SendSuccessMessage(GetString($"输入指令切换自动模式:[c/92C5EC:/air auto]")); + } + return; + } + + if (args.Parameters.Count == 1 && args.Parameters[0].ToLower() == "list") + { + args.Player.SendInfoMessage(GetString($"[{data.Name}的垃圾桶]\n") + string.Join(", ", data.ItemName.Select(x => "[c/92C5EC:{0}]".SFormat(x)))); + return; + } + + if (args.Parameters.Count == 1 && args.Parameters[0].ToLower() == "on") + { + var isEnabled = data.Enabled; + data.Enabled = !isEnabled; + var Mess = isEnabled ? GetString("禁用") : GetString("启用"); + args.Player.SendSuccessMessage(GetString($"玩家 [{args.Player.Name}] 已[c/92C5EC:{Mess}]自动垃圾桶功能。")); + return; + } + + if (args.Parameters.Count == 1 && args.Parameters[0].ToLower() == "clear") + { + data.ItemName.Clear(); + args.Player.SendSuccessMessage(GetString($"已清理[c/92C5EC: {args.Player.Name} ]的自动垃圾桶表")); + return; + } + + if (args.Parameters.Count == 1 && args.Parameters[0].ToLower() == "yes") + { + data.ItemName.Add(args.TPlayer.inventory[args.TPlayer.selectedItem].Name); + args.Player.SendSuccessMessage(GetString("手选物品 [c/92C5EC:{0}] 已加入自动垃圾桶中! 脱手即清!"), args.TPlayer.inventory[args.TPlayer.selectedItem].Name); + return; + } + + if (args.Parameters.Count == 1 && args.Parameters[0].ToLower() == "auto") + { + var isEnabled = data.Auto; + data.Auto = !isEnabled; + var Mess = isEnabled ? GetString("禁用") : GetString("启用"); + args.Player.SendSuccessMessage(GetString($"玩家 [{args.Player.Name}] 的垃圾桶位格监听功能已[c/92C5EC:{Mess}]")); + return; + } + + if (args.Parameters.Count == 1 && args.Parameters[0].ToLower() == "mess") + { + var isEnabled = data.Mess; + data.Mess = !isEnabled; + var Mess = isEnabled ? GetString("禁用") : GetString("启用"); + args.Player.SendSuccessMessage(GetString($"玩家 [{args.Player.Name}] 的自动清理消息已[c/92C5EC:{Mess}]")); + return; + } + + if (args.Parameters.Count == 2) + { + Item item; + List Items = TShock.Utils.GetItemByIdOrName(args.Parameters[1]); + if (Items.Count > 1) + { + args.Player.SendMultipleMatchError(Items.Select(i => i.Name)); + return; + } + + if (Items.Count == 0) + { + args.Player.SendErrorMessage(GetString("不存在该物品,\"物品查询\": \"[c/92C5EC:https://terraria.wiki.gg/zh/wiki/Item_IDs]\"")); + return; + } + + else + { + item = Items[0]; + } + + switch (args.Parameters[0].ToLower()) + { + case "add": + { + if (data.ItemName.Contains(item.Name)) + { + args.Player.SendErrorMessage(GetString("物品 [c/92C5EC:{0}] 已在垃圾桶中!"), item.Name); + return; + } + data.ItemName.Add(item.Name); + args.Player.SendSuccessMessage(GetString("已成功将物品添加到垃圾桶: [c/92C5EC:{0}]!"), item.Name); + break; + } + case "delete": + case "del": + case "remove": + { + if (!data.ItemName.Contains(item.Name)) + { + args.Player.SendErrorMessage(GetString("物品 {0} 不在垃圾桶中!"), item.Name); + return; + } + data.ItemName.Remove(item.Name); + args.Player.SendSuccessMessage(GetString("已成功从垃圾桶删除物品: [c/92C5EC:{0}]!"), item.Name); + break; + } + + default: + { + HelpCmd(args.Player); + break; + } + } + } + } + + #region 菜单方法 + private static void HelpCmd(TSPlayer player) + { + if (player == null) return; + else + { + player.SendMessage(GetString("【自动垃圾桶】指令菜单\n") + + GetString("/air —— 查看垃圾桶菜单\n") + + GetString("/air on —— 开启|关闭垃圾桶功能\n") + + GetString("/air list —— 列出自己的垃圾桶\n") + + GetString("/air clear —— 清理垃圾桶\n") + + GetString("/air yes —— 将手持物品加入垃圾桶\n") + + GetString("/air auto —— 监听垃圾桶位格开关\n") + + GetString("/air mess —— 开启|关闭清理消息\n") + + GetString("/air add 或 del 物品名字 —— 添加|删除《自动垃圾桶》的物品"), Color.AntiqueWhite); + } + } + #endregion + + +} diff --git a/src/AutoAirItem/Configuration.cs b/src/AutoAirItem/Configuration.cs new file mode 100644 index 000000000..3c401661d --- /dev/null +++ b/src/AutoAirItem/Configuration.cs @@ -0,0 +1,61 @@ +using Newtonsoft.Json; +using TShockAPI; + +namespace AutoAirItem; + +internal class Configuration +{ + #region 实例变量 + [JsonProperty("插件指令权限", Order = -16)] + public string Text { get; set; } = "指令菜单:/air 或 /垃圾,权限名【AutoAir.use】,给玩家权限:/group addperm default AutoAir.use"; + + [JsonProperty("使用说明", Order = -15)] + public string Text2 { get; set; } = "玩家每次进出服都会更新【记录时间】,玩家A离线时间与玩家B登录时间相差超过【清理周期】所设定的时间,则自动清理该玩家A的数据"; + + [JsonProperty("插件开关", Order = -14)] + public bool Open { get; set; } = true; + + [JsonProperty("清理垃圾速度", Order = -2)] + public int UpdateRate = 10; + + [JsonProperty("广告开关", Order = -1)] + public bool Enabled { get; set; } = true; + + [JsonProperty("广告内容", Order = -1)] + public string Advertisement { get; set; } = $"\n[i:3456][C/F2F2C7:插件开发] [C/BFDFEA:by] [c/00FFFF:羽学][i:3459]"; + + [JsonProperty("是否清理数据", Order = 1)] + public bool ClearData { get; set; } = true; + + [JsonProperty("清理数据周期/小时", Order = 2)] + public long timer { get; set; } = 24; + + + #endregion + + #region 读取与创建配置文件方法 + public static readonly string FilePath = Path.Combine(TShock.SavePath, "自动垃圾桶.json"); + + public void Write() + { + var json = JsonConvert.SerializeObject(this, Formatting.Indented); + File.WriteAllText(FilePath, json); + } + + public static Configuration Read() + { + if (!File.Exists(FilePath)) + { + var NewConfig = new Configuration(); + new Configuration().Write(); + return NewConfig; + } + else + { + var jsonContent = File.ReadAllText(FilePath); + return JsonConvert.DeserializeObject(jsonContent)!; + } + } + #endregion + +} \ No newline at end of file diff --git a/src/AutoAirItem/MyData.cs b/src/AutoAirItem/MyData.cs new file mode 100644 index 000000000..71a79f2fb --- /dev/null +++ b/src/AutoAirItem/MyData.cs @@ -0,0 +1,44 @@ +namespace AutoAirItem; + +public class MyData +{ + //玩家数据表 + public List Items { get; set; } = new List(); + + #region 数据结构 + public class ItemData + { + //玩家名字 + public string Name { get; set; } + + public bool IsActive { get; set; } + + //玩家出入服务器的记录时间 + public DateTime LogTime { get; set; } + + //玩家自己的垃圾桶开关 + public bool Enabled { get; set; } = false; + + //监听垃圾桶位格开关 + public bool Auto { get; set; } = false; + + //垃圾桶的回收提示 + public bool Mess { get; set; } = true; + + //垃圾桶表 + public List ItemName { get; set; } + + public ItemData(string name = "",bool Active = true, bool enabled = true, bool auto = true, bool mess = true, DateTime time = default, List item = null!) + { + this.Name = name ?? ""; + this.IsActive = Active; + this.Enabled = enabled; + this.LogTime = time; + this.Auto = auto; + this.Mess = mess; + this.ItemName = item ?? new List(); + } + } + + #endregion +} diff --git a/src/AutoAirItem/README.md b/src/AutoAirItem/README.md new file mode 100644 index 000000000..46a01febe --- /dev/null +++ b/src/AutoAirItem/README.md @@ -0,0 +1,91 @@ +# AutoAirItem 自动垃圾桶插件 + +- 作者: 羽学 +- 出处: 无 +- Tshock版自动垃圾桶,帮助玩家清理自身垃圾的小插件 +- 由玩家使用指令独立运行的插件,无需服主写配置, +- 它会自动根据玩家加入服务器自动创建配置结构。 +- 通过玩家指令交互的一款全自动插件。 + +## 更新日志 +``` +v1.1.0 +将数据表内容从Config移到插件内部的MyData类里, +不再以来对配置文件的频繁写入,避免玩家太多时把Config写爆。 +第一次进服自动开启垃圾桶功能,并在玩家把物品放到垃圾桶时会触发相关指令提示 +加入了对玩家在线状态判断,避免人在服里玩了24小时导致无辜被清理数据。 +加入了对清理哪些玩家数据时的离服播报 + + +v1.0.2 +加入了将手持物品加入垃圾桶指令:/air yes +未选中后才会清理,选中时哪怕输错了,也可以用/air del 物品名 移除 +加入了开启关闭清理信息指令:/air mess +加入了监听玩家垃圾桶位格功能,当物品放入垃圾桶时自动添加到《垃圾桶表》处理 + +v1.0.1 +移除了每次/air add 或 del时的插件启用状态提醒 +加入【清理数据周期】逻辑: +玩家每次进出服都会更新【记录时间】, +玩家A离线时间与玩家B登录时间相差 +超过【清理周期】所设定的时间,则自动清理该玩家A的数据 +如果《清理数据周期》:设置超过9999999999小时,就相当于永远不清理数据了 + +v1.0.0 +根据使用Mod《更好的体验》的想法,实现的一个Tshock版自动垃圾桶 +清理垃圾速度单位为帧率,数值越小清理越快。 +使用指令/air on开启插件 +使用/air add 物品名 或 物品id 或 Alt+左键点选物品,自动将物品名写入到配置文件当中 +根据玩家进服事件自动创建 "玩家数据表", +"垃圾桶物品"存在物品且开启了"垃圾桶开关"时会主动触发清理逻辑 +配备了"登录时间"用于给服主参考:是否需要自己手动移除该玩家的数据 +``` + +## 指令 + +| 语法 | 别名 | 权限 | 说明 | +| -------------------------------- | :---: | :--------------: | :--------------------------------------: | +| /air | /垃圾 | AutoAir.use | 指令菜单 | +| /air on | /垃圾 on | AutoAir.use | 开启或关闭自身的垃圾桶功能 | +| /air list | /垃圾 list | AutoAir.use | 列出自己的垃圾桶物品名 | +| /air clear | /垃圾 clear | AutoAir.use | 清空自己的垃圾桶表 | +| /air yes | /垃圾 yes | AutoAir.use | 手持物品加入垃圾桶表 | +| /air auto | /垃圾 auto | AutoAir.use | 将物品放入垃圾桶位格时自动添加垃圾桶表 | +| /air mess | /垃圾 mess | AutoAir.use | 开启或关闭清理消息 | +| /air add 或 del id | /垃圾 add 或 del 物品名| AutoAir.use | 添加或移除自己的垃圾桶物品 | + +--- +注意事项 +--- +1.`如何给玩家添加权限`请使用该指令在控制台发送: `/group addperm default AutoAir.use` + +2.`垃圾桶开关`与`垃圾桶物品`和均由玩家游戏内指令触发! + +3.`玩家数据表`由玩家加入服务器后`自动写入`,假设存在同名玩家,则会更新该玩家的`记录时间`(离线也会更新一次记录时间) + +4.`清理垃圾速度`的单位为帧率,数值越小清理`速度越快`。 + +5.`清理数据周期` 玩家A`离线时间为00:00`,玩家B`登录时间为00:10`,`清理周期为10小时` 玩家A未能在`10:10之前`登录游戏,`当玩家B离开`就会`清空玩家A`的自动垃圾桶数据 + +6.`清理数据周期`如果设置超过`9999999999小时`就相当于永远不清理数据了 + +7.`监听垃圾桶`使用指令`/air auto`开启,当垃圾桶位格放入物品时自动添加垃圾桶表内 + +## 配置 + +```json +{ + "插件指令权限": "指令菜单:/air 或 /垃圾,权限名【AutoAir.use】,给玩家权限:/group addperm default AutoAir.use", + "使用说明": "玩家每次进出服都会更新【记录时间】,玩家A离线时间与玩家B登录时间相差超过【清理周期】所设定的时间,则自动清理该玩家A的数据", + "插件开关": true, + "清理垃圾速度": 60, + "广告开关": true, + "广告内容": "[i:3456][C/F2F2C7:插件开发] [C/BFDFEA:by] [c/00FFFF:羽学][i:3459]", + "是否清理数据": true, + "清理数据周期/小时": 24 +} +``` +## 反馈 +- 优先发issued -> 共同维护的插件库:https://github.com/UnrealMultiple/TShockPlugin +- 次优先:TShock官方群:816771079 +- 大概率看不到但是也可以:国内社区trhub.cn ,bbstr.net , tr.monika.love \ No newline at end of file diff --git a/src/AutoAirItem/README_EN.md b/src/AutoAirItem/README_EN.md new file mode 100644 index 000000000..db7291b92 --- /dev/null +++ b/src/AutoAirItem/README_EN.md @@ -0,0 +1,61 @@ +# AutoAirItem + +- Authors: 羽学 +- Source: 无 +- TShock version of the Auto Trash Can, a small plugin to help players clean up their trash. +- A plugin that is independently run by players using commands, without the need for server administrators to write configurations. +- It automatically creates the configuration structure when a player joins the server. +- A fully automated plugin that interacts with players through commands. + + +## Commands + +| Syntax | Alias | Permission | Description | +| ---------------------------------- | :----: | :-------------------: | :---------------------------------------------: | +| /air | /垃圾 | AutoAir.use | Command menu | +| /air on | /垃圾 on | AutoAir.use | Enable or disable personal trash can feature | +| /air list | /垃圾 list | AutoAir.use | List items in personal trash can | +| /air clear | /垃圾 clear | AutoAir.use | Clear personal trash can list | +| /air yes | /垃圾 yes | AutoAir.use | Add held item to personal trash can list | +| /air auto | /垃圾 auto | AutoAir.use | Automatically add items to trash can when placed in the designated slot | +| /air mess | /垃圾 mess | AutoAir.use | Enable or disable cleanup messages | +| /air add or del id | /垃圾 add or del 物品名 | AutoAir.use | Add or remove items from personal trash can list | + + +--- +Notes +--- + +1. To give players permission, use this command in the console: `/group addperm default AutoAir.use`. + +2. The "Trash Bin Toggle" and "Trash Bin Items" are both triggered by in-game player commands! + +3. The "Player Data Table" is automatically updated when a player joins the server. If a player with the same name exists, their "record time" will be updated (it will also update once when they are offline). + +4. The unit for "Trash Cleanup Speed" is the frame rate. The smaller the value, the "faster" the cleanup speed. + +5. "Data Cleanup Cycle": If Player A logs out at 00:00 and Player B logs in at 00:10, with a "cleanup cycle of 10 hours," if Player A does not log back in by 10:10, Player A's auto-trash data will be cleared "when Player B logs off." + +6. If the "Data Cleanup Cycle" is set to more than "9999999999 hours," it is equivalent to never clearing the data. + +7. To "Monitor Trash Bin," use the command `/air auto` to enable auto-monitoring. Items placed in the trash bin slot will automatically be added to the trash bin table. + +## Config +> Configuration file location:tshock/自动垃圾桶.json +```json +{ + "插件指令权限": "指令菜单:/air 或 /垃圾,权限名【AutoAir.use】,给玩家权限:/group addperm default AutoAir.use", // Command permissions for the plugin, allowing players to use /air or /trash commands with the AutoAir.use permission + "使用说明": "玩家每次进出服都会更新【记录时间】,玩家A离线时间与玩家B登录时间相差超过【清理周期】所设定的时间,则自动清理该玩家A的数据", // Description of how the plugin works: player record time is updated on join/leave, and data is cleared if the time between Player A logging out and Player B logging in exceeds the set cleanup cycle + "插件开关": true, // Toggle to enable or disable the plugin + "清理垃圾速度": 60, // Speed of trash cleanup, lower values mean faster cleanup + "广告开关": true, // Toggle to enable or disable advertisements + "广告内容": "[i:3456][C/F2F2C7:插件开发] [C/BFDFEA:by] [c/00FFFF:羽学][i:3459]", // Content of the advertisement message + "是否清理数据": true, // Whether or not to clean up player data + "清理数据周期/小时": 24 // The data cleanup cycle in hours +} + +``` +## FeedBack +- Github Issue -> TShockPlugin Repo: https://github.com/UnrealMultiple/TShockPlugin +- TShock QQ Group: 816771079 +- China Terraria Forum: trhub.cn, bbstr.net, tr.monika.love \ No newline at end of file diff --git a/src/AutoAirItem/i18n/en_US.po b/src/AutoAirItem/i18n/en_US.po new file mode 100644 index 000000000..d35011684 --- /dev/null +++ b/src/AutoAirItem/i18n/en_US.po @@ -0,0 +1,190 @@ +msgid "" +msgstr "" +"Project-Id-Version: AutoAirItem\n" +"POT-Creation-Date: 2024-10-23 21:18:29+0800\n" +"PO-Revision-Date: 2024-10-23 21:38+0800\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4.4\n" + +#: ..\..\Commands.cs:42 +#, csharp-format +msgid "[{0}的垃圾桶]\n" +msgstr "[{0}'s Trash Bin]\n" + +#: ..\..\AutoAirItem.cs:53 +msgid "[自动垃圾桶]重新加载配置完毕。" +msgstr "[Auto Air Item] Reload configuration completed。" + +#: ..\..\AutoAirItem.cs:130 +msgid "[c/A7DDF0:{0}]:[c/74F3C9:{1}小时], " +msgstr "[c/A7DDF0:{0}]: [c/74F3C9:{1} hours], " + +#: ..\..\AutoAirItem.cs:116 +msgid "" +"[i:3455][c/AD89D5:自][c/D68ACA:动][c/DF909A:垃][c/E5A894:圾][c/" +"E5BE94:桶][i:3454]" +msgstr "[i:3455]AutoAirItem[i:3454]" + +#: ..\..\AutoAirItem.cs:201 +#, csharp-format +msgid "【自动垃圾桶】已将 '[c/92C5EC:{0}]'从您的背包中移除" +msgstr "" +"【AutoAirItem】has removed '[c/92C5EC:{0}]' from your backpack" + +#: ..\..\Commands.cs:150 +msgid "【自动垃圾桶】指令菜单\n" +msgstr "【AutoAirItem】Help\n" + +#: ..\..\Commands.cs:151 +msgid "/air —— 查看垃圾桶菜单\n" +msgstr "/air —— AutoAirItem Help\n" + +#: ..\..\Commands.cs:158 +msgid "/air add 或 del 物品名字 —— 添加|删除《自动垃圾桶》的物品" +msgstr "" +"/air add or del item name —— Add|Remove items from the Auto " +"Trash List" + +#: ..\..\Commands.cs:156 +msgid "/air auto —— 监听垃圾桶位格开关\n" +msgstr "/air auto —— Toggle Auto Trash Bin listening\n" + +#: ..\..\Commands.cs:154 +msgid "/air clear —— 清理垃圾桶\n" +msgstr "/air clear —— Clear Trash List\n" + +#: ..\..\Commands.cs:153 +msgid "/air list —— 列出自己的垃圾桶\n" +msgstr "/air list —— List your own trash bin items\n" + +#: ..\..\Commands.cs:157 +msgid "/air mess —— 开启|关闭清理消息\n" +msgstr "/air mess —— Toggle cleaning messages\n" + +#: ..\..\Commands.cs:152 +msgid "/air on —— 开启|关闭垃圾桶功能\n" +msgstr "/air on —— Toggle trash bin function\n" + +#: ..\..\Commands.cs:155 +msgid "/air yes —— 将手持物品加入垃圾桶\n" +msgstr "/air yes —— Add held item to the Trash\n" + +#: ..\..\Commands.cs:99 +msgid "" +"不存在该物品,\"物品查询\": \"[c/92C5EC:https://terraria.wiki." +"gg/zh/wiki/Item_IDs]\"" +msgstr "" +"The item does not exist, \"item lookup\": \"[c/92C5EC:https://" +"terraria.wiki.gg/wiki/Item_IDs]\"" + +#: ..\..\AutoAirItem.cs:118 +#, csharp-format +msgid "" +"超过 [c/E17D8C:{0}] 小时 已清理 [c/76D5B4:自动垃圾桶] 数据:" +msgstr "" +"Exceeded [c/E17D8C:{0}] hours, cleaned [c/76D5B4:AutoAirItem] " +"data:" + +#: ..\..\Commands.cs:50 ..\..\Commands.cs:73 ..\..\Commands.cs:82 +msgid "禁用" +msgstr "False" + +#: ..\..\Commands.cs:34 +#, csharp-format +msgid "您的垃圾桶监听状态为:[c/92C5EC:{0}]" +msgstr "Your trash bin listening status is: [c/92C5EC:{0}]" + +#: ..\..\Commands.cs:50 ..\..\Commands.cs:73 ..\..\Commands.cs:82 +msgid "启用" +msgstr "True" + +#: ..\..\Commands.cs:30 +msgid "请输入该指令开启→: [c/92C5EC:/air on] " +msgstr "" +"Please enter the command to enable →: [c/92C5EC:/air on] " + +#: ..\..\Commands.cs:21 +msgid "" +"请用角色[c/D95065:重进服务器]后输入:/air 指令查看菜单\n" +"羽学声明:本插件纯属[c/7E93DE:免费]请勿上当受骗" +msgstr "" +"Please use the character [c/D95065:re-enter the server] and " +"then enter: /air to view the menu.\n" +"Yu Xue statement: This plugin is purely [c/7E93DE:free]; do " +"not be deceived" + +#: ..\..\Commands.cs:65 +msgid "手选物品 [c/92C5EC:{0}] 已加入自动垃圾桶中! 脱手即清!" +msgstr "" +"The manually selected item [c/92C5EC:{0}] has been added to " +"the Auto Trash Bin! It will be cleared upon release!" + +#: ..\..\Commands.cs:35 +msgid "输入指令切换自动模式:[c/92C5EC:/air auto]" +msgstr "" +"Enter the command to toggle auto mode: [c/92C5EC:/air auto]" + +#: ..\..\Commands.cs:74 +#, csharp-format +msgid "玩家 [{0}] 的垃圾桶位格监听功能已[c/92C5EC:{1}]" +msgstr "" +"Player [{0}]'s trash bin slot listening function has been " +"[c/92C5EC:{1}]" + +#: ..\..\Commands.cs:83 +#, csharp-format +msgid "玩家 [{0}] 的自动清理消息已[c/92C5EC:{1}]" +msgstr "" +"Player [{0}]'s auto cleanup messages have been [c/92C5EC:{1}]" + +#: ..\..\Commands.cs:51 +#, csharp-format +msgid "玩家 [{0}] 已[c/92C5EC:{1}]自动垃圾桶功能。" +msgstr "" +"Player [{0}] has [c/92C5EC:{1}] the Auto Trash Bin function。" + +#: ..\..\Commands.cs:114 +msgid "物品 [c/92C5EC:{0}] 已在垃圾桶中!" +msgstr "Item [c/92C5EC:{0}] is now in the trash bin!" + +#: ..\..\Commands.cs:127 +msgid "物品 {0} 不在垃圾桶中!" +msgstr "Item {0} is not in the trash bin!" + +#: ..\..\Commands.cs:131 +msgid "已成功从垃圾桶删除物品: [c/92C5EC:{0}]!" +msgstr "" +"Item [c/92C5EC:{0}] has been successfully deleted from the " +"Trash!" + +#: ..\..\Commands.cs:118 +msgid "已成功将物品添加到垃圾桶: [c/92C5EC:{0}]!" +msgstr "" +"Item [c/92C5EC:{0}] has been successfully added to the Trash!" + +#: ..\..\AutoAirItem.cs:189 +#, csharp-format +msgid "" +"已将 '[c/92C5EC:{0}]'添加到自动垃圾桶|指令菜单:[c/A1D4C2:/air]" +msgstr "" +"Item [c/92C5EC:{0}] has been added to the Auto Trash | Command " +"Help: [c/A1D4C2:/air]" + +#: ..\..\Commands.cs:58 +#, csharp-format +msgid "已清理[c/92C5EC: {0} ]的自动垃圾桶表" +msgstr "The Auto Trash list for [c/92C5EC: {0}] has been cleaned" + +#: ..\..\AutoAirItem.cs:117 +#, csharp-format +msgid "" +"以下玩家 与 [c/ABD6C7:{0}] 离开时间\n" +"【[c/A1D4C2:{1}]】\n" +msgstr "" +"The following players have left with [c/ABD6C7:{0}] at time\n" +"【[c/A1D4C2:{1}]】\n" diff --git a/src/AutoAirItem/i18n/template.pot b/src/AutoAirItem/i18n/template.pot new file mode 100644 index 000000000..ec17155c5 --- /dev/null +++ b/src/AutoAirItem/i18n/template.pot @@ -0,0 +1,173 @@ +msgid "" +msgstr "" +"Project-Id-Version: AutoAirItem\n" +"POT-Creation-Date: 2024-10-23 21:18:29+0800\n" +"PO-Revision-Date: 2024-10-23 21:18:29+0800\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: GetText.NET Extractor\n" + +#: ..\..\Commands.cs:42 +#, csharp-format +msgid "" +"[{0}的垃圾桶]\n" +msgstr "" + +#: ..\..\AutoAirItem.cs:53 +msgid "[自动垃圾桶]重新加载配置完毕。" +msgstr "" + +#: ..\..\AutoAirItem.cs:130 +msgid "[c/A7DDF0:{0}]:[c/74F3C9:{1}小时], " +msgstr "" + +#: ..\..\AutoAirItem.cs:116 +msgid "" +"[i:3455][c/AD89D5:自][c/D68ACA:动][c/DF909A:垃][c/E5A894:圾][c/E5BE94:桶][i:3454]" +msgstr "" + +#: ..\..\AutoAirItem.cs:201 +#, csharp-format +msgid "【自动垃圾桶】已将 '[c/92C5EC:{0}]'从您的背包中移除" +msgstr "" + +#: ..\..\Commands.cs:150 +msgid "" +"【自动垃圾桶】指令菜单\n" +msgstr "" + +#: ..\..\Commands.cs:151 +msgid "" +"/air —— 查看垃圾桶菜单\n" +msgstr "" + +#: ..\..\Commands.cs:158 +msgid "/air add 或 del 物品名字 —— 添加|删除《自动垃圾桶》的物品" +msgstr "" + +#: ..\..\Commands.cs:156 +msgid "" +"/air auto —— 监听垃圾桶位格开关\n" +msgstr "" + +#: ..\..\Commands.cs:154 +msgid "" +"/air clear —— 清理垃圾桶\n" +msgstr "" + +#: ..\..\Commands.cs:153 +msgid "" +"/air list —— 列出自己的垃圾桶\n" +msgstr "" + +#: ..\..\Commands.cs:157 +msgid "" +"/air mess —— 开启|关闭清理消息\n" +msgstr "" + +#: ..\..\Commands.cs:152 +msgid "" +"/air on —— 开启|关闭垃圾桶功能\n" +msgstr "" + +#: ..\..\Commands.cs:155 +msgid "" +"/air yes —— 将手持物品加入垃圾桶\n" +msgstr "" + +#: ..\..\Commands.cs:99 +msgid "" +"不存在该物品,\"物品查询\": \"[c/92C5EC:https://terraria.wiki.gg/zh/wiki/Item_IDs]\"" +msgstr "" + +#: ..\..\AutoAirItem.cs:118 +#, csharp-format +msgid "超过 [c/E17D8C:{0}] 小时 已清理 [c/76D5B4:自动垃圾桶] 数据:" +msgstr "" + +#: ..\..\Commands.cs:50 +#: ..\..\Commands.cs:73 +#: ..\..\Commands.cs:82 +msgid "禁用" +msgstr "" + +#: ..\..\Commands.cs:34 +#, csharp-format +msgid "您的垃圾桶监听状态为:[c/92C5EC:{0}]" +msgstr "" + +#: ..\..\Commands.cs:50 +#: ..\..\Commands.cs:73 +#: ..\..\Commands.cs:82 +msgid "启用" +msgstr "" + +#: ..\..\Commands.cs:30 +msgid "请输入该指令开启→: [c/92C5EC:/air on] " +msgstr "" + +#: ..\..\Commands.cs:21 +msgid "" +"请用角色[c/D95065:重进服务器]后输入:/air 指令查看菜单\n" +"羽学声明:本插件纯属[c/7E93DE:免费]请勿上当受骗" +msgstr "" + +#: ..\..\Commands.cs:65 +msgid "手选物品 [c/92C5EC:{0}] 已加入自动垃圾桶中! 脱手即清!" +msgstr "" + +#: ..\..\Commands.cs:35 +msgid "输入指令切换自动模式:[c/92C5EC:/air auto]" +msgstr "" + +#: ..\..\Commands.cs:74 +#, csharp-format +msgid "玩家 [{0}] 的垃圾桶位格监听功能已[c/92C5EC:{1}]" +msgstr "" + +#: ..\..\Commands.cs:83 +#, csharp-format +msgid "玩家 [{0}] 的自动清理消息已[c/92C5EC:{1}]" +msgstr "" + +#: ..\..\Commands.cs:51 +#, csharp-format +msgid "玩家 [{0}] 已[c/92C5EC:{1}]自动垃圾桶功能。" +msgstr "" + +#: ..\..\Commands.cs:114 +msgid "物品 [c/92C5EC:{0}] 已在垃圾桶中!" +msgstr "" + +#: ..\..\Commands.cs:127 +msgid "物品 {0} 不在垃圾桶中!" +msgstr "" + +#: ..\..\Commands.cs:131 +msgid "已成功从垃圾桶删除物品: [c/92C5EC:{0}]!" +msgstr "" + +#: ..\..\Commands.cs:118 +msgid "已成功将物品添加到垃圾桶: [c/92C5EC:{0}]!" +msgstr "" + +#: ..\..\AutoAirItem.cs:189 +#, csharp-format +msgid "已将 '[c/92C5EC:{0}]'添加到自动垃圾桶|指令菜单:[c/A1D4C2:/air]" +msgstr "" + +#: ..\..\Commands.cs:58 +#, csharp-format +msgid "已清理[c/92C5EC: {0} ]的自动垃圾桶表" +msgstr "" + +#: ..\..\AutoAirItem.cs:117 +#, csharp-format +msgid "" +"以下玩家 与 [c/ABD6C7:{0}] 离开时间\n" +"【[c/A1D4C2:{1}]】\n" +msgstr "" + diff --git a/src/BedSet/README_EN.md b/src/BedSet/README_EN.md index 1831b7333..56aba91d5 100644 --- a/src/BedSet/README_EN.md +++ b/src/BedSet/README_EN.md @@ -6,7 +6,7 @@ ## Command -| 语法 | 权限 | 说明 | +| Command | Permission | Details | | -------------- | :-----------------: | :------: | | /shome | bed.spawn.set | set spawn point| diff --git a/src/EssentialsPlus/Commands.cs b/src/EssentialsPlus/Commands.cs index acbc96585..c79202275 100644 --- a/src/EssentialsPlus/Commands.cs +++ b/src/EssentialsPlus/Commands.cs @@ -20,14 +20,14 @@ public static async void Find(CommandArgs e) var match = regex.Match(e.Message); if (!match.Success) { - e.Player.SendErrorMessage("格式错误!正确的语法是:{0}find <-类> <名称...> [页数]", + e.Player.SendErrorMessage(GetString("格式错误!正确的语法是:{0}find <-参数> <名称...> [页数]"), TShock.Config.Settings.CommandSpecifier); - e.Player.SendSuccessMessage("有效的 {0}find 类:", TShock.Config.Settings.CommandSpecifier); - e.Player.SendInfoMessage("-command: 查找命令."); - e.Player.SendInfoMessage("-item: 查找物品."); - e.Player.SendInfoMessage("-npc: 查找NPC."); - e.Player.SendInfoMessage("-tile: 查找方块."); - e.Player.SendInfoMessage("-wall: 查找墙壁."); + e.Player.SendSuccessMessage(GetString("有效的 {0}find 参数:"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendInfoMessage(GetString("-command: 查找命令.")); + e.Player.SendInfoMessage(GetString("-item: 查找物品.")); + e.Player.SendInfoMessage(GetString("-npc: 查找NPC.")); + e.Player.SendInfoMessage(GetString("-tile: 查找方块.")); + e.Player.SendInfoMessage(GetString("-wall: 查找墙壁.")); return; } @@ -35,7 +35,7 @@ public static async void Find(CommandArgs e) if (!string.IsNullOrWhiteSpace(match.Groups["page"].Value) && (!int.TryParse(match.Groups["page"].Value, out page) || page <= 0)) { - e.Player.SendErrorMessage("无效的页数 '{0}'!", match.Groups["page"].Value); + e.Player.SendErrorMessage(GetString("无效的页数 '{0}'!"), match.Groups["page"].Value); return; } @@ -55,16 +55,16 @@ await Task.Run(() => var command in TShockAPI.Commands.ChatCommands.FindAll(c => c.Names.Any(s => s.ContainsInsensitive(match.Groups[2].Value)))) { - commands.Add(string.Format("{0} (权限: {1})", command.Name, command.Permissions.FirstOrDefault())); + commands.Add(string.Format(GetString("{0} (权限: {1})"), command.Name, command.Permissions.FirstOrDefault())); } }); PaginationTools.SendPage(e.Player, page, commands, new PaginationTools.Settings { - HeaderFormat = "找到的命令 ({0}/{1}):", - FooterFormat = string.Format("输入 /find -command {0} {{0}} 查看更多", match.Groups[2].Value), - NothingToDisplayString = "未找到命令。" + HeaderFormat = GetString("找到的命令 ({0}/{1}):"), + FooterFormat = string.Format(GetString("输入 /find -command {0} {{0}} 查看更多"), match.Groups[2].Value), + NothingToDisplayString = GetString("未找到命令。") }); return; } @@ -102,9 +102,9 @@ await Task.Run(() => PaginationTools.SendPage(e.Player, page, items, new PaginationTools.Settings { - HeaderFormat = "找到的物品 ({0}/{1}):", - FooterFormat = string.Format("输入 /find -item {0} {{0}} 查看更多", match.Groups[2].Value), - NothingToDisplayString = "未找到物品。" + HeaderFormat = GetString("找到的物品 ({0}/{1}):"), + FooterFormat = string.Format(GetString("输入 /find -item {0} {{0}} 查看更多"), match.Groups[2].Value), + NothingToDisplayString = GetString("未找到物品。") }); return; } @@ -143,9 +143,9 @@ await Task.Run(() => PaginationTools.SendPage(e.Player, page, npcs, new PaginationTools.Settings { - HeaderFormat = "找到的NPC ({0}/{1}):", - FooterFormat = string.Format("输入 /find -npc {0} {{0}} 查看更多", match.Groups[2].Value), - NothingToDisplayString = "未找到NPC。", + HeaderFormat = GetString("找到的NPC ({0}/{1}):"), + FooterFormat = string.Format(GetString("输入 /find -npc {0} {{0}} 查看更多"), match.Groups[2].Value), + NothingToDisplayString = GetString("未找到NPC。"), }); return; } @@ -189,9 +189,9 @@ await Task.Run(() => PaginationTools.SendPage(e.Player, page, tiles, new PaginationTools.Settings { - HeaderFormat = "找到的方块 ({0}/{1}):", - FooterFormat = string.Format("输入 /find -tile {0} {{0}} 查看更多", match.Groups[2].Value), - NothingToDisplayString = "未找到方块。", + HeaderFormat = GetString("找到的方块 ({0}/{1}):"), + FooterFormat = string.Format(GetString("输入 /find -tile {0} {{0}} 查看更多"), match.Groups[2].Value), + NothingToDisplayString = GetString("未找到方块。"), }); return; } @@ -234,9 +234,9 @@ await Task.Run(() => PaginationTools.SendPage(e.Player, page, walls, new PaginationTools.Settings { - HeaderFormat = "找到的墙壁 ({0}/{1}):", - FooterFormat = string.Format("输入 /find -wall {0} {{0}} 查看更多", match.Groups[2].Value), - NothingToDisplayString = "未找到墙壁。", + HeaderFormat = GetString("找到的墙壁 ({0}/{1}):"), + FooterFormat = string.Format(GetString("输入 /find -wall {0} {{0}} 查看更多"), match.Groups[2].Value), + NothingToDisplayString = GetString("未找到墙壁。"), }); return; } @@ -245,12 +245,12 @@ await Task.Run(() => default: { - e.Player.SendSuccessMessage("有效的 {0}find 开关:", TShock.Config.Settings.CommandSpecifier); - e.Player.SendInfoMessage("-command: 查找命令."); - e.Player.SendInfoMessage("-item: 查找物品."); - e.Player.SendInfoMessage("-npc: 查找NPC."); - e.Player.SendInfoMessage("-tile: 查找方块."); - e.Player.SendInfoMessage("-wall: 查找墙壁."); + e.Player.SendSuccessMessage(GetString("有效的 {0}find 参数:"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendInfoMessage(GetString("-command: 查找命令.")); + e.Player.SendInfoMessage(GetString("-item: 查找物品.")); + e.Player.SendInfoMessage(GetString("-npc: 查找NPC.")); + e.Player.SendInfoMessage(GetString("-tile: 查找方块.")); + e.Player.SendInfoMessage(GetString("-wall: 查找墙壁.")); return; } } @@ -263,7 +263,7 @@ public static void FreezeTime(CommandArgs e) if (FreezeTimer.Enabled) { FreezeTimer.Stop(); - TSPlayer.All.SendInfoMessage("{0} 解除了时间冻结。", e.Player.Name); + TSPlayer.All.SendInfoMessage(GetString("{0} 解除了时间冻结。"), e.Player.Name); } else { @@ -279,7 +279,7 @@ public static void FreezeTime(CommandArgs e) TSPlayer.All.SendData(PacketTypes.TimeSet); }; FreezeTimer.Start(); - TSPlayer.All.SendInfoMessage("{0} 冻结了时间。", e.Player.Name); + TSPlayer.All.SendInfoMessage(GetString("{0} 冻结了时间。"), e.Player.Name); } } @@ -287,7 +287,7 @@ public static void DeleteHome(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("语法错误!正确的语法是:{0}delhome <家的名称>", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("语法错误!正确的语法是:{0}delhome <家的名称>"), TShock.Config.Settings.CommandSpecifier); return; } @@ -297,16 +297,16 @@ public static void DeleteHome(CommandArgs e) { if (EssentialsPlus.Homes.DeleteHome(e.Player, homeName)) { - e.Player.SendSuccessMessage("成功删除您的家 '{0}'。", homeName); + e.Player.SendSuccessMessage(GetString("成功删除您的家 '{0}'。"), homeName); } else { - e.Player.SendErrorMessage("无法删除家,请检查日志获取更多详细信息。"); + e.Player.SendErrorMessage(GetString("无法删除家,请检查日志获取更多详细信息。")); } } else { - e.Player.SendErrorMessage("无效的家 '{0}'!", homeName); + e.Player.SendErrorMessage(GetString("无效的家 '{0}'!"), homeName); } } @@ -314,14 +314,14 @@ public static async void MyHome(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("语法错误!正确的语法是:{0}myhome <家的名称>", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("语法错误!正确的语法是:{0}myhome <家的名称>"), TShock.Config.Settings.CommandSpecifier); return; } if (Regex.Match(e.Message, @"^\w+ -l(?:ist)?$").Success) { var homes = EssentialsPlus.Homes.GetAllAsync(e.Player); - e.Player.SendInfoMessage(homes.Count == 0 ? "您没有设置家。" : "家的列表: {0}", string.Join(", ", homes.Select(h => h.Name))); + e.Player.SendInfoMessage(homes.Count == 0 ? GetString("您没有设置家。") : GetString("家的列表: {0}"), string.Join(", ", homes.Select(h => h.Name))); } else { @@ -330,11 +330,11 @@ public static async void MyHome(CommandArgs e) if (home != null) { e.Player.Teleport(home.X, home.Y); - e.Player.SendSuccessMessage("传送您到您的家 '{0}'。", homeName); + e.Player.SendSuccessMessage(GetString("传送您到您的家 '{0}'。"), homeName); } else { - e.Player.SendErrorMessage("无效的家 '{0}'!", homeName); + e.Player.SendErrorMessage(GetString("无效的家 '{0}'!"), homeName); } } } @@ -343,7 +343,7 @@ public static async void SetHome(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("语法错误!正确的语法是:{0}sethome <家的名称>", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("语法错误!正确的语法是:{0}sethome <家的名称>"), TShock.Config.Settings.CommandSpecifier); return; } @@ -352,28 +352,28 @@ public static async void SetHome(CommandArgs e) { if (EssentialsPlus.Homes.UpdateHome(e.Player, homeName, e.Player.X, e.Player.Y)) { - e.Player.SendSuccessMessage("更新了您的家 '{0}'。", homeName); + e.Player.SendSuccessMessage(GetString("更新了您的家 '{0}'。"), homeName); } else { - e.Player.SendErrorMessage("无法更新家,请检查日志获取更多详细信息。"); + e.Player.SendErrorMessage(GetString("无法更新家,请检查日志获取更多详细信息。")); } return; } if (EssentialsPlus.Homes.GetAllAsync(e.Player).Count >= e.Player.Group.GetDynamicPermission(Permissions.HomeSet)) { - e.Player.SendErrorMessage("您已达到家的设置上限!"); + e.Player.SendErrorMessage(GetString("您已达到家的设置上限!")); return; } if (EssentialsPlus.Homes.AddHome(e.Player, homeName, e.Player.X, e.Player.Y)) { - e.Player.SendSuccessMessage("设置了您的家 '{0}'。", homeName); + e.Player.SendSuccessMessage(GetString("设置了您的家 '{0}'。"), homeName); } else { - e.Player.SendErrorMessage("无法设置家,请检查日志获取更多详细信息。"); + e.Player.SendErrorMessage(GetString("无法设置家,请检查日志获取更多详细信息。")); } } @@ -391,23 +391,23 @@ public static async void KickAll(CommandArgs e) noSave = true; continue; default: - e.Player.SendSuccessMessage("有效的 {0}kickall 开关:", TShock.Config.Settings.CommandSpecifier); - e.Player.SendInfoMessage("-nosave: 踢出时不保存 SSC 数据."); + e.Player.SendSuccessMessage(GetString("有效的 {0}kickall 参数:"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendInfoMessage(GetString("-nosave: 踢出时不保存 SSC 数据.")); return; } } var kickLevel = e.Player.Group.GetDynamicPermission(Permissions.KickAll); - var reason = string.IsNullOrWhiteSpace(match.Groups[2].Value) ? "没有原因。" : match.Groups[2].Value; + var reason = string.IsNullOrWhiteSpace(match.Groups[2].Value) ? GetString("没有原因。") : match.Groups[2].Value; await Task.WhenAll(TShock.Players.Where(p => p != null && p.Group.GetDynamicPermission(Permissions.KickAll) < kickLevel).Select(p => Task.Run(() => { if (!noSave && p.IsLoggedIn) { p.SaveServerCharacter(); } - p.Disconnect("踢出原因: " + reason); + p.Disconnect(GetString("踢出原因: ") + reason); }))); - e.Player.SendSuccessMessage("成功踢出所有人。原因: '{0}'。", reason); + e.Player.SendSuccessMessage(GetString("成功踢出所有人。原因: '{0}'。"), reason); } @@ -416,11 +416,11 @@ public static async void RepeatLast(CommandArgs e) var lastCommand = e.Player.GetPlayerInfo().LastCommand; if (string.IsNullOrWhiteSpace(lastCommand)) { - e.Player.SendErrorMessage("您没有上次的命令!"); + e.Player.SendErrorMessage(GetString("您没有上次的命令!")); return; } - e.Player.SendSuccessMessage("重复执行上次的命令 '{0}{1}'!", TShock.Config.Settings.CommandSpecifier, lastCommand); + e.Player.SendSuccessMessage(GetString("重复执行上次的命令 '{0}{1}'!"), TShock.Config.Settings.CommandSpecifier, lastCommand); await Task.Run(() => TShockAPI.Commands.HandleCommand(e.Player, TShock.Config.Settings.CommandSpecifier + lastCommand)); } @@ -447,11 +447,11 @@ await Task.Run(() => } if (!full) { - e.Player.SendSuccessMessage("填满了您的物品栏。"); + e.Player.SendSuccessMessage(GetString("填满了您的物品栏。")); } else { - e.Player.SendErrorMessage("您的物品栏已经满了。"); + e.Player.SendErrorMessage(GetString("您的物品栏已经满了。")); } } else @@ -460,14 +460,14 @@ await Task.Run(() => var amtToAdd = item.maxStack - item.stack; if (amtToAdd == 0) { - e.Player.SendErrorMessage("您的{0}已经满了。", item.Name); + e.Player.SendErrorMessage(GetString("您的{0}已经满了。"), item.Name); } else if (amtToAdd > 0 && item.stack > 0) { e.Player.GiveItem(item.type, amtToAdd); } - e.Player.SendSuccessMessage("增加了您的{0}的堆叠数量。", item.Name); + e.Player.SendSuccessMessage(GetString("增加了您的{0}的堆叠数量。"), item.Name); } }); } @@ -485,7 +485,7 @@ public static async void Mute(CommandArgs e) var match = regex.Match(e.Message); if (!match.Success) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:/mute add <名称> [时间]"); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:/mute add <名称> [时间]")); return; } @@ -494,7 +494,7 @@ public static async void Mute(CommandArgs e) (!TShock.Utils.TryParseTime(match.Groups[3].Value, out seconds) || seconds <= 0 || seconds > int.MaxValue / 1000)) { - e.Player.SendErrorMessage("无效的时间 '{0}'!", match.Groups[3].Value); + e.Player.SendErrorMessage(GetString("无效的时间 '{0}'!"), match.Groups[3].Value); return; } @@ -507,50 +507,50 @@ public static async void Mute(CommandArgs e) var user = TShock.UserAccounts.GetUserAccountByName(playerName); if (user == null) { - e.Player.SendErrorMessage("无效的玩家或账户 '{0}'!", playerName); + e.Player.SendErrorMessage(GetString("无效的玩家或账户 '{0}'!"), playerName); } else { if (TShock.Groups.GetGroupByName(user.Group).GetDynamicPermission(Permissions.Mute) >= e.Player.Group.GetDynamicPermission(Permissions.Mute)) { - e.Player.SendErrorMessage("您不能禁言 {0}!", user.Name); + e.Player.SendErrorMessage(GetString("您不能禁言 {0}!"), user.Name); return; } if (EssentialsPlus.Mutes.AddMute(user, DateTime.UtcNow.AddSeconds(seconds))) { - TSPlayer.All.SendInfoMessage("{0} 禁言了 {1}。", e.Player.Name, user.Name); + TSPlayer.All.SendInfoMessage(GetString("{0} 禁言了 {1}。"), e.Player.Name, user.Name); } else { - e.Player.SendErrorMessage("无法禁言,请查看日志获取更多信息。"); + e.Player.SendErrorMessage(GetString("无法禁言,请查看日志获取更多信息。")); } } } else if (players.Count > 1) { - e.Player.SendErrorMessage("匹配到多个玩家:{0}", string.Join(", ", players.Select(p => p.Name))); + e.Player.SendErrorMessage(GetString("匹配到多个玩家:{0}"), string.Join(", ", players.Select(p => p.Name))); } else { if (players[0].Group.GetDynamicPermission(Permissions.Mute) >= e.Player.Group.GetDynamicPermission(Permissions.Mute)) { - e.Player.SendErrorMessage("您不能禁言 {0}!", players[0].Name); + e.Player.SendErrorMessage(GetString("您不能禁言 {0}!"), players[0].Name); return; } if (EssentialsPlus.Mutes.AddMute(players[0], DateTime.UtcNow.AddSeconds(seconds))) { - TSPlayer.All.SendInfoMessage("{0} 禁言了 {1}。", e.Player.Name, players[0].Name); + TSPlayer.All.SendInfoMessage(GetString("{0} 禁言了 {1}。"), e.Player.Name, players[0].Name); players[0].mute = true; try { await Task.Delay(TimeSpan.FromSeconds(seconds), players[0].GetPlayerInfo().MuteToken); players[0].mute = false; - players[0].SendInfoMessage("您已解除禁言。"); + players[0].SendInfoMessage(GetString("您已解除禁言。")); } catch (TaskCanceledException) { @@ -558,7 +558,7 @@ public static async void Mute(CommandArgs e) } else { - e.Player.SendErrorMessage("无法禁言,请查看日志获取更多信息。"); + e.Player.SendErrorMessage(GetString("无法禁言,请查看日志获取更多信息。")); } } } @@ -575,7 +575,7 @@ public static async void Mute(CommandArgs e) var match = regex.Match(e.Message); if (!match.Success) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:/mute del <名称>"); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:/mute del <名称>")); return; } @@ -588,34 +588,34 @@ public static async void Mute(CommandArgs e) var user = TShock.UserAccounts.GetUserAccountByName(playerName); if (user == null) { - e.Player.SendErrorMessage("无效的玩家或账户 '{0}'!", playerName); + e.Player.SendErrorMessage(GetString("无效的玩家或账户 '{0}'!"), playerName); } else { if (EssentialsPlus.Mutes.DeleteMute(user)) { - TSPlayer.All.SendInfoMessage("{0} 解除了 {1} 的禁言。", e.Player.Name, user.Name); + TSPlayer.All.SendInfoMessage(GetString("{0} 解除了 {1} 的禁言。"), e.Player.Name, user.Name); } else { - e.Player.SendErrorMessage("无法解除禁言,请查看日志获取更多信息。"); + e.Player.SendErrorMessage(GetString("无法解除禁言,请查看日志获取更多信息。")); } } } else if (players.Count > 1) { - e.Player.SendErrorMessage("匹配到多个玩家:{0}", string.Join(", ", players.Select(p => p.Name))); + e.Player.SendErrorMessage(GetString("匹配到多个玩家:{0}"), string.Join(", ", players.Select(p => p.Name))); } else { if (EssentialsPlus.Mutes.DeleteMute(players[0])) { players[0].mute = false; - TSPlayer.All.SendInfoMessage("{0} 解除了 {1} 的禁言。", e.Player.Name, players[0].Name); + TSPlayer.All.SendInfoMessage(GetString("{0} 解除了 {1} 的禁言。"), e.Player.Name, players[0].Name); } else { - e.Player.SendErrorMessage("无法解除禁言,请查看日志获取更多信息。"); + e.Player.SendErrorMessage(GetString("无法解除禁言,请查看日志获取更多信息。")); } } } @@ -626,9 +626,9 @@ public static async void Mute(CommandArgs e) #region 帮助 default: - e.Player.SendSuccessMessage("禁言子命令:"); - e.Player.SendInfoMessage("add <名称> [时间] - 禁言玩家或账户。"); - e.Player.SendInfoMessage("del <名称> - 解除禁言玩家或账户。"); + e.Player.SendSuccessMessage(GetString("禁言子命令:")); + e.Player.SendInfoMessage(GetString("add <名称> [时间] - 禁言玩家或账户。")); + e.Player.SendInfoMessage(GetString("del <名称> - 解除禁言玩家或账户。")); return; #endregion @@ -650,7 +650,7 @@ public static void Ruler(CommandArgs e) { if (e.Player.TempPoints.Any(p => p == Point.Zero)) { - e.Player.SendErrorMessage("尺规未设置!"); + e.Player.SendErrorMessage(GetString("尺规未设置!")); return; } @@ -659,28 +659,28 @@ public static void Ruler(CommandArgs e) var x = Math.Abs(p1.X - p2.X); var y = Math.Abs(p1.Y - p2.Y); var cartesian = Math.Sqrt((x * x) + (y * y)); - e.Player.SendInfoMessage("距离:X轴:{0},Y轴:{1},直角距离:{2:N3}", x, y, cartesian); + e.Player.SendInfoMessage(GetString("距离:X轴:{0},Y轴:{1},直角距离:{2:N3}"), x, y, cartesian); } else if (e.Parameters.Count == 1) { if (e.Parameters[0] == "1") { e.Player.AwaitingTempPoint = 1; - e.Player.SendInfoMessage("修改一个方块以设置第一个尺规点。"); + e.Player.SendInfoMessage(GetString("修改一个方块以设置第一个尺规点。")); } else if (e.Parameters[0] == "2") { e.Player.AwaitingTempPoint = 2; - e.Player.SendInfoMessage("修改一个方块以设置第二个尺规点。"); + e.Player.SendInfoMessage(GetString("修改一个方块以设置第二个尺规点。")); } else { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}ruler [1/2]", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}ruler [1/2]"), TShock.Config.Settings.CommandSpecifier); } } else { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}ruler [1/2]", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}ruler [1/2]"), TShock.Config.Settings.CommandSpecifier); } } @@ -691,7 +691,7 @@ public static void Send(CommandArgs e) var match = regex.Match(e.Message); if (!match.Success) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}send [r,g,b] <文本...>", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}send [r,g,b] <文本...>"), TShock.Config.Settings.CommandSpecifier); return; } @@ -701,7 +701,7 @@ public static void Send(CommandArgs e) if (!string.IsNullOrWhiteSpace(match.Groups[1].Value) && !string.IsNullOrWhiteSpace(match.Groups[2].Value) && !string.IsNullOrWhiteSpace(match.Groups[3].Value) && (!byte.TryParse(match.Groups[1].Value, out r) || !byte.TryParse(match.Groups[2].Value, out g) || !byte.TryParse(match.Groups[3].Value, out b))) { - e.Player.SendErrorMessage("无效的颜色!"); + e.Player.SendErrorMessage(GetString("无效的颜色!")); return; } TSPlayer.All.SendMessage(match.Groups[4].Value, new Color(r, g, b)); @@ -714,9 +714,9 @@ public static async void Sudo(CommandArgs e) var match = regex.Match(e.Message); if (!match.Success) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}sudo [-switches...] <玩家> <命令...>", TShock.Config.Settings.CommandSpecifier); - e.Player.SendSuccessMessage("有效的 {0}sudo 开关:", TShock.Config.Settings.CommandSpecifier); - e.Player.SendInfoMessage("-f, -force: 强制sudo,忽略权限限制。"); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}sudo [-switches...] <玩家> <命令...>"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendSuccessMessage(GetString("有效的 {0}sudo 参数:"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendInfoMessage(GetString("-f, -force: 强制sudo,忽略权限限制。")); return; } @@ -729,14 +729,14 @@ public static async void Sudo(CommandArgs e) case "force": if (!e.Player.Group.HasPermission(Permissions.SudoForce)) { - e.Player.SendErrorMessage("您没有访问 '-{0}' 开关的权限!", capture.Value); + e.Player.SendErrorMessage(GetString("您没有访问 '-{0}' 参数的权限!"), capture.Value); return; } force = true; continue; default: - e.Player.SendSuccessMessage("有效的 {0}sudo 开关:", TShock.Config.Settings.CommandSpecifier); - e.Player.SendInfoMessage("-f, -force: 强制sudo,忽略权限限制。"); + e.Player.SendSuccessMessage(GetString("有效的 {0}sudo 参数:"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendInfoMessage(GetString("-f, -force: 强制sudo,忽略权限限制。")); return; } } @@ -747,25 +747,25 @@ public static async void Sudo(CommandArgs e) var players = TShock.Players.FindPlayers(playerName); if (players.Count == 0) { - e.Player.SendErrorMessage("无效的玩家 '{0}'!", playerName); + e.Player.SendErrorMessage(GetString("无效的玩家 '{0}'!"), playerName); } else if (players.Count > 1) { - e.Player.SendErrorMessage("匹配到多个玩家:{0}", string.Join(", ", players.Select(p => p.Name))); + e.Player.SendErrorMessage(GetString("匹配到多个玩家:{0}"), string.Join(", ", players.Select(p => p.Name))); } else { if ((e.Player.Group.GetDynamicPermission(Permissions.Sudo) <= players[0].Group.GetDynamicPermission(Permissions.Sudo)) && !e.Player.Group.HasPermission(Permissions.SudoSuper)) { - e.Player.SendErrorMessage("您无法强制 {0} 执行 {1}{2}!", players[0].Name, TShock.Config.Settings.CommandSpecifier, command); + e.Player.SendErrorMessage(GetString("您无法强制 {0} 执行 {1}{2}!"), players[0].Name, TShock.Config.Settings.CommandSpecifier, command); return; } - e.Player.SendSuccessMessage("强制 {0} 执行 {1}{2}。", players[0].Name, TShock.Config.Settings.CommandSpecifier, command); + e.Player.SendSuccessMessage(GetString("强制 {0} 执行 {1}{2}。"), players[0].Name, TShock.Config.Settings.CommandSpecifier, command); if (!e.Player.Group.HasPermission(Permissions.SudoInvisible)) { - players[0].SendInfoMessage("{0} 强制您执行 {1}{2}。", e.Player.Name, TShock.Config.Settings.CommandSpecifier, command); + players[0].SendInfoMessage(GetString("{0} 强制您执行 {1}{2}。"), e.Player.Name, TShock.Config.Settings.CommandSpecifier, command); } var fakePlayer = new TSPlayer(players[0].Index) @@ -792,9 +792,9 @@ public static async void TimeCmd(CommandArgs e) var match = regex.Match(e.Message); if (!match.Success) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}timecmd [-switches...] <时间> <命令...>", TShock.Config.Settings.CommandSpecifier); - e.Player.SendSuccessMessage("有效的 {0}timecmd 开关:", TShock.Config.Settings.CommandSpecifier); - e.Player.SendInfoMessage("-r, -repeat: 重复执行时间命令。"); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}timecmd [-switches...] <时间> <命令...>"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendSuccessMessage(GetString("有效的 {0}timecmd 参数:"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendInfoMessage(GetString("-r, -repeat: 重复执行时间命令。")); return; } @@ -808,31 +808,31 @@ public static async void TimeCmd(CommandArgs e) repeat = true; break; default: - e.Player.SendSuccessMessage("有效的 {0}timecmd 开关:", TShock.Config.Settings.CommandSpecifier); - e.Player.SendInfoMessage("-r, -repeat: 重复执行时间命令。"); + e.Player.SendSuccessMessage(GetString("有效的 {0}timecmd 参数:"), TShock.Config.Settings.CommandSpecifier); + e.Player.SendInfoMessage(GetString("-r, -repeat: 重复执行时间命令。")); return; } } if (!TShock.Utils.TryParseTime(match.Groups[2].Value, out int seconds) || seconds <= 0 || seconds > int.MaxValue / 1000) { - e.Player.SendErrorMessage("无效的时间 '{0}'!", match.Groups[2].Value); + e.Player.SendErrorMessage(GetString("无效的时间 '{0}'!"), match.Groups[2].Value); return; } if (repeat) { - e.Player.SendSuccessMessage("已排队执行命令 '{0}{1}'。使用 /cancel 取消!", TShock.Config.Settings.CommandSpecifier, match.Groups[3].Value); + e.Player.SendSuccessMessage(GetString("已排队执行命令 '{0}{1}'。使用 /cancel 取消!"), TShock.Config.Settings.CommandSpecifier, match.Groups[3].Value); } else { - e.Player.SendSuccessMessage("已排队执行命令 '{0}{1}'。使用 /cancel 取消!", TShock.Config.Settings.CommandSpecifier, match.Groups[3].Value); + e.Player.SendSuccessMessage(GetString("已排队执行命令 '{0}{1}'。使用 /cancel 取消!"), TShock.Config.Settings.CommandSpecifier, match.Groups[3].Value); } e.Player.AddResponse("cancel", o => { e.Player.GetPlayerInfo().CancelTimeCmd(); - e.Player.SendSuccessMessage("取消所有时间命令!"); + e.Player.SendSuccessMessage(GetString("取消所有时间命令!")); }); var token = e.Player.GetPlayerInfo().TimeCmdToken; @@ -858,26 +858,26 @@ public static void Back(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}eback [步数]", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}eback [步数]"), TShock.Config.Settings.CommandSpecifier); return; } var steps = 1; if (e.Parameters.Count > 0 && (!int.TryParse(e.Parameters[0], out steps) || steps <= 0)) { - e.Player.SendErrorMessage("无效的步数 '{0}'!", e.Parameters[0]); + e.Player.SendErrorMessage(GetString("无效的步数 '{0}'!"), e.Parameters[0]); return; } var info = e.Player.GetPlayerInfo(); if (info.BackHistoryCount == 0) { - e.Player.SendErrorMessage("无法传送回上一个位置!"); + e.Player.SendErrorMessage(GetString("无法传送回上一个位置!")); return; } steps = Math.Min(steps, info.BackHistoryCount); - e.Player.SendSuccessMessage("传送回 {0} 步.", steps); + e.Player.SendSuccessMessage(GetString("传送回 {0} 步."), steps); var vector = info.PopBackHistory(steps); e.Player.Teleport(vector.X, vector.Y); } @@ -886,14 +886,14 @@ public static async void Down(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}down [层数]", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}down [层数]"), TShock.Config.Settings.CommandSpecifier); return; } var levels = 1; if (e.Parameters.Count > 0 && (!int.TryParse(e.Parameters[0], out levels) || levels <= 0)) { - e.Player.SendErrorMessage("无效的层数 '{0}'!", levels); + e.Player.SendErrorMessage(GetString("无效的层数 '{0}'!"), levels); return; } @@ -923,7 +923,7 @@ await Task.Run(() => if (currentLevel == 0) { - e.Player.SendErrorMessage("无法传送下去!"); + e.Player.SendErrorMessage(GetString("无法传送下去!")); } else { @@ -933,7 +933,7 @@ await Task.Run(() => } e.Player.Teleport(16 * x, (16 * y) - 10); - e.Player.SendSuccessMessage("传送下 {0} 层.", currentLevel); + e.Player.SendSuccessMessage(GetString("传送下 {0} 层."), currentLevel); } } @@ -941,14 +941,14 @@ public static async void Left(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}left [层数]", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}left [层数]"), TShock.Config.Settings.CommandSpecifier); return; } var levels = 1; if (e.Parameters.Count > 0 && (!int.TryParse(e.Parameters[0], out levels) || levels <= 0)) { - e.Player.SendErrorMessage("无效的层数 '{0}'!", levels); + e.Player.SendErrorMessage(GetString("无效的层数 '{0}'!"), levels); return; } @@ -981,7 +981,7 @@ await Task.Run(() => if (currentLevel == 0) { - e.Player.SendErrorMessage("无法传送左边!"); + e.Player.SendErrorMessage(GetString("无法传送左边!")); } else { @@ -991,7 +991,7 @@ await Task.Run(() => } e.Player.Teleport((16 * x) + 12, 16 * y); - e.Player.SendSuccessMessage("传送左 {0} 层.", currentLevel); + e.Player.SendSuccessMessage(GetString("传送左 {0} 层."), currentLevel); } } @@ -999,14 +999,14 @@ public static async void Right(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}right [层数]", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}right [层数]"), TShock.Config.Settings.CommandSpecifier); return; } var levels = 1; if (e.Parameters.Count > 0 && (!int.TryParse(e.Parameters[0], out levels) || levels <= 0)) { - e.Player.SendErrorMessage("无效的层数 '{0}'!", levels); + e.Player.SendErrorMessage(GetString("无效的层数 '{0}'!"), levels); return; } @@ -1039,7 +1039,7 @@ await Task.Run(() => if (currentLevel == 0) { - e.Player.SendErrorMessage("无法传送右边!"); + e.Player.SendErrorMessage(GetString("无法传送右边!")); } else { @@ -1049,7 +1049,7 @@ await Task.Run(() => } e.Player.Teleport(16 * x, 16 * y); - e.Player.SendSuccessMessage("传送右 {0} 层.", currentLevel); + e.Player.SendSuccessMessage(GetString("传送右 {0} 层."), currentLevel); } } @@ -1057,14 +1057,14 @@ public static async void Up(CommandArgs e) { if (e.Parameters.Count > 1) { - e.Player.SendErrorMessage("无效的语法!正确的语法是:{0}up [层数]", TShock.Config.Settings.CommandSpecifier); + e.Player.SendErrorMessage(GetString("无效的语法!正确的语法是:{0}up [层数]"), TShock.Config.Settings.CommandSpecifier); return; } var levels = 1; if (e.Parameters.Count > 0 && (!int.TryParse(e.Parameters[0], out levels) || levels <= 0)) { - e.Player.SendErrorMessage("无效的层数 '{0}'!", levels); + e.Player.SendErrorMessage(GetString("无效的层数 '{0}'!"), levels); return; } @@ -1097,7 +1097,7 @@ await Task.Run(() => if (currentLevel == 0) { - e.Player.SendErrorMessage("无法传送上面!"); + e.Player.SendErrorMessage(GetString("无法传送上面!")); } else { @@ -1107,7 +1107,7 @@ await Task.Run(() => } e.Player.Teleport(16 * x, (16 * y) + 6); - e.Player.SendSuccessMessage("传送上 {0} 层.", currentLevel); + e.Player.SendSuccessMessage(GetString("传送上 {0} 层."), currentLevel); } } diff --git a/src/EssentialsPlus/EssentialsPlus.cs b/src/EssentialsPlus/EssentialsPlus.cs index 9d6fba452..feb25e2d3 100644 --- a/src/EssentialsPlus/EssentialsPlus.cs +++ b/src/EssentialsPlus/EssentialsPlus.cs @@ -24,7 +24,7 @@ public class EssentialsPlus : TerrariaPlugin public override string Name => "EssentialsPlus"; - public override Version Version => new Version(1, 0, 2); + public override Version Version => new Version(1, 0, 3); public EssentialsPlus(Main game) @@ -67,7 +67,7 @@ private void OnReload(ReloadEventArgs e) Config.Write(path); } Homes.Reload(); - e.Player.SendSuccessMessage("[EssentialsPlus] 重新加载配置和家!"); + e.Player.SendSuccessMessage(GetString("[EssentialsPlus] 重新加载配置和家!")); } private readonly List teleportCommands = new List @@ -93,7 +93,7 @@ private void OnPlayerCommand(PlayerCommandEventArgs e) .Intersect(Config.DisabledCommandsInPvp.Select(s => s.ToLowerInvariant())) .Any()) { - e.Player.SendErrorMessage("在PvP中无法使用该命令!"); + e.Player.SendErrorMessage(GetString("在PvP中无法使用该命令!")); e.Handled = true; return; } @@ -131,9 +131,9 @@ private void OnInitialize(EventArgs e) string.IsNullOrWhiteSpace(Config.MySqlDbName)) { Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("[Essentials+] MySQL已启用,但未设置Essentials+ MySQL配置。"); - Console.WriteLine("[Essentials+] 请在essentials.json中配置您的MySQL服务器信息,然后重新启动服务器。"); - Console.WriteLine("[Essentials+] 此插件现在将禁用自身..."); + Console.WriteLine(GetString("[Essentials+] MySQL已启用,但未设置Essentials+ MySQL配置。")); + Console.WriteLine(GetString("[Essentials+] 请在essentials.json中配置您的MySQL服务器信息,然后重新启动服务器。")); + Console.WriteLine(GetString("[Essentials+] 此插件现在将禁用自身...")); Console.ResetColor(); GeneralHooks.ReloadEvent -= this.OnReload; @@ -150,7 +150,7 @@ private void OnInitialize(EventArgs e) var host = Config.MySqlHost.Split(':'); Db = new MySqlConnection { - ConnectionString = string.Format("Server={0}; Port={1}; Database={2}; Uid={3}; Pwd={4};", + ConnectionString = string.Format( "Server={0}; Port={1}; Database={2}; Uid={3}; Pwd={4};", host[0], host.Length == 1 ? "3306" : host[1], Config.MySqlDbName, @@ -163,7 +163,7 @@ private void OnInitialize(EventArgs e) Db = TShock.Config.Settings.StorageType.Equals("sqlite", StringComparison.OrdinalIgnoreCase) ? (IDbConnection) new SqliteConnection( "Data Source=" + Path.Combine(TShock.SavePath, "essentials.sqlite")) - : throw new InvalidOperationException("无效的存储类型!"); + : throw new InvalidOperationException(GetString("无效的存储类型!")); } Mutes = new MuteManager(Db); @@ -183,103 +183,103 @@ private void OnInitialize(EventArgs e) Add(new Command(Permissions.Find, Commands.Find, "find", "查找") { - HelpText = "查找具有指定名称的物品和/或NPC。" + HelpText = GetString("查找具有指定名称的物品和/或NPC。") }); Add(new Command(Permissions.FreezeTime, Commands.FreezeTime, "freezetime", "冻结时间") { - HelpText = "切换冻结时间。" + HelpText = GetString("切换冻结时间。") }); Add(new Command(Permissions.HomeDelete, Commands.DeleteHome, "delhome", "删除家点") { AllowServer = false, - HelpText = "删除您的一个家点。" + HelpText = GetString("删除您的一个家点。") }); Add(new Command(Permissions.HomeSet, Commands.SetHome, "sethome", "设置家点") { AllowServer = false, - HelpText = "设置您的一个家点。" + HelpText = GetString("设置您的一个家点。") }); Add(new Command(Permissions.HomeTp, Commands.MyHome, "myhome", "我的家点") { AllowServer = false, - HelpText = "传送到您的一个家点。" + HelpText = GetString("传送到您的一个家点。") }); Add(new Command(Permissions.KickAll, Commands.KickAll, "kickall", "踢出所有人") { - HelpText = "踢出服务器上的所有人。" + HelpText = GetString("踢出服务器上的所有人。") }); Add(new Command(Permissions.LastCommand, Commands.RepeatLast, "=", "重复上一条命令") { - HelpText = "允许您重复上一条命令。" + HelpText = GetString("允许您重复上一条命令。") }); Add(new Command(Permissions.More, Commands.More, "more", "最大化堆叠") { AllowServer = false, - HelpText = "最大化手持物品的堆叠。" + HelpText = GetString("最大化手持物品的堆叠。") }); //这将覆盖TShock的 'mute' 命令 Add(new Command(Permissions.Mute, Commands.Mute, "mute", "禁言管理") { - HelpText = "管理禁言。" + HelpText = GetString("管理禁言。") }); Add(new Command(Permissions.PvP, Commands.PvP, "pvpget2", "切换PvP状态") { AllowServer = false, - HelpText = "切换您的PvP状态。" + HelpText = GetString("切换您的PvP状态。") }); Add(new Command(Permissions.Ruler, Commands.Ruler, "ruler", "测量工具") { AllowServer = false, - HelpText = "允许您测量两个方块之间的距离。" + HelpText = GetString("允许您测量两个方块之间的距离。") }); Add(new Command(Permissions.Send, Commands.Send, "send", "广播消息") { - HelpText = "以自定义颜色广播消息。" + HelpText = GetString("以自定义颜色广播消息。") }); Add(new Command(Permissions.Sudo, Commands.Sudo, "sudo", "代执行") { - HelpText = "允许您以其他用户的身份执行命令。" + HelpText = GetString("允许您以其他用户的身份执行命令。") }); Add(new Command(Permissions.TimeCmd, Commands.TimeCmd, "timecmd", "定时命令") { - HelpText = "在给定时间间隔后执行命令。" + HelpText = GetString("在给定时间间隔后执行命令。") }); Add(new Command(Permissions.TpBack, Commands.Back, "eback", "b", "回到") { AllowServer = false, - HelpText = "在死亡或传送后将您传送回之前的位置。" + HelpText = GetString("在死亡或传送后将您传送回之前的位置。") }); Add(new Command(Permissions.TpDown, Commands.Down, "down", "向下传送") { AllowServer = false, - HelpText = "通过一个方块层向下传送您。" + HelpText = GetString("通过一个方块层向下传送您。") }); Add(new Command(Permissions.TpLeft, Commands.Left, "left", "向左传送") { AllowServer = false, - HelpText = "通过一个方块层向左传送您。" + HelpText = GetString("通过一个方块层向左传送您。") }); Add(new Command(Permissions.TpRight, Commands.Right, "right", "向右传送") { AllowServer = false, - HelpText = "通过一个方块层向右传送您。" + HelpText = GetString("通过一个方块层向右传送您。") }); Add(new Command(Permissions.TpUp, Commands.Up, "up", "向上传送") { AllowServer = false, - HelpText = "通过一个方块层向上传送您。" + HelpText = GetString("通过一个方块层向上传送您。") }); @@ -314,7 +314,7 @@ private async void OnJoin(JoinEventArgs e) { await Task.Delay(muteExpiration - DateTime.UtcNow, player.GetPlayerInfo().MuteToken); player.mute = false; - player.SendInfoMessage("您已被解除禁言。"); + player.SendInfoMessage(GetString("您已被解除禁言。")); } catch (TaskCanceledException) { diff --git a/src/EssentialsPlus/README.md b/src/EssentialsPlus/README.md index f28aa0ad9..15a2a8a34 100644 --- a/src/EssentialsPlus/README.md +++ b/src/EssentialsPlus/README.md @@ -2,17 +2,19 @@ - 作者: WhiteX等人,Average,Cjx,肝帝熙恩适配与修改,Cai更新 - 出处: [github](https://github.com/QuiCM/EssentialsPlus) -- 提供一些管理指令 +- Essentials+ 是一种组合,用于改进和优化 Essentials 和 MoreAdminCommands 中的某些功能。所有命令都是异步执行的。不包括 Flag 命令。 ## 更新日志 ``` +1.0.3 +i18n完成,且预置es-EN 1.0.2 修复数据库错误 1.0.1 修复重启无法获取禁言的BUG, 重命名一些方法 ``` -## 指令 ## +## 指令 - **/find** 或 **/查找** -> 包含多个子命令: - **-command** 或 **-命令** -> 根据输入搜索特定命令,返回匹配的命令及其权限。 @@ -20,52 +22,50 @@ - **-tile** 或 **-方块** -> 根据输入搜索特定方块,返回匹配的方块及其 ID。 - **-wall** 或 **-墙壁** -> 根据输入搜索特定墙壁,返回匹配的墙壁及其 ID。 - **/freezetime** 或 **/冻结时间** -> 冻结或解冻时间。 -- **/delhome** 或 **/删除家点** <家名称> -> 删除您的一个家点。 -- **/sethome** 或 **/设置家点** <家名称> -> 设置您的一个家点。 -- **/myhome** 或 **/我的家点** <家名称> -> 传送到您的一个家点。 -- **/kickall** 或 **/踢所有人** <原因> -> 踢出服务器上的所有人。 +- **/delhome** 或 **/删除家点** `<家名称>` -> 删除您的一个家点。 +- **/sethome** 或 **/设置家点** `<家名称>` -> 设置您的一个家点。 +- **/myhome** 或 **/我的家点** `<家名称>` -> 传送到您的一个家点。 +- **/kickall** 或 **/踢所有人** `<原因>` -> 踢出服务器上的所有人。有效标志:`-nosave` -> 踢出时不会保存 SSC 背包。 - **/=** 或 **/重复** -> 重复您最后输入的命令(不包括其他 /= 的迭代)。 - **/more** 或 **/堆叠** -> 最大化手持物品的堆叠。子命令: - **-all** 或 **-全部** -> 最大化玩家背包中所有可堆叠的物品。 - **/mute** 或 **/静音管理** -> 覆盖 TShock 的 /mute。包含子命令: - - **add** <名称> <时间> -> 为名称为 <名称> 的用户添加静音,时间为 <时间>。 - - **delete** <名称> -> 删除名称为 <名称> 的用户的静音。 + - **add** `<名称> <时间>` -> 为名称为 `<名称>` 的用户添加静音,时间为 `<时间>`。 + - **delete** `<名称>` -> 删除名称为 `<名称>` 的用户的静音。 - **help** 或 **帮助** -> 输出命令信息。 -- **/pvpget2** 或 **/切换PvP状态** -> 切换您的PvP状态。 -- **/ruler** 或 **/测量工具** [1|2] -> 测量点 1 和点 2 之间的距离。 -- **/send** 或 **/广播消息** -> 以自定义颜色广播消息。 -- **/sudo** 或 **/代执行** -> 尝试让 <玩家> 执行 <命令>。包含子命令: - - **-force** -> 强制运行命令,不受 <玩家> 的权限限制。 -- **/timecmd** 或 **/定时命令** -> 在给定时间间隔后执行命令。包含子命令: - - **-repeat** -> 每隔 <时间> 重复执行 <命令>。 -- **/eback** 或 **/b** 或 **/返回** [步数] -> 将您带回到上一个位置。如果提供了 [步数],则尝试将您带回 [步数] 步之前的位置。 -- **/down** 或 **/下** [层数] -> 尝试向下移动您在地图上的位置。如果指定了 [层数],则尝试向下移动 [层数] 次。 -- **/left** 或 **/左** [层数] -> 与 /down [层数] 相同,但向左移动。 -- **/right** 或 **/右** [层数] -> 与 /down [层数] 相同,但向右移动。 -- **/up** 或 **/上** [层数] -> 与 /down [层数] 相同,但向上移动。 +- **/pvp** 或 **/切换PvP状态** -> 切换您的 PvP 状态。 +- **/ruler** 或 **/测量工具** `[1|2]` -> 测量点 1 和点 2 之间的距离。 +- **/sudo** 或 **/代执行** `[flag] <玩家> <命令>` -> 让 `<玩家>` 执行 `<命令>`。有效标志:`-force` -> 强制执行命令,忽略 `<玩家>` 的权限限制。拥有 `essentials.sudo.super` 权限的玩家可以对任何人使用 /sudo。 +- **/timecmd** 或 **/定时命令** `[flag] <时间> <命令>` -> 在 `<时间>` 后执行 `<命令>`。有效标志:`-repeat` -> 每隔 `<时间>` 重复执行 `<命令>`。 +- **/back** 或 **/返回** `[步数]` -> 将您带回到上一个位置。如果提供了 `[步数]`,则尝试将您带回 `[步数]` 步之前的位置。 +- **/down** 或 **/下** `[层数]` -> 尝试向下移动您在地图上的位置。如果指定了 `[层数]`,则尝试向下移动 `[层数]` 次。 +- **/left** 或 **/左** `[层数]` -> 类似于 /down `[层数]`,但向左移动。 +- **/right** 或 **/右** `[层数]` -> 类似于 /down `[层数]`,但向右移动。 +- **/up** 或 **/上** `[层数]` -> 类似于 /down `[层数]`,但向上移动。 +## 权限 - -## 权限 ## - -- essentials.find -> 允许使用 /find 命令。 -- essentials.freezetime -> 允许使用 /freezetime 命令。 -- essentials.home.delete -> 允许使用 /delhome 和 /sethome 命令。 -- essentials.home.tp -> 允许使用 /myhome 命令。 -- essentials.kickall -> 允许使用 /kickall 命令。 -- essentials.lastcommand -> 允许使用 /= 命令。 -- essentials.more -> 允许使用 /more 命令。 -- essentials.mute -> 允许使用 /mute 命令。 -- essentials.pvp -> 允许使用 /pvpget2 命令。 -- essentials.ruler -> 允许使用 /ruler 命令。 -- essentials.send -> 允许使用 /send 命令。 -- essentials.sudo -> 允许使用 /sudo 命令。 -- essentials.timecmd -> 允许使用 /timecmd 命令。 -- essentials.tp.eback -> 允许使用 /eback 命令。 -- essentials.tp.down -> 允许使用 /down 命令。 -- essentials.tp.left -> 允许使用 /left 命令。 -- essentials.tp.right -> 允许使用 /right 命令。 -- essentials.tp.up -> 允许使用 /up 命令。 +- `essentials.find` -> 授予访问 `/find` 命令的权限。 +- `essentials.freezetime` -> 授予访问 `/freezetime` 命令的权限。 +- `essentials.home.delete` -> 授予访问 `/delhome` 和 `/sethome` 命令的权限。 +- `essentials.home.tp` -> 授予访问 `/myhome` 命令的权限。 +- `essentials.kickall` -> 授予访问 `/kickall` 命令的权限。 +- `essentials.lastcommand` -> 授予访问 `/=` 命令的权限。 +- `essentials.more` -> 授予访问 `/more` 命令的权限。 +- `essentials.mute` -> 授予访问改进后的 `/mute` 命令的权限。 +- `essentials.pvp` -> 授予访问 `/pvp` 命令的权限。 +- `essentials.ruler` -> 授予访问 `/ruler` 命令的权限。 +- `essentials.send` -> 授予访问 `/send` 命令的权限。 +- `essentials.sudo` -> 授予访问 `/sudo` 命令的权限。 +- `essentials.sudo.force` -> 扩展 `sudo` 的功能。 +- `essentials.sudo.super` -> 允许对任何人使用 `sudo`。 +- `essentials.sudo.invisible` -> 使通过 `sudo` 执行的命令不可见。 +- `essentials.timecmd` -> 授予访问 `/timecmd` 命令的权限。 +- `essentials.tp.back` -> 授予访问 `/back` 命令的权限。 +- `essentials.tp.down` -> 授予访问 `/down` 命令的权限。 +- `essentials.tp.left` -> 授予访问 `/left` 命令的权限。 +- `essentials.tp.right` -> 授予访问 `/right` 命令的权限。 +- `essentials.tp.up` -> 授予访问 `/up` 命令的权限。 ## 配置 > 配置文件位置:tshock/EssentialsPlus.json diff --git a/src/EssentialsPlus/README_EN.md b/src/EssentialsPlus/README_EN.md new file mode 100644 index 000000000..4ab5dd244 --- /dev/null +++ b/src/EssentialsPlus/README_EN.md @@ -0,0 +1,89 @@ +# EssentialsPlus + +- Authors: WhiteX等人,Average,Cjx,肝帝熙恩适配与修改,Cai更新 +- Source: [github](https://github.com/QuiCM/EssentialsPlus) +- Essentials+ is a combination of things from Essentials and things from MoreAdminCommands made better. All commands run asynchronously. It does not include Sign Commands. + + +## Commands + +- **/find** -> Takes a variety of subcommands: + - **-command** -> Searches for a specific command based on input, returning matching commands and their permissions. + - **-item** -> Searches for a specific item based on input, returning matching items and their IDs. + - **-tile** -> Searches for a specific tile based on input, returning matching tiles and their IDs. + - **-wall** -> Searches for a specific wall based on input, returning matching walls and their IDs. +- **/freezetime** -> Freezes and unfreezes time. +- **/delhome** `` -> Deletes a home specified by ``. +- **/sethome** `` -> Sets a home named ``. +- **/myhome** `` -> Teleports you to your home named ``. +- **/kickall** ` ` -> Kicks every player for ``. Valid flag: `-nosave` -> The kick doesn't save SSC inventory. +- **/=** -> Repeats your last entered command (not including other instances of /=). +- **/more** -> Maximizes the item stack of the held item. Includes subcommands: + - **-all** -> Maximizes all stackable items in the player's inventory. +- **/mute** -> Overwrites TShock's /mute. Includes subcommands: + - **add** `