Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加插件:PersonalPermission 玩家单独权限 #40

Merged
merged 2 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions PersonalPermission/DB.cs
Original file line number Diff line number Diff line change
@@ -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<string> GetPermissions(int id)
{
using (var reader = DbExt.QueryReader(TShock.DB, $"SELECT * FROM PersonalPermission WHERE UserID='{id}';"))
{
var list = new List<string>();
if (reader.Read())
{
try {
var text = reader.Get<string>("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<int, List<string>> GetAllPermissions()
{
using (var reader = DbExt.QueryReader(TShock.DB, $"SELECT * FROM PersonalPermission;"))
{
var list = new Dictionary<int, List<string>>();
while (reader.Read())
{
try
{
var permissions = new List<string>();
var text = reader.Get<string>("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<int>("UserID"), permissions);
}
catch (Exception ex) { TShock.Log.ConsoleError($"[PersonalPermission] 读取数据库时发生错误.\n{ex}"); }
}
return list;
}
}
public static bool SetPermissions(int id, List<string> 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;
}
}
}
218 changes: 218 additions & 0 deletions PersonalPermission/PPMain.cs
Original file line number Diff line number Diff line change
@@ -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<string>() : 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<string> 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<Group>("PersonalPermission");
group.Parent = args.Player.Group;
args.Result = args.Player.GetData<Group>("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<string>();
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<Group>("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<Group>("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;
}
}
}
5 changes: 5 additions & 0 deletions PersonalPermission/PersonalPermission.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\template.targets" />

</Project>
28 changes: 28 additions & 0 deletions PersonalPermission/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# PersonalPermission 玩家单独权限

- 作者: Megghy,肝帝熙恩更新1449
- 出处: [github](https://github.com/Megghy/PersonalPermission)
- 以给玩家给予一个单独的权限而不是添加给所在用户组.​
- 对于开发者:可使用 <玩家对象(TSPlayer)>.GetData<Group>("PersonalPermission"); 来获取一个包含独立权限的用户组对象, 同时直接调用 .HasPermission 也会自动判断权限.


## 更新日志

```
暂无
```

## 指令

| 语法 | 权限 | 说明 |
| -------------- | :-----------------: | :------: |
| /pp | personalpermission.admin | 为玩家添/删加权限等指令|

## 配置

```
暂无
```
## 反馈
- 共同维护的插件库:https://github.com/THEXN/TShockPlugin/
- 国内社区trhub.cn 或 TShock官方群等
10 changes: 10 additions & 0 deletions Plugin.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | 决斗系统 | 无 |
Expand All @@ -77,3 +77,4 @@
| [EssentialsPlus](EssentialsPlus/README.md) | 更多管理指令 | 无 |
| [ShowArmors](ShowArmors/README.md) | 展示装备栏 | 无 |
| [VeinMiner](VeinMiner/README.md) | 连锁挖矿 | 无 |
| [PersonalPermission](PersonalPermission/README.md) | 为玩家单独设置权限 | 无 |
Loading