Skip to content

Commit

Permalink
feat: death ranking (死亡排行榜)
Browse files Browse the repository at this point in the history
  • Loading branch information
LaoSparrow committed Jun 20, 2023
1 parent ca8f6d0 commit 5ce19ee
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 2 deletions.
103 changes: 103 additions & 0 deletions PrismBot/InternalPlugins/DeathRanking/DeathRanking.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System.Text;
using System.Text.Json.Serialization;
using Microsoft.EntityFrameworkCore;
using PrismBot.SDK;
using PrismBot.SDK.Data;
using PrismBot.SDK.Extensions;
using PrismBot.SDK.Interfaces;
using PrismBot.SDK.Static;
using Sora.EventArgs.SoraEvent;

namespace PrismBot.InternalPlugins.DeathRanking;

public class DeathRanking : Plugin
{
public override string GetPluginName() => "Death Ranking";

public override string GetVersion() => "1.0.0";

public override string GetAuthor() => "LaoSparrow";

public override string GetDescription() => "死亡排行榜";

public override void OnLoad()
{
CommandManager.RegisterGroupCommand(this, new RankingGroupCommand());
}
}

public class RankingGroupCommand : IGroupCommand
{
private const int PAGE_SIZE = 10;

public string GetCommand() => "死亡排行榜";

public string GetPermission() => "deathranking.list";

public async Task OnPermissionDeniedAsync(string type, GroupMessageEventArgs eventArgs)
{
await eventArgs.SendDefaultPermissionDeniedMessageAsync();
}

public async Task OnPermissionGrantedAsync(string type, GroupMessageEventArgs eventArgs)
{
var args = eventArgs.Message.GetCommandArgs();
if (args.Length < 2)
{
await eventArgs.SourceGroup.SendGroupMessage("用法:死亡排行榜 <服务器标识符> [页数]");
return;
}

var currentPage = 1;
if (args.Length >= 3 && !int.TryParse(args[2], out currentPage))
{
await eventArgs.SourceGroup.SendGroupMessage("页数需为数字并大于0");
return;
}
if (currentPage <= 0)
{
await eventArgs.SourceGroup.SendGroupMessage("页数需为数字并大于0");
return;
}

await using var db = new BotDbContext();
var server = await db.Servers.FirstOrDefaultAsync(x => x.Identity == args[1]);
if (server == null)
{
await eventArgs.SourceGroup.SendGroupMessage($"未找到标识符为 {args[1]} 的服务器。");
return;
}

var result = await server.SendGetToEndpointAsync<DeathRankingRespond>("prismbot/death_ranking", new Dictionary<string, object>
{
{ "token", server.Token }
});
if (result.Ranking == null)
{
await eventArgs.SourceGroup.SendGroupMessage($"服务器发生内部错误 ({nameof(result.Ranking)}值为空)");
return;
}

var sb = new StringBuilder();
sb.AppendFormat("服务器: {0}({1})\n", server.ServerName, server.Identity);
sb.Append("---死亡排行榜---\n");
foreach (var r in result.Ranking.Skip((currentPage - 1) * PAGE_SIZE).Take(PAGE_SIZE))
{
sb.AppendFormat("{0}: {1}\n", r.PlayerName, r.DeathCount);
}

sb.AppendFormat("---页: <{0}/{1}>---", currentPage, result.Ranking.Length / PAGE_SIZE + 1);
await eventArgs.SourceGroup.SendGroupMessage(sb.ToString());
}

public class DeathRankingRespond
{
public class DeathRankingRecord
{
public string PlayerName { get; set; }
public int DeathCount { get; set; }
}

[JsonPropertyName("ranking")] public DeathRankingRecord[]? Ranking { get; set; }
}
}
71 changes: 69 additions & 2 deletions PrismBotTShockAdapter/PrismBotTShockAdapter.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Newtonsoft.Json;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using PrismBotTShockAdapter.Models;
using Rests;
using Terraria;
using TerrariaApi.Server;
using TShockAPI;
using TShockAPI.DB;

namespace PrismBotTShockAdapter;

Expand Down Expand Up @@ -38,7 +40,7 @@ public override void Initialize()
JsonConvert.SerializeObject(new Config()));
TShock.Log.ConsoleWarn("未找到配置文件(tshock/PrismBot/config.json),已自动生成");
}

var elegantWhitelistPath = Path.Combine(AppContext.BaseDirectory, "tshock", "PrismBot", "elegantWhitelist.json");
if (!File.Exists(elegantWhitelistPath))
{
Expand All @@ -48,8 +50,26 @@ public override void Initialize()
TShock.Log.ConsoleWarn("未找到配置文件(tshock/PrismBot/elegantWhitelist.json),已自动生成");
}


// Database Initialization

var tableCreator = new SqlTableCreator(
TShock.DB,
TShock.DB.GetSqlType() == SqlType.Sqlite ? new SqliteQueryCreator() : new MysqlQueryCreator());

var deathRankingTable = new SqlTable("PB_DeathRanking",
new SqlColumn("AccountID", MySqlDbType.Int32) { Primary = true },
new SqlColumn("DeathCount", MySqlDbType.Int32));
tableCreator.EnsureTableStructure(deathRankingTable);


// Registration and Hooking

ServerApi.Hooks.ServerJoin.Register(this, OnJoin);
TShock.RestApi.Register("/player/info", OnPlayerInventory);

TShockAPI.GetDataHandlers.KillMe.Register(OnPlayerDeath);
TShock.RestApi.Register("/prismbot/death_ranking", OnRestDeathRanking);
}

private async void OnJoin(JoinEventArgs args)
Expand Down Expand Up @@ -107,4 +127,51 @@ private object OnPlayerInventory(RestRequestArgs args)
{"inventory", playerInfo.inventory}
};
}

#region Death Ranking

private void OnPlayerDeath(object? sender, GetDataHandlers.KillMeEventArgs e)
{
try
{
var player = TShock.Players[e.PlayerId];
if (player.Account == null)
return;

TShock.DB.Query(
Utils.SwitchDBQuery(
"INSERT INTO PB_DeathRanking (AccountID, DeathCount) VALUES (@0, 1) ON DUPLICATE KEY UPDATE DeathCount=DeathCount+1",
"INSERT INTO PB_DeathRanking (AccountID, DeathCount) VALUES (@0, 1) ON CONFLICT(AccountID) DO UPDATE SET DeathCount=DeathCount+1"),
player.Account.ID);
}
catch (Exception ex)
{
TShock.Log.ConsoleWarn($"[PrismBotAdapter] Exception occur at {nameof(OnPlayerDeath)}, Ex:\n{ex}");
}
}

private object OnRestDeathRanking(RestRequestArgs args)
{
var ranking = new List<dynamic>();
using (var reader =
TShock.DB.QueryReader(
"SELECT Users.Username AS Username, DeathCount FROM PB_DeathRanking INNER JOIN Users ON PB_DeathRanking.AccountID=Users.ID ORDER BY DeathCount DESC"))
{
while (reader.Read())
{
ranking.Add(new
{
PlayerName = reader.Get<string>("Username"),
DeathCount = reader.Get<int>("DeathCount")
});
}
}

return new RestObject
{
{ "ranking", ranking }
};
}

#endregion
}
9 changes: 9 additions & 0 deletions PrismBotTShockAdapter/Utils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using TShockAPI;

namespace PrismBotTShockAdapter;

public static class Utils
{
public static string SwitchDBQuery(string mysqlQuery, string sqliteQuery) =>
TShock.Config.Settings.StorageType.ToLower() == "mysql" ? mysqlQuery : sqliteQuery;
}

0 comments on commit 5ce19ee

Please sign in to comment.