From 512881afdd286026c6d8600625e0b186dd7849f7 Mon Sep 17 00:00:00 2001 From: xien <2383759126@qq.com> Date: Sun, 21 Apr 2024 16:13:18 +0800 Subject: [PATCH 1/2] =?UTF-8?q?add=20=E6=B7=BB=E5=8A=A0=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=20PersonalPermission=20=E7=8E=A9=E5=AE=B6=E5=8D=95=E7=8B=AC?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PersonalPermission/DB.cs | 96 ++++++++ PersonalPermission/PPMain.cs | 218 +++++++++++++++++++ PersonalPermission/PersonalPermission.csproj | 5 + PersonalPermission/README.md | 28 +++ Plugin.sln | 10 + 5 files changed, 357 insertions(+) create mode 100644 PersonalPermission/DB.cs create mode 100644 PersonalPermission/PPMain.cs create mode 100644 PersonalPermission/PersonalPermission.csproj create mode 100644 PersonalPermission/README.md diff --git a/PersonalPermission/DB.cs b/PersonalPermission/DB.cs new file mode 100644 index 00000000..2b3b6af9 --- /dev/null +++ b/PersonalPermission/DB.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using TShockAPI; +using TShockAPI.DB; + +namespace PersonalPermission +{ + class DB + { + public static void TryCreateTable() + { + try + { + SqlTable sqlTable = new SqlTable("PersonalPermission", new SqlColumn[] + { + new SqlColumn("UserID", MySql.Data.MySqlClient.MySqlDbType.Int32){ Primary = true }, + new SqlColumn("Permissions", MySql.Data.MySqlClient.MySqlDbType.Text) + }); + IDbConnection db = TShock.DB; + IQueryBuilder queryBuilder2; + if (DbExt.GetSqlType(TShock.DB) != SqlType.Sqlite) + { + IQueryBuilder queryBuilder = new MysqlQueryCreator(); + queryBuilder2 = queryBuilder; + } + else + { + IQueryBuilder queryBuilder = new SqliteQueryCreator(); + queryBuilder2 = queryBuilder; + } + new SqlTableCreator(db, queryBuilder2).EnsureTableStructure(sqlTable); + } + catch (Exception ex) { TShock.Log.Error(ex.Message); } + } + public static bool AddUser(int id) + { + try { return DbExt.Query(TShock.DB, $"INSERT INTO PersonalPermission (UserID) VALUES ({id});") != -1; } + catch (Exception ex) { TShock.Log.ConsoleError($"添加玩家信息失败.\n" + ex); return false; } + } + public static List GetPermissions(int id) + { + using (var reader = DbExt.QueryReader(TShock.DB, $"SELECT * FROM PersonalPermission WHERE UserID='{id}';")) + { + var list = new List(); + if (reader.Read()) + { + try { + var text = reader.Get("Permissions") ?? ""; + if (text.Contains(",")) + { + text.Split(',').ForEach(p => { if (!list.Contains(p)) list.Add(p); }); + } + else if (!string.IsNullOrWhiteSpace(text)) list.Add(text); + } + catch (Exception ex) { TShock.Log.ConsoleError($"[PersonalPermission] 读取数据库时发生错误.\n{ex}"); } + } + else AddUser(id); + return list; + } + } + public static Dictionary> GetAllPermissions() + { + using (var reader = DbExt.QueryReader(TShock.DB, $"SELECT * FROM PersonalPermission;")) + { + var list = new Dictionary>(); + while (reader.Read()) + { + try + { + var permissions = new List(); + var text = reader.Get("Permissions") ?? ""; + if (text.Contains(",")) + { + text.Split(',').ForEach(p => { if (!permissions.Contains(p)) permissions.Add(p); }); + } + else if (!string.IsNullOrWhiteSpace(text)) permissions.Add(text); + list.Add(reader.Get("UserID"), permissions); + } + catch (Exception ex) { TShock.Log.ConsoleError($"[PersonalPermission] 读取数据库时发生错误.\n{ex}"); } + } + return list; + } + } + public static bool SetPermissions(int id, List list) + { + if (DbExt.Query(TShock.DB, $"UPDATE PersonalPermission SET Permissions=@0 WHERE UserID={id};", new object[] { string.Join(",", list) }) != -1) + { + return true; + } + TShock.Log.ConsoleError("保存玩家权限失败."); + return false; + } + } +} diff --git a/PersonalPermission/PPMain.cs b/PersonalPermission/PPMain.cs new file mode 100644 index 00000000..bd305c43 --- /dev/null +++ b/PersonalPermission/PPMain.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Terraria; +using TerrariaApi.Server; +using TShockAPI; +using TShockAPI.DB; +using TShockAPI.Hooks; + +namespace PersonalPermission +{ + [ApiVersion(2, 1)] + public class PPMain : TerrariaPlugin + { + public override string Name => "PersonalPermission"; + public override Version Version => new Version(1, 1, 0, 0); + public override string Author => "Megghy,肝帝熙恩更新1449"; + public override string Description => "允许为玩家单独设置权限."; + public PPMain(Main game) : base(game) + { + } + public override void Initialize() + { + DB.TryCreateTable(); + ServerApi.Hooks.GamePostInitialize.Register(this, OnPostInitialize); + } + public void OnPostInitialize(EventArgs args) + { + ServerApi.Hooks.ServerJoin.Register(this, OnJoin, int.MinValue); + PlayerHooks.PlayerPermission += OnPermissionCheck; + GeneralHooks.ReloadEvent += OnReload; + Commands.ChatCommands.Add(new Command("personalpermission.admin", PPCommand, "pp")); + } + void OnJoin(JoinEventArgs args) + { + var plr = TShock.Players[args.Who]; + var account = TShock.UserAccounts.GetUserAccountByName(plr.Name); + plr.SetData("PersonalPermission", GetPPGroup(account == null ? new List() : DB.GetPermissions(account.ID))); + } + void OnReload(ReloadEventArgs args) + { + TShock.Players.Where(p => p != null && p.Account != null).ForEach(p => p.SetData("PersonalPermission", GetPPGroup(DB.GetPermissions(p.Account.ID)))); + TShock.Log.ConsoleInfo("已重载玩家个人权限."); + } + Group GetPPGroup(List list) + { + var group = new Group("PersonalPermission"); + list?.ForEach(p => group.AddPermission(p)); + return group; + } + public void OnPermissionCheck(PlayerPermissionEventArgs args) + { + try + { + var plr = args.Player; + if (!plr.RealPlayer || plr.Group.TotalPermissions.Contains("*") || plr.Group.Name == "superadmin") + { + args.Result = PermissionHookResult.Granted; + return; + } + var group = args.Player.GetData("PersonalPermission"); + group.Parent = args.Player.Group; + args.Result = args.Player.GetData("PersonalPermission").HasPermission(args.Permission) + ? PermissionHookResult.Granted + : PermissionHookResult.Denied; + } + catch (Exception ex) { TShock.Log.ConsoleError(ex.Message); args.Result = PermissionHookResult.Denied; } + } + public void PPCommand(CommandArgs args) + { + var plr = args.Player; + var cmd = args.Parameters; + try + { + + if (cmd.Count >= 1) + { + switch (cmd[0].ToLower()) + { + case "add": + if (cmd.Count >= 3) + { + var acclist = TShock.UserAccounts.GetUserAccountsByName(cmd[1]); + if (acclist.Count > 1) + { + plr.SendMultipleMatchError(acclist); + } + else if (acclist.Count == 0) + { + plr.SendErrorMessage($"未找到名称中包含 {cmd[1]} 的玩家."); + } + else + { + Add(acclist.First(), cmd[2]); + } + } + else + { + plr.SendInfoMessage($"无效的命令. /pp add [C/66E5B5:玩家名] [C/66E5B5:权限]"); + } + break; + case "del": + if (cmd.Count >= 3) + { + var acclist = TShock.UserAccounts.GetUserAccountsByName(cmd[1]); + if (acclist.Count > 1) + { + plr.SendMultipleMatchError(acclist); + } + else if (acclist.Count == 0) + { + plr.SendErrorMessage($"未找到名称中包含 {cmd[1]} 的玩家."); + } + else + { + Del(acclist.First(), cmd[2]); + } + } + else + { + plr.SendInfoMessage($"无效的命令. /pp del [C/66E5B5:玩家名] [C/66E5B5:权限]"); + } + break; + case "list": + if (cmd.Count >= 2) + { + var acclist = TShock.UserAccounts.GetUserAccountsByName(cmd[1]); + if (acclist.Count > 1) + { + plr.SendMultipleMatchError(acclist); + } + else if (acclist.Count == 0) + { + plr.SendErrorMessage($"未找到名称中包含 {cmd[1]} 的玩家."); + } + else + { + var data = DB.GetPermissions(acclist[0].ID); + plr.SendInfoMessage($"玩家 {acclist[0].Name} 的所有权限: ({data.Count} 条)\n{string.Join(", ", data)}"); + } + } + else + { + plr.SendInfoMessage($"无效的命令. /pp list [C/66E5B5:玩家名]"); + } + break; + case "search": + if (cmd.Count >= 2) + { + var list = new List(); + DB.GetAllPermissions().Where(data => data.Value.Contains(cmd[1])).ForEach(data => list.Add((TShock.UserAccounts.GetUserAccountByID(data.Key) ?? new UserAccount()).Name)); + plr.SendInfoMessage($"拥有权限 {cmd[1]} 的所有玩家: ({list.Count} 位)\n{string.Join(", ", list)}"); + } + else + { + plr.SendInfoMessage($"无效的命令. /pp search [C/66E5B5:权限名]"); + } + break; + default: + Help(); + break; + } + } + else + { + Help(); + } + } + catch (Exception ex) { TShock.Log.ConsoleError(ex.Message); } + void Help() + { + plr.SendInfoMessage($"可用命令:\n" + + $"/pp add [C/66E5B5:玩家名] [C/66E5B5:权限]\n" + + $"/pp del [C/66E5B5:玩家名] [C/66E5B5:权限]\n" + + $"/pp list [C/66E5B5:玩家名]\n" + + $"/pp search [C/66E5B5:权限名]\n"); + } + void Add(UserAccount account, string perm) + { + var data = DB.GetPermissions(account.ID); + if (data != null && !data.Contains(perm)) + { + data.Add(perm); + if (DB.SetPermissions(account.ID, data)) + { + TShock.Players.FirstOrDefault(p => p?.Name == account.Name).GetData("PersonalPermission")?.AddPermission(perm); + plr.SendSuccessMessage($"已为玩家 {account.Name} 添加权限 {perm}."); + } + else plr.SendErrorMessage($"添加权限失败."); + } + else plr.SendErrorMessage($"玩家 {account.Name} 已存在权限 {perm}."); + } + void Del(UserAccount account, string perm) + { + var data = DB.GetPermissions(account.ID); + if (data != null && data.Contains(perm)) + { + data.Remove(perm); + if (DB.SetPermissions(account.ID, data)) + { + TShock.Players.FirstOrDefault(p => p?.Name == account.Name).GetData("PersonalPermission")?.RemovePermission(perm); + plr.SendSuccessMessage($"已为玩家 {account.Name} 移除权限 {perm}."); + } + else + plr.SendErrorMessage($"移除权限失败."); + } + else + plr.SendErrorMessage($"玩家 {account.Name} 未存在权限 {perm}."); + } + } + protected override void Dispose(bool disposing) + { + ServerApi.Hooks.ServerJoin.Deregister(this, OnJoin); + PlayerHooks.PlayerPermission -= OnPermissionCheck; + GeneralHooks.ReloadEvent -= OnReload; + } + } +} diff --git a/PersonalPermission/PersonalPermission.csproj b/PersonalPermission/PersonalPermission.csproj new file mode 100644 index 00000000..54932bd7 --- /dev/null +++ b/PersonalPermission/PersonalPermission.csproj @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/PersonalPermission/README.md b/PersonalPermission/README.md new file mode 100644 index 00000000..9e01dc78 --- /dev/null +++ b/PersonalPermission/README.md @@ -0,0 +1,28 @@ +# PersonalPermission 玩家单独权限 + +- 作者: Megghy,肝帝熙恩更新1449 +- 出处: [github](https://github.com/Megghy/PersonalPermission) +- 以给玩家给予一个单独的权限而不是添加给所在用户组.​ +- 对于开发者:可使用 <玩家对象(TSPlayer)>.GetData("PersonalPermission"); 来获取一个包含独立权限的用户组对象, 同时直接调用 .HasPermission 也会自动判断权限. + + +## 更新日志 + +``` +暂无 +``` + +## 指令 + +| 语法 | 权限 | 说明 | +| -------------- | :-----------------: | :------: | +| /pp | personalpermission.admin | 为玩家添/删加权限等指令| + +## 配置 + +``` +暂无 +``` +## 反馈 +- 共同维护的插件库:https://github.com/THEXN/TShockPlugin/ +- 国内社区trhub.cn 或 TShock官方群等 \ No newline at end of file diff --git a/Plugin.sln b/Plugin.sln index 33bce203..b75239dc 100644 --- a/Plugin.sln +++ b/Plugin.sln @@ -102,6 +102,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShowArmors", "ShowArmors\Sh EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VeinMiner", "VeinMiner\VeinMiner.csproj", "{BC20D582-EBEF-4FC4-832C-49EC814CF9A9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PersonalPermission", "PersonalPermission\PersonalPermission.csproj", "{673A34A5-8C67-4909-885F-BD47AF0F58A4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -486,6 +488,14 @@ Global {BC20D582-EBEF-4FC4-832C-49EC814CF9A9}.Release|Any CPU.Build.0 = Release|Any CPU {BC20D582-EBEF-4FC4-832C-49EC814CF9A9}.Release|x64.ActiveCfg = Release|Any CPU {BC20D582-EBEF-4FC4-832C-49EC814CF9A9}.Release|x64.Build.0 = Release|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Debug|x64.ActiveCfg = Debug|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Debug|x64.Build.0 = Debug|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Release|Any CPU.Build.0 = Release|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Release|x64.ActiveCfg = Release|Any CPU + {673A34A5-8C67-4909-885F-BD47AF0F58A4}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From ccad916751b1c7a53126b0893df15444f7d2b38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=82=9D=E5=B8=9D=E7=86=99=E6=81=A9?= <111548550+THEXN@users.noreply.github.com> Date: Sun, 21 Apr 2024 16:15:02 +0800 Subject: [PATCH 2/2] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 00904482..b5aee704 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ | [DataSync](DataSync/README.md) | 进度同步 | 无 | | [ProgressRestrict](ProgressRestrict/README.md) | 超进度检测 | DataSync | | [PacketsStop](PacketsStop/README.md) | 数据包拦截 | 无 | -| [DeathDrop](DeathDrop/README.md) | 怪物死亡随机和自定义掉落物品 | 无 | +| [DeathDrop](DeathDrop/README.md) | 怪物死亡随机和自定义掉落物品 | 无 | | [DTEntryBlock](DTEntryBlock/README.md) | 阻止进入地牢或神庙 | 无 | | [PerPlayerLoot](PerPlayerLoot/README.md) | 玩家战利品单独箱子 | 无 | | [PvPer](PvPer/README.md) | 决斗系统 | 无 | @@ -77,3 +77,4 @@ | [EssentialsPlus](EssentialsPlus/README.md) | 更多管理指令 | 无 | | [ShowArmors](ShowArmors/README.md) | 展示装备栏 | 无 | | [VeinMiner](VeinMiner/README.md) | 连锁挖矿 | 无 | +| [PersonalPermission](PersonalPermission/README.md) | 为玩家单独设置权限 | 无 |