diff --git a/Plugin.sln b/Plugin.sln index fc6fdd210..ee9c24e23 100644 --- a/Plugin.sln +++ b/Plugin.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.9.34622.214 @@ -278,6 +277,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoClassificationQuickStac EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGen", "src\SourceGen\SourceGen.csproj", "{E5E60819-4B13-4982-B345-358A4DBE9D3B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrCDK", "src\TrCDK\TrCDK.csproj", "{D06CC8C7-7B77-428B-B5BA-A690C17DE382}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BossLock", "src\BossLock\BossLock.csproj", "{80ACB7F0-2820-44D5-B0CA-CC73444D880E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GhostView", "src\GhostView\GhostView.csproj", "{6ABEAB06-DC01-48AE-8119-9E25213C9949}" @@ -1374,6 +1374,14 @@ Global {E5E60819-4B13-4982-B345-358A4DBE9D3B}.Release|Any CPU.Build.0 = Release|Any CPU {E5E60819-4B13-4982-B345-358A4DBE9D3B}.Release|x64.ActiveCfg = Release|Any CPU {E5E60819-4B13-4982-B345-358A4DBE9D3B}.Release|x64.Build.0 = Release|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Debug|x64.ActiveCfg = Debug|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Debug|x64.Build.0 = Debug|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Release|Any CPU.Build.0 = Release|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Release|x64.ActiveCfg = Release|Any CPU + {D06CC8C7-7B77-428B-B5BA-A690C17DE382}.Release|x64.Build.0 = Release|Any CPU {80ACB7F0-2820-44D5-B0CA-CC73444D880E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80ACB7F0-2820-44D5-B0CA-CC73444D880E}.Debug|Any CPU.Build.0 = Debug|Any CPU {80ACB7F0-2820-44D5-B0CA-CC73444D880E}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/src/EssentialsPlus/Db/TpAllowManager.cs b/src/EssentialsPlus/Db/TpAllowManager.cs index a02c847c9..c4bc7e6e9 100644 --- a/src/EssentialsPlus/Db/TpAllowManager.cs +++ b/src/EssentialsPlus/Db/TpAllowManager.cs @@ -48,30 +48,23 @@ public bool ToggleTpAllow(TSPlayer player) if (existing == null) { - newState = true; + // 默认允许 + newState = false; this.TpAllows.Add(new TpAllow(player.Name, newState)); - - if (this.db.Query("INSERT OR REPLACE INTO TpAllows VALUES (@0, @1)", - player.Name, newState ? 1 : 0) > 0) - { - player.TPAllow = newState; - return true; - } - return false; } else { newState = !existing.IsEnabled; existing.IsEnabled = newState; + } - if (this.db.Query("UPDATE TpAllows SET IsEnabled = @0 WHERE Name = @1", - newState ? 1 : 0, player.Name) > 0) - { - player.TPAllow = newState; - return true; - } - return false; + if (this.db.Query("REPLACE INTO TpAllows VALUES (@0, @1);", + player.Name, newState ? 1 : 0) > 0) + { + player.TPAllow = newState; + return true; } + return false; } catch (Exception ex) { @@ -136,12 +129,22 @@ public bool IsTpAllowed(TSPlayer player) player.TPAllow = isEnabled; return isEnabled; } + + // 未找到记录时,默认允许传送并添加记录 + var defaultAllowed = true; + this.TpAllows.Add(new TpAllow(player.Name, defaultAllowed)); + this.db.Query("INSERT INTO TpAllows (Name, IsEnabled) VALUES (@0, @1)", + player.Name, defaultAllowed ? 1 : 0); + player.TPAllow = defaultAllowed; + return defaultAllowed; } catch (Exception ex) { TShock.Log.Error($"查询玩家 {player.Name} 的传送权限时发生错误: {ex}"); } - player.TPAllow = false; - return false; + + // 异常情况下保持默认允许(可选,根据需求决定) + player.TPAllow = true; + return true; } } \ No newline at end of file diff --git a/src/EssentialsPlus/EssentialsPlus.cs b/src/EssentialsPlus/EssentialsPlus.cs index b140fbf6b..f61148aaf 100644 --- a/src/EssentialsPlus/EssentialsPlus.cs +++ b/src/EssentialsPlus/EssentialsPlus.cs @@ -24,7 +24,7 @@ public class EssentialsPlus : LazyPlugin public override string Description => GetString("增强版Essentials"); public override string Name => System.Reflection.Assembly.GetExecutingAssembly().GetName().Name!; - public override Version Version => new Version(1, 0, 9); + public override Version Version => new Version(1, 1, 0); public EssentialsPlus(Main game) diff --git a/src/EssentialsPlus/README.md b/src/EssentialsPlus/README.md index 9a197b910..9d325d845 100644 --- a/src/EssentialsPlus/README.md +++ b/src/EssentialsPlus/README.md @@ -75,6 +75,8 @@ ``` ## 更新日志 +### v1.1.0 +- Tpallow默认允许传送 ### v1.0.9 - 数据库记录玩家tpallow状态 ### v1.0.7 diff --git a/src/Ezperm/Ezperm.csproj b/src/Ezperm/Ezperm.csproj index 606c2b11f..6a1afdace 100644 --- a/src/Ezperm/Ezperm.csproj +++ b/src/Ezperm/Ezperm.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/LazyAPI/Attributes/CommonAttribute.cs b/src/LazyAPI/Attributes/CommonAttribute.cs index 65d82eb99..74a6626a1 100644 --- a/src/LazyAPI/Attributes/CommonAttribute.cs +++ b/src/LazyAPI/Attributes/CommonAttribute.cs @@ -54,4 +54,14 @@ public class AliasAttribute(params string[] aliases) : Attribute public HashSet alias = [.. aliases]; } +[AttributeUsage(AttributeTargets.Class)] +public class HelpTextAttribute(string helpText) : Attribute +{ + public string helpText = helpText; +} +[AttributeUsage(AttributeTargets.Method)] +public class UsageAttribute(string usage) : Attribute +{ + public string usage = usage; +} \ No newline at end of file diff --git a/src/LazyAPI/Commands/Command.HelpCommand.cs b/src/LazyAPI/Commands/Command.HelpCommand.cs index 79d261d37..2933d9c0e 100644 --- a/src/LazyAPI/Commands/Command.HelpCommand.cs +++ b/src/LazyAPI/Commands/Command.HelpCommand.cs @@ -11,7 +11,7 @@ public HelpCommand(Command parent, string infoPrefix) { this.parent = parent; this.permissions = []; - this.info = infoPrefix + "help"; + this.usage = GetString($"{infoPrefix}help - list available usages"); } public override ParseResult TryParse(CommandArgs args, int current) @@ -27,7 +27,9 @@ public override ParseResult TryParse(CommandArgs args, int current) } args.Player.SendInfoMessage(GetString("available usage:")); - foreach (var sub in this.parent._dict.Values.SelectMany(subs => subs).Concat(this.parent._main).Distinct() + foreach (var sub in this.parent._dict.Values + .SelectMany(subs => subs) + .Concat(this.parent._main).Distinct() .Where(sub => sub.CanExec(args.Player))) { args.Player.SendInfoMessage(sub.ToString()); diff --git a/src/LazyAPI/Commands/Command.cs b/src/LazyAPI/Commands/Command.cs index 93067a022..2c41f0911 100644 --- a/src/LazyAPI/Commands/Command.cs +++ b/src/LazyAPI/Commands/Command.cs @@ -11,7 +11,7 @@ internal partial class Command : CommandBase public Command(MemberInfo type, string infoPrefix) : base(type) { - this.info = $"{infoPrefix} <...>"; + this.usage = CommandHelper.GetCommandUsage(type) ?? $"{infoPrefix} <...>"; this._infoPrefix = infoPrefix; } diff --git a/src/LazyAPI/Commands/CommandBase.cs b/src/LazyAPI/Commands/CommandBase.cs index 66d73e7a6..51bc639a2 100644 --- a/src/LazyAPI/Commands/CommandBase.cs +++ b/src/LazyAPI/Commands/CommandBase.cs @@ -17,12 +17,12 @@ protected internal readonly struct ParseResult(CommandBase current, int num) protected string[] permissions; private readonly bool _realPlayer; - protected string? info; + internal string? usage; public abstract ParseResult TryParse(CommandArgs args, int current); public override string? ToString() { - return this.info; + return this.usage; } protected CommandBase(MemberInfo member) @@ -68,6 +68,6 @@ protected bool CheckPlayer(TSPlayer plr) } protected ParseResult GetResult(int num) { - return new(this, num); + return new ParseResult(this, num); } } diff --git a/src/LazyAPI/Commands/CommandHelper.cs b/src/LazyAPI/Commands/CommandHelper.cs index cace62b91..12fc5c706 100644 --- a/src/LazyAPI/Commands/CommandHelper.cs +++ b/src/LazyAPI/Commands/CommandHelper.cs @@ -54,6 +54,7 @@ private static Command BuildTree(Type type, string prefix) { var al = GetAlias(func).ToArray(); CommandBase sub = func.GetCustomAttribute() != null ? new FlexibleCommand(func, prefix + AliasToString(al)) : new SingleCommand(func, prefix + AliasToString(al)); + foreach (var alias in al) { result.Add(alias, sub); @@ -68,6 +69,11 @@ private static Command BuildTree(Type type, string prefix) private static void ParseCommand(Command tree, CommandArgs args) { + if (args.Parameters.Count == 0) + { + args.Parameters.Add("help"); + } + var result = tree.TryParse(args, 0); if (result.unmatched == 0) { @@ -96,6 +102,16 @@ private static IEnumerable GetCommandAlias(MemberInfo info) yield return info.Name.ToLower(); } + + internal static string? GetCommandUsage(MemberInfo info) + { + return info.GetCustomAttributes().Select(a => a.usage).FirstOrDefault(); + } + + private static string GetCommandHelpText(MemberInfo info) + { + return info.GetCustomAttributes().Select(a => a.helpText).FirstOrDefault() ?? GetString("No help available."); + } internal static string[] Register(Type type) @@ -105,10 +121,14 @@ internal static string[] Register(Type type) Console.WriteLine($"Command `{type.FullName}` should be static"); } var names = GetCommandAlias(type).ToArray(); + var helpText = GetCommandHelpText(type); var tree = BuildTree(type, AliasToString(names)); - + TShockAPI.Commands.ChatCommands.Add(new TShockAPI.Command(args => ParseCommand(tree, args), - names)); + names) + { + HelpText = helpText + }); return names; } diff --git a/src/LazyAPI/Commands/CommandParser.cs b/src/LazyAPI/Commands/CommandParser.cs index a0b1805d4..353a92ef6 100644 --- a/src/LazyAPI/Commands/CommandParser.cs +++ b/src/LazyAPI/Commands/CommandParser.cs @@ -77,13 +77,13 @@ private static bool TryParseAccount(string arg, out object obj) private static readonly Dictionary friendlyName = new() { - [typeof(bool)] = "bool", - [typeof(int)] = "int", - [typeof(long)] = "long", - [typeof(string)] = "str", - [typeof(DateTime)] = "date", - [typeof(TSPlayer)] = "player", - [typeof(UserAccount)] = "account" + [typeof(bool)] = GetString("bool"), + [typeof(int)] = GetString("int"), + [typeof(long)] = GetString("long"), + [typeof(string)] = GetString("str"), + [typeof(DateTime)] = GetString("date"), + [typeof(TSPlayer)] = GetString("player"), + [typeof(UserAccount)] = GetString("account") }; public static Parser GetParser(Type type) diff --git a/src/LazyAPI/Commands/FlexibleCommand.cs b/src/LazyAPI/Commands/FlexibleCommand.cs index 9d7a1a967..fdeb7cce0 100644 --- a/src/LazyAPI/Commands/FlexibleCommand.cs +++ b/src/LazyAPI/Commands/FlexibleCommand.cs @@ -1,33 +1,39 @@ using MonoMod.Utils; -using System; -using System.Collections.Generic; -using System.Linq; using System.Reflection; using System.Text; -using System.Threading.Tasks; using TShockAPI; namespace LazyAPI.Commands; internal class FlexibleCommand : CommandBase { private readonly CommandParser.Parser[] argParsers; + private readonly (CommandParser.Parser, object?)[] defaultParsers; private readonly FastReflectionHelper.FastInvoker method; public FlexibleCommand(MethodInfo method, string infoPrefix) : base(method) { var param = method.GetParameters(); var ap = new List(); + var dp = new List<(CommandParser.Parser, object?)>(); var sb = new StringBuilder(); sb.Append(infoPrefix); foreach (var p in param.Skip(1)) { - ap.Add(CommandParser.GetParser(p.ParameterType)); - sb.Append($"<{p.Name}: {CommandParser.GetFriendlyName(p.ParameterType)}> "); + if (p.IsOptional) + { + dp.Add((CommandParser.GetParser(p.ParameterType), p.DefaultValue)); + sb.Append(@$"[{p.Name}:{CommandParser.GetFriendlyName(p.ParameterType)}] "); + } + else + { + ap.Add(CommandParser.GetParser(p.ParameterType)); + sb.Append($"<{p.Name}:{CommandParser.GetFriendlyName(p.ParameterType)}> "); + } } - this.argParsers = [.. ap]; - this.info = sb.ToString(); + this.defaultParsers = [.. dp]; + this.usage = CommandHelper.GetCommandUsage(method) ?? sb.ToString(); this.method = method.GetFastInvoker(); } @@ -35,19 +41,35 @@ public override ParseResult TryParse(CommandArgs args, int current) { var p = args.Parameters; var n = this.argParsers.Length; + var d = this.defaultParsers.Length; if (p.Count < n + current) { return this.GetResult(Math.Abs(n + current - p.Count)); } - var a = new object?[n + 1]; + var a = new object?[n + d + 1]; a[0] = args; var unmatched = this.argParsers.Where((t, i) => !t(p[current + i], out a[i + 1])).Count(); if (unmatched != 0) { return this.GetResult(unmatched); } - + if (this.defaultParsers.Where((t, i) => + { + var (k, v) = t; + if (p.Count <= n + i + 1) + { + a[n + i + 1] = v; + return false; + } + else + { + return !k(p[current + n + i], out a[n + i + 1]); + } + }).Any()) + { + return this.GetResult(0); + } if (this.CheckPlayer(args.Player)) { this.method(null, a); diff --git a/src/LazyAPI/Commands/SingleCommand.cs b/src/LazyAPI/Commands/SingleCommand.cs index 225510e78..4f072b540 100644 --- a/src/LazyAPI/Commands/SingleCommand.cs +++ b/src/LazyAPI/Commands/SingleCommand.cs @@ -24,7 +24,7 @@ public SingleCommand(MethodInfo method, string infoPrefix) : base(method) } this.argParsers = [.. ap]; - this.info = sb.ToString(); + this.usage = CommandHelper.GetCommandUsage(method) ?? sb.ToString(); this.method = method.GetFastInvoker(); } diff --git a/src/LazyAPI/Extensions/TSPlayerExtension.cs b/src/LazyAPI/Extensions/TSPlayerExtension.cs index 548e5de4b..33b5d77cb 100644 --- a/src/LazyAPI/Extensions/TSPlayerExtension.cs +++ b/src/LazyAPI/Extensions/TSPlayerExtension.cs @@ -26,6 +26,27 @@ public static void SendPlayerSlot(this TSPlayer player, int slot) player.SendData(PacketTypes.PlayerSlot, "", slot); } + public static void ExecCommand(this TSPlayer player, string cmd) + { + try + { + player.tempGroup = new SuperAdminGroup(); + TShockAPI.Commands.HandleCommand(player, cmd.SFormat(player.Name)); + } + finally + { + player.tempGroup = null; + } + } + + public static void ExecCommand(this TSPlayer player, IEnumerable cmds) + { + foreach (var cmd in cmds) + { + player.ExecCommand(cmd); + } + } + public static Dictionary GetProgress(this TSPlayer Player) { return GameProgress.DefaultProgressNames diff --git a/src/LazyAPI/PluginContainer.cs b/src/LazyAPI/PluginContainer.cs index aa8c8b9d2..8e26889a1 100644 --- a/src/LazyAPI/PluginContainer.cs +++ b/src/LazyAPI/PluginContainer.cs @@ -10,7 +10,7 @@ public class PluginContainer : LazyPlugin { public override string Author => "cc004 & members of UnrealMultiple"; - public override Version Version => new Version(1, 0, 2, 1); + public override Version Version => new Version(1, 0, 2, 2); public PluginContainer(Main game) : base(game) { } public override void Initialize() diff --git a/src/TrCDK/Command.cs b/src/TrCDK/Command.cs new file mode 100644 index 000000000..97ccc26b3 --- /dev/null +++ b/src/TrCDK/Command.cs @@ -0,0 +1,169 @@ +using LazyAPI.Attributes; +using LazyAPI.Extensions; +using System.Text; +using TShockAPI; + +namespace TrCDK; + +[Command("cdk")] +[Permissions("cdk.use")] +[HelpText("CDK系统主命令")] +public class Command +{ + [Alias("give")] + [Permissions("cdk.give")] + [Usage("cdk give <玩家名> <指令列表> - 给玩家CDK奖励")] + public static void Give(CommandArgs args, TSPlayer? player, string cmd) + { + if(player == null) + { + args.Player.SendErrorMessage(GetString("[c/ffd700:玩家不存在]")); + return; + } + var cmds = cmd.Split(','); + if (cmds.Length > 0) + { + args.Player.ExecCommand(cmds); + args.Player.SendSuccessMessage(GetString($"[c/ffd700:已给予玩家 {player.Name} CDK奖励]")); + } + else + { + args.Player.SendErrorMessage(GetString("[c/ffd700:指令不能为空]")); + } + } + + [Alias("update")] + [Flexible] + [Permissions("cdk.update")] + [Usage("cdk update <使用次数> <过期时间> <指令> [组限制] [玩家限制] --- 更新CDK信息")] + public static void Update(CommandArgs args, string cdkname, int usetime, long utiltime, string cmds = "" ,string grouplimit = "", string playerlimit = "") + { + var cdkData = CDK.GetData(cdkname); + if (cdkData == null) + { + args.Player.SendErrorMessage(GetString("[c/ffd700:CDK不存在]")); + return; + } + CDK.Update(cdkname, usetime, utiltime, grouplimit, playerlimit, cdkData.Used, cmds); + args.Player.SendSuccessMessage(GetString("[c/ffd700:CDK更新成功]")); + } + + [Alias("del")] + [Permissions("cdk.del")] + [Usage("cdk del - 删除指定CDK")] + public static void Delete(CommandArgs args, string cdkname) + { + if (CDK.GetData(cdkname) == null) + { + args.Player.SendErrorMessage(GetString("[c/ffd700:CDK不存在]")); + return; + } + CDK.DelCDK(cdkname); + args.Player.SendSuccessMessage(GetString("[c/ffd700:CDK删除成功]")); + } + + [Alias("add")] + [Flexible] + [Permissions("cdk.add")] + [Usage("cdk add <使用次数> <过期时间> <指令> [组限制] [玩家限制] - 添加新CDK")] + public static void Add(CommandArgs args, string cdkname, int usetime, long utiltime, string cmds, string grouplimit = "", string playerlimit = "") + { + if (CDK.Insert(cdkname, usetime, utiltime, grouplimit, playerlimit, cmds)) + { + args.Player.SendSuccessMessage(GetString("[c/ffd700:CDK添加成功]")); + } + else + { + args.Player.SendErrorMessage(GetString("[c/ffd700:CDK添加失败]")); + } + } + + [Alias("list")] + [Permissions("cdk.list")] + [Usage("cdk list - 列出所有CDK")] + public static void List(CommandArgs args) + { + var cdkList = CDK.GetAllData(); + if (cdkList.Length == 0) + { + args.Player.SendInfoMessage(GetString("[c/ffd700:没有可用的CDK]")); + return; + } + var sb = new StringBuilder(); + sb.AppendLine(GetString("[c/ffd700:当前可用的CDK列表]")); + foreach (var cdk in cdkList) + { + sb.Append(GetString($"[c/ffd700:{cdk.Name}] [c/00FF00:剩余使用次数: {cdk.Usetime}] [c/ffd700:过期时间: {new DateTime(cdk.Utiltime).ToLocalTime()}] ")); + if(cdk.Playerlimit != "") + { + sb.Append(GetString($"[c/ffd700:玩家限制: {cdk.Playerlimit}] ")); + } + if(cdk.Grouplimit != "") + { + sb.Append(GetString($"[c/ffd700:组限制: {cdk.Grouplimit}] ")); + } + if(cdk.Cmds != "") + { + sb.Append(GetString($"[c/ffd700:指令: {cdk.Cmds}] ")); + } + if(cdk.Used != "") + { + sb.Append(GetString($"[c/ffd700:已使用玩家: {cdk.Used}] ")); + } + sb.AppendLine(); + } + args.Player.SendInfoMessage(sb.ToString().Trim()); + } + + [Alias("use")] + [RealPlayer] + [Usage("cdk use - 兑换CDK礼包")] + public static void Use(CommandArgs args, string cdk) + { + var cdkData = CDK.GetData(cdk); + if (cdkData == null) + { + args.Player.SendInfoMessage(GetString("[c/ffd700:CDK不存在或已失效]")); + return; + } + + if (cdkData.Playerlimit != "") + { + if (!cdkData.Playerlimit.Contains(args.Player.Name)) + { + args.Player.SendInfoMessage(GetString("[c/ffd700:你不在该CDK的领取名单中]")); + return; + } + } + if (cdkData.Grouplimit != "") + { + if (!cdkData.Grouplimit.Contains(args.Player.Group.Name)) + { + args.Player.SendInfoMessage(GetString("[c/ffd700:你所在的组不能领取该CDK]")); + return; + } + } + if (cdkData.Usetime < 1) + { + args.Player.SendInfoMessage(GetString("[c/ffd700:你手慢了, 该CDK已经被领完]")); + return; + } + var time2 = Convert.ToDateTime(DateTime.Now.ToString()).Ticks; + var min = (cdkData.Utiltime - time2) / 10000000; + if (min <= 0) + { + args.Player.SendInfoMessage(GetString("[c/ffd700:你来晚了, 该CDK已经过期了]")); + return; + } + if (cdkData.Used.Contains(args.Player.Name)) + { + args.Player.SendInfoMessage(GetString("[c/ffd700:已经领取过了,不能太贪心哦]")); + return; + } + var strcmd = cdkData.Cmds.Replace("[plr]", args.Player.Name); + var cmds = strcmd.Split(','); + args.Player.ExecCommand(cmds); + CDK.Update(cdkData.Name, cdkData.Usetime - 1, cdkData.Utiltime, cdkData.Grouplimit, cdkData.Playerlimit, (cdkData.Used == "") ? args.Player.Name : cdkData.Used + "," + args.Player.Name, cdkData.Cmds); + args.Player.SendSuccessMessage(GetString("[c/ffd700:CDK兑换成功!]")); + } +} diff --git a/src/TrCDK/Data.cs b/src/TrCDK/Data.cs new file mode 100644 index 000000000..d26dd90d2 --- /dev/null +++ b/src/TrCDK/Data.cs @@ -0,0 +1,83 @@ +using Microsoft.Data.Sqlite; +using LinqToDB.Mapping; +using LazyAPI.Database; +using LinqToDB; + +namespace TrCDK; + +[Table("CDK")] +public class CDK : RecordBase +{ + [Column("name"), PrimaryKey, NotNull] + public string Name { get; set; } = string.Empty; + + [Column("usetime")] + public int Usetime { get; set; } + + [Column("utiltime")] + public long Utiltime { get; set; } + + [Column("grouplimit")] + public string Grouplimit { get; set; } = string.Empty; + + [Column("playerlimit")] + public string Playerlimit { get; set; } = string.Empty; + + [Column("used")] + public string Used { get; set; } = string.Empty; + + [Column("cmds")] + public string Cmds { get; set; } = string.Empty; + + private static readonly Context _context = Db.Context("CDK"); + + public static bool Insert(string CDKname, int Usetime, long Utiltime, string Grouplimit, string Playerlimit, string Cmds) + { + return _context.Insert(new CDK + { + Name = CDKname, + Usetime = Usetime, + Utiltime = Utiltime, + Grouplimit = Grouplimit, + Playerlimit = Playerlimit, + Used = "", + Cmds = Cmds + }) == 1; + } + + public static void Update(string CDKname, int Usetime, long Utiltime, string Grouplimit, string Playerlimit, string Used, string Cmds) + { + var cdk = _context.Records.FirstOrDefault(c => c.Name == CDKname); + if (cdk != null) + { + cdk.Usetime = Usetime; + cdk.Utiltime = Utiltime; + cdk.Grouplimit = Grouplimit; + cdk.Playerlimit = Playerlimit; + cdk.Used = Used; + cdk.Cmds = Cmds; + _context.Update(cdk); + } + } + + public static CDK? GetData(string name) + { + return _context.Records.FirstOrDefault(c => c.Name == name); + } + + public static CDK[] GetAllData() + { + return [.. _context.Records]; + } + + public static bool DelCDK(string name) + { + var cdk = _context.Records.FirstOrDefault(c => c.Name == name); + if (cdk != null) + { + _context.Delete(cdk); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/TrCDK/Main.cs b/src/TrCDK/Main.cs new file mode 100644 index 000000000..ff1c190d0 --- /dev/null +++ b/src/TrCDK/Main.cs @@ -0,0 +1,29 @@ +using TShockAPI; +using Terraria; +using TerrariaApi.Server; +using System.Globalization; +using Microsoft.Xna.Framework; +using LazyAPI.Extensions; +using LazyAPI; + +namespace TrCDK; + +[ApiVersion(2, 1)] +public class TrCDK : LazyPlugin +{ + public override string Author => "Jonesn"; + public override string Description => GetString("CDK系统"); + public override string Name => "TrCDK"; + public override Version Version => new Version(1, 0, 0, 0); + public TrCDK(Main game) : base(game) { } + + public override void Initialize() + { + + } + + protected override void Dispose(bool Disposing) + { + + } +} \ No newline at end of file diff --git a/src/TrCDK/README.en-US.md b/src/TrCDK/README.en-US.md new file mode 100644 index 000000000..07cb4fc06 --- /dev/null +++ b/src/TrCDK/README.en-US.md @@ -0,0 +1,37 @@ +# TrCDK CDK +- Author: Jonesn +- Source: ARK Server +- Can return the player's last death location with customizable cooldown time. +- Administrators can create, delete, and update CDKs, and players can redeem (execute commands) rewards using valid CDKs. +- CDKs can set usage times, expiration time, group restrictions, and player restrictions. + + +## Commands +| Syntax | Permission | Description | +| --- | --- | --- | +| /cdk `` | cdk.use | Players redeem CDK packages. | +| /cdkloadall | cdk.admin.loadall | Display all CDK lists. | +| /cdkadd `` `` `` `` `` `` | cdk.admin.add | Add a new CDK. | +| /cdkdel `` | cdk.admin.del | Delete the specified CDK. | +| /cdkupdate `` `` `` `` `` `` `` | cdk.admin.update | Update CDK information. | +| /cdkgive `` `` | cdk.admin.give | Grant CDK rewards to a player. | + + +### Notes +- **/cdkadd and /cdkupdate**: Expiry time format is `yyyy-MM-ddThh:mm`, e.g., `2024-12-31T23:59`. Group and player limits are separated by commas; use `none` for no restrictions. +- **/cdkgive**: Command lists are separated by commas, e.g., `/give 4956 [plr] 1,/heal [plr]`. + + +## Configuration +> Database file location: tshock/TrCDK.sqlite + + +## Change Log +### v1.0.0.0 +Initial release. + + +## Feedback +- Priority: Submit issues -> Shared plugin library: https://github.com/UnrealMultiple/TShockPlugin +- Secondary: TShock Official Group: 816771079 +- Less frequently checked but acceptable: Chinese communities trhub.cn, bbstr.net \ No newline at end of file diff --git a/src/TrCDK/README.md b/src/TrCDK/README.md new file mode 100644 index 000000000..d717309a3 --- /dev/null +++ b/src/TrCDK/README.md @@ -0,0 +1,34 @@ +# TrCDK CDK系统插件 +- 作者: Jonesn +- 出处: ARK服务器 +- 可以返回上次玩家的死亡地点,可自定义冷却时间 +- 管理员能创建、删除、更新 CDK,玩家可使用有效 CDK 兑换(执行指令)奖励。 +- CDK可以设置使用次数、过期时间、组限制、玩家限制。 + +## 指令 +| 语法 | 权限 | 说明 | +|-------------------------------------------------------------|-------------------|-------------| +| /cdk use | cdk.use | 玩家兑换 CDK 礼包 | +| /cdk list | cdk.admin.loadall | 显示所有 CDK 列表 | +| /cdk add `` `<使用次数>` `<过期时间>` `<指令>` `[组限制]` `[玩家限制]` | cdk.admin.add | 添加新 CDK | +| /cdk del `` | cdk.admin.del | 删除指定 CDK | +| /cdk update `` `<使用次数>` `<过期时间>` `<指令>` `[组限制]` `[玩家限制]` | cdk.admin.update | 更新 CDK 信息 | +| /cdk give `<玩家名>` `<指令列表>` | cdk.admin.give | 给玩家 CDK 奖励 | + +### 注意事项 +- **/cdkadd 和 /cdkupdate**:过期时间格式 `yyyy-MM-ddThh:mm`,如 `2024-12-31T23:59`。组和玩家限制用逗号分隔,不限制填 `none`。 +- **/cdkgive**:指令列表用逗号分隔,如 `/give 4956 [plr] 1,/heal [plr]`。 + +## 配置 +> 数据库文件位置:tshock/TrCDK.sqlite + + +## 更新日志 + +### v1.0.0.0 +- 初始版本发布 + +## 反馈 +- 优先发issued -> 共同维护的插件库:https://github.com/UnrealMultiple/TShockPlugin +- 次优先:TShock官方群:816771079 +- 大概率看不到但是也可以:国内社区trhub.cn ,bbstr.net \ No newline at end of file diff --git a/src/TrCDK/TrCDK.csproj b/src/TrCDK/TrCDK.csproj new file mode 100644 index 000000000..1005d2601 --- /dev/null +++ b/src/TrCDK/TrCDK.csproj @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/TrCDK/manifest.json b/src/TrCDK/manifest.json new file mode 100644 index 000000000..e41c9eaf9 --- /dev/null +++ b/src/TrCDK/manifest.json @@ -0,0 +1,11 @@ +{ + "README.en-US": { + "Description": "Enter redemption code (CDK) to execute commands" + }, + "README.es-ES": { + "Description": "Introduce el código de canje (CDK) para ejecutar comandos" + }, + "README": { + "Description": "输入兑换码执行指令" + } +} \ No newline at end of file