mirror of
https://github.com/Empostor/Empostor.git
synced 2026-10-19 15:51:39 +00:00
Command Description
This commit is contained in:
1 parent
f94c0e052c
commit
0b748eb200
13 files changed
+356
-48
No files matched your search
@@ -30,6 +30,7 @@ COPY src/Empostor.Plugins.QqVerify/Empostor.Plugins.QqVerify.csproj ./Empostor.P
|
||||
COPY src/Empostor.Plugins.Titles/Empostor.Plugins.Titles.csproj ./Empostor.Plugins.Titles/
|
||||
COPY src/Empostor.Plugins.Welcome/Empostor.Plugins.Welcome.csproj ./Empostor.Plugins.Welcome/
|
||||
COPY src/Empostor.Plugins.MapVote/Empostor.Plugins.MapVote.csproj ./Empostor.Plugins.MapVote/
|
||||
COPY src/Empostor.Plugins.Message/Empostor.Plugins.Message.csproj ./Empostor.Plugins.Message/
|
||||
|
||||
# Restore dependencies
|
||||
RUN dotnet restore Empostor.Server/Empostor.Server.csproj -a $TARGETARCH
|
||||
@@ -64,6 +65,8 @@ RUN dotnet publish Empostor.Plugin.Chat/Empostor.Plugin.Chat.csproj \
|
||||
dotnet publish Empostor.Plugins.Welcome/Empostor.Plugins.Welcome.csproj \
|
||||
-c Release -a $TARGETARCH --self-contained false -o /publish/plugins --no-restore && \
|
||||
dotnet publish Empostor.Plugins.MapVote/Empostor.Plugins.MapVote.csproj \
|
||||
-c Release -a $TARGETARCH --self-contained false -o /publish/plugins --no-restore && \
|
||||
dotnet publish Empostor.Plugins.Message/Empostor.Plugins.Message.csproj \
|
||||
-c Release -a $TARGETARCH --self-contained false -o /publish/plugins --no-restore
|
||||
|
||||
# ============================================
|
||||
@@ -91,6 +94,7 @@ COPY --from=build /publish/plugins/Empostor.Plugins.QqVerify.dll ./plugins/
|
||||
COPY --from=build /publish/plugins/Empostor.Plugins.Titles.dll ./plugins/
|
||||
COPY --from=build /publish/plugins/Empostor.Plugins.Welcome.dll ./plugins/
|
||||
COPY --from=build /publish/plugins/Empostor.Plugins.MapVote.dll ./plugins/
|
||||
COPY --from=build /publish/plugins/Empostor.Plugins.Message.dll ./plugins/
|
||||
|
||||
# Copy marketplace data
|
||||
COPY marketplace/ ./marketplace/
|
||||
|
||||
@@ -189,7 +189,21 @@ public sealed class LanguageService
|
||||
"command.players.not_in_lobby": "This command can only be used in the lobby.",
|
||||
"command.players.header": "=== Players ({0}) ===",
|
||||
"command.players.entry": "{0} | {1} | {2}ms",
|
||||
"command.ping.result": "Your ping: {0}ms"
|
||||
"command.ping.result": "Your ping: {0}ms",
|
||||
"command.help.description": "Show available commands.",
|
||||
"command.help.usage": "help [command]",
|
||||
"command.stat.description": "Show your player statistics.",
|
||||
"command.stat.usage": "stat",
|
||||
"command.setcolor.description": "Change your player color.",
|
||||
"command.setcolor.usage": "setcolor <0-17>",
|
||||
"command.players.description": "List players in the current game.",
|
||||
"command.players.usage": "players",
|
||||
"command.ping.description": "Show your network ping.",
|
||||
"command.ping.usage": "ping",
|
||||
"command.note.description": "Set or clear a lobby note (host only).",
|
||||
"command.note.usage": "note <text> | note clear",
|
||||
"command.max.description": "Set max players for the lobby (host only).",
|
||||
"command.max.usage": "max <1-15>"
|
||||
}
|
||||
""";
|
||||
|
||||
@@ -228,7 +242,21 @@ public sealed class LanguageService
|
||||
"command.players.not_in_lobby": "此指令只能在大厅中使用。",
|
||||
"command.players.header": "=== 在线玩家 ({0}) ===",
|
||||
"command.players.entry": "{0} | {1} | {2}ms",
|
||||
"command.ping.result": "你的延迟:{0}ms"
|
||||
"command.ping.result": "你的延迟:{0}ms",
|
||||
"command.help.description": "显示可用命令。",
|
||||
"command.help.usage": "help [命令]",
|
||||
"command.stat.description": "显示你的游戏统计。",
|
||||
"command.stat.usage": "stat",
|
||||
"command.setcolor.description": "修改你的颜色。",
|
||||
"command.setcolor.usage": "setcolor <0-17>",
|
||||
"command.players.description": "列出当前房间的玩家。",
|
||||
"command.players.usage": "players",
|
||||
"command.ping.description": "显示你的网络延迟。",
|
||||
"command.ping.usage": "ping",
|
||||
"command.note.description": "设置或清除房间备注(仅房主)。",
|
||||
"command.note.usage": "note <文字> | note clear",
|
||||
"command.max.description": "设置房间最大人数(仅房主)。",
|
||||
"command.max.usage": "max <1-15>"
|
||||
}
|
||||
""";
|
||||
|
||||
@@ -267,7 +295,21 @@ public sealed class LanguageService
|
||||
"command.players.not_in_lobby": "此指令只能在大廳中使用。",
|
||||
"command.players.header": "=== 線上玩家 ({0}) ===",
|
||||
"command.players.entry": "{0} | {1} | {2}ms",
|
||||
"command.ping.result": "你的延遲:{0}ms"
|
||||
"command.ping.result": "你的延遲:{0}ms",
|
||||
"command.help.description": "顯示可用命令。",
|
||||
"command.help.usage": "help [命令]",
|
||||
"command.stat.description": "顯示你的遊戲統計。",
|
||||
"command.stat.usage": "stat",
|
||||
"command.setcolor.description": "修改你的顏色。",
|
||||
"command.setcolor.usage": "setcolor <0-17>",
|
||||
"command.players.description": "列出當前房間的玩家。",
|
||||
"command.players.usage": "players",
|
||||
"command.ping.description": "顯示你的網路延遲。",
|
||||
"command.ping.usage": "ping",
|
||||
"command.note.description": "設置或清除房間備註(僅房主)。",
|
||||
"command.note.usage": "note <文字> | note clear",
|
||||
"command.max.description": "設置房間最大人數(僅房主)。",
|
||||
"command.max.usage": "max <1-15>"
|
||||
}
|
||||
""";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Empostor.Api.Commands;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -25,23 +26,106 @@ public sealed class NarratorCommand : ICommand
|
||||
|
||||
public async ValueTask<bool> ExecuteAsync(CommandContext ctx)
|
||||
{
|
||||
var args = ctx.Args;
|
||||
|
||||
// Host commands
|
||||
if (args.Length > 0 && ctx.Sender.IsHost)
|
||||
{
|
||||
var sub = args[0].ToLowerInvariant();
|
||||
|
||||
if (sub == "enable" || sub == "on")
|
||||
{
|
||||
_service.SetEnabled(ctx.Game, true);
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
T(ctx, "narrator.host_enabled", "Narrator enabled for this game."), ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sub == "disable" || sub == "off")
|
||||
{
|
||||
_service.SetEnabled(ctx.Game, false);
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
T(ctx, "narrator.host_disabled", "Narrator disabled for this game."), ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sub == "status")
|
||||
{
|
||||
var enabled = _service.IsEnabled(ctx.Game);
|
||||
var max = _service.GetMaxUses(ctx.Game);
|
||||
var statusText = T(ctx, enabled ? "narrator.status_enabled" : "narrator.status_disabled",
|
||||
enabled ? "enabled" : "disabled");
|
||||
var msg = T(ctx, "narrator.host_status", "Status: {0} | Max uses per player per game: {1}")
|
||||
.Replace("{0}", statusText)
|
||||
.Replace("{1}", max.ToString());
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(msg, ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sub == "limit")
|
||||
{
|
||||
if (args.Length < 2 || !int.TryParse(args[1], out var limit) || limit < 0)
|
||||
{
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
T(ctx, "narrator.host_limit_usage", "Usage: #narrator limit <number>"), ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
_service.SetMaxUses(ctx.Game, limit);
|
||||
if (limit == 0)
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
T(ctx, "narrator.host_limit_zero", "Limit set to 0 (effectively disabled)."), ctx.PlayerControl);
|
||||
else
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
T(ctx, "narrator.host_limit_set", "Limit set to {0} per player per game.")
|
||||
.Replace("{0}", limit.ToString()),
|
||||
ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Show host commands if no args provided
|
||||
if (args.Length == 0)
|
||||
{
|
||||
await ShowUsageAsync(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check game state — meeting must be active
|
||||
if (!_service.IsMeetingActive(ctx.Game))
|
||||
{
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
"[Narrator] You can only use this command during a meeting.", ctx.PlayerControl);
|
||||
T(ctx, "narrator.meeting_only", "You can only use #narrator during a meeting."), ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if narrator is enabled
|
||||
if (!_service.IsEnabled(ctx.Game))
|
||||
{
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
T(ctx, "narrator.disabled", "The narrator is currently disabled by the host."), ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
var playerName = ctx.PlayerControl.PlayerInfo.PlayerName;
|
||||
|
||||
// Check usage limits
|
||||
var (allowed, error) = _service.TryUse(ctx.Game, playerName);
|
||||
if (!allowed)
|
||||
{
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
$"[Narrator] {error}", ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
var playerMessage = ctx.RawArgs?.Trim();
|
||||
if (string.IsNullOrEmpty(playerMessage))
|
||||
{
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(
|
||||
"Usage: /narrator <your question or statement>\nExample: /narrator I'm being accused but I have a visual task, how do I prove myself?",
|
||||
ctx.PlayerControl);
|
||||
await ShowUsageAsync(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.LogInformation("[Narrator] {player} asks: {message}", ctx.PlayerControl.PlayerInfo.PlayerName, playerMessage);
|
||||
_logger.LogInformation("[Narrator] {player} asks: {message}", playerName, playerMessage);
|
||||
|
||||
var context = _service.BuildContext(ctx.Game, ctx.PlayerControl);
|
||||
var reply = await _service.AskNarratorAsync(context, playerMessage);
|
||||
@@ -51,4 +135,21 @@ public sealed class NarratorCommand : ICommand
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async ValueTask ShowUsageAsync(CommandContext ctx)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(T(ctx, "narrator.usage",
|
||||
"Usage: #narrator <your question or statement>"));
|
||||
if (ctx.Sender.IsHost)
|
||||
sb.AppendLine(T(ctx, "narrator.host_commands",
|
||||
"Host commands: #narrator enable | disable | limit <number>"));
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(sb.ToString(), ctx.PlayerControl);
|
||||
}
|
||||
|
||||
private static string T(CommandContext ctx, string key, string defaultText)
|
||||
{
|
||||
string result = ctx.Lang.Get(key, ctx.SenderLanguage);
|
||||
return result == key ? defaultText : result;
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@ public sealed class NarratorPlugin : PluginBase, IPluginLanguageProvider
|
||||
{
|
||||
["en"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.narrator.description"] = "Ask the narrator for AI-powered advice during a meeting.",
|
||||
["command.narrator.usage"] = "narrator <your question>",
|
||||
["narrator.meeting_only"] = "You can only use #narrator during a meeting.",
|
||||
["narrator.disabled"] = "The narrator is currently disabled by the host.",
|
||||
["narrator.status_enabled"] = "enabled",
|
||||
@@ -44,6 +46,8 @@ public sealed class NarratorPlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_CN"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.narrator.description"] = "在会议中向旁白寻求AI建议。",
|
||||
["command.narrator.usage"] = "narrator <你要提的问题>",
|
||||
["narrator.meeting_only"] = "只能在会议中使用 #narrator。",
|
||||
["narrator.disabled"] = "房主已禁用旁白功能。",
|
||||
["narrator.status_enabled"] = "已启用",
|
||||
@@ -59,6 +63,8 @@ public sealed class NarratorPlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_TW"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.narrator.description"] = "在會議中向旁白尋求AI建議。",
|
||||
["command.narrator.usage"] = "narrator <你要提的問題>",
|
||||
["narrator.meeting_only"] = "只能在會議中使用 #narrator。",
|
||||
["narrator.disabled"] = "房主已停用旁白功能。",
|
||||
["narrator.status_enabled"] = "已啟用",
|
||||
|
||||
@@ -29,6 +29,8 @@ public sealed class MapVotePlugin : PluginBase, IPluginLanguageProvider
|
||||
{
|
||||
["en"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.votemap.description"] = "Vote for the next map.",
|
||||
["command.votemap.usage"] = "votemap <map>",
|
||||
["mapvote.disabled"] = "Map voting is currently disabled by the host.",
|
||||
["mapvote.unknown_map"] = "Unknown map: {0}. Available: Skeld, Mira, Polus, Airship, Fungle",
|
||||
["mapvote.voted"] = "{0} voted for {1}.",
|
||||
@@ -46,6 +48,8 @@ public sealed class MapVotePlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_CN"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.votemap.description"] = "投票选择下一张地图。",
|
||||
["command.votemap.usage"] = "votemap <地图名>",
|
||||
["mapvote.disabled"] = "投票选图功能已被房主禁用。",
|
||||
["mapvote.unknown_map"] = "未知地图:{0}。可选:Skeld, Mira, Polus, Airship, Fungle",
|
||||
["mapvote.voted"] = "{0} 投票选择了 {1}。",
|
||||
@@ -63,6 +67,8 @@ public sealed class MapVotePlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_TW"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.votemap.description"] = "投票選擇下一張地圖。",
|
||||
["command.votemap.usage"] = "votemap <地圖名>",
|
||||
["mapvote.disabled"] = "投票選圖功能已被房主停用。",
|
||||
["mapvote.unknown_map"] = "未知地圖:{0}。可選:Skeld, Mira, Polus, Airship, Fungle",
|
||||
["mapvote.voted"] = "{0} 投票選擇了 {1}。",
|
||||
|
||||
@@ -31,12 +31,7 @@ public sealed class MessageCommand : ICommand
|
||||
}
|
||||
|
||||
var targetFc = ctx.Args[0].Trim().ToUpperInvariant();
|
||||
var content = ctx.RawArgs!;
|
||||
|
||||
// Remove the friend code prefix from the raw args to get the message content
|
||||
var contentStart = ctx.RawArgs!.IndexOf(targetFc, StringComparison.OrdinalIgnoreCase);
|
||||
if (contentStart >= 0)
|
||||
content = ctx.RawArgs[(contentStart + ctx.Args[0].Length)..].Trim();
|
||||
var content = ctx.RawArgs!.Substring(ctx.Args[0].Length).Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Empostor.Api.Events;
|
||||
using Empostor.Api.Events.Client;
|
||||
using Empostor.Api.Events.Game;
|
||||
|
||||
namespace Empostor.Plugins.Message;
|
||||
|
||||
@@ -17,46 +14,18 @@ public sealed class MessageEventListener : IEventListener
|
||||
_store = store;
|
||||
}
|
||||
|
||||
[EventListener]
|
||||
public async ValueTask OnClientConnected(IClientConnectedEvent e)
|
||||
{
|
||||
await DeliverMessages(e.Client.FriendCode, e.Client.Language, null);
|
||||
}
|
||||
|
||||
[EventListener]
|
||||
public async ValueTask OnPlayerJoined(IGamePlayerJoinedEvent e)
|
||||
{
|
||||
var fc = e.Player.Client.FriendCode;
|
||||
if (string.IsNullOrEmpty(fc)) return;
|
||||
|
||||
// Deliver any undelivered messages when player joins a game
|
||||
var messages = _store.TakeAll(fc);
|
||||
if (messages.Count == 0) return;
|
||||
|
||||
var ctrl = e.Player.Character;
|
||||
if (ctrl == null) return;
|
||||
|
||||
await DeliverToPlayer(messages, ctrl, e.Player.Client.Name ?? "Player");
|
||||
}
|
||||
|
||||
private async ValueTask DeliverMessages(string? friendCode, Api.Languages.Language language, Api.Innersloth.IInnerPlayerControl? ctrl)
|
||||
{
|
||||
if (string.IsNullOrEmpty(friendCode)) return;
|
||||
|
||||
var messages = _store.TakeAll(friendCode);
|
||||
if (messages.Count == 0) return;
|
||||
|
||||
// Messages were already delivered via OnPlayerJoined with character reference
|
||||
// OnClientConnected happens before player has a character, so store them back and wait for game join
|
||||
foreach (var msg in messages)
|
||||
_store.Add(msg);
|
||||
}
|
||||
|
||||
private async ValueTask DeliverToPlayer(
|
||||
System.Collections.Generic.IReadOnlyList<PendingMessage> messages,
|
||||
Empostor.Api.Innersloth.IInnerPlayerControl ctrl,
|
||||
string playerName)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(string.Format("--- You have {0} pending message(s) ---", messages.Count));
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ public sealed class MessagePlugin : PluginBase, IPluginLanguageProvider
|
||||
{
|
||||
["en"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.msg.description"] = "Leave a message for a player by friend code.",
|
||||
["command.msg.usage"] = "msg <friendcode> <message>",
|
||||
["message.usage"] = "Usage: #msg <friendcode> <message>\nExample: #msg ABCDEFG Hey, let's play again!",
|
||||
["message.sent"] = "Message sent to {0}.",
|
||||
["message.too_long"] = "Message is too long. Max {0} characters.",
|
||||
@@ -41,6 +43,8 @@ public sealed class MessagePlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_CN"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.msg.description"] = "通过好友代码给玩家留言。",
|
||||
["command.msg.usage"] = "msg <好友代码> <留言内容>",
|
||||
["message.usage"] = "用法:#msg <好友代码> <留言内容>\n示例:#msg ABCDEFG 下次一起玩!",
|
||||
["message.sent"] = "留言已发送给 {0}。",
|
||||
["message.too_long"] = "留言内容过长,最多 {0} 个字符。",
|
||||
@@ -53,6 +57,8 @@ public sealed class MessagePlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_TW"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.msg.description"] = "透過好友代碼給玩家留言。",
|
||||
["command.msg.usage"] = "msg <好友代碼> <留言內容>",
|
||||
["message.usage"] = "用法:#msg <好友代碼> <留言內容>\n範例:#msg ABCDEFG 下次一起玩!",
|
||||
["message.sent"] = "留言已發送給 {0}。",
|
||||
["message.too_long"] = "留言內容過長,最多 {0} 個字元。",
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net8.0": {
|
||||
"BouncyCastle.Cryptography": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.6.1",
|
||||
"contentHash": "vZsG2YILhthgRqO+ZVgRff4ZFKKTl0v7kqaVBLCtRvpREhfBP33pcWrdA3PRYgWuFL1RxiUFvjMUHTdBZlJcoA=="
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Features": "2.2.0",
|
||||
"System.Text.Encodings.Web": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.AspNetCore.Http.Features": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.2.0",
|
||||
"contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "9.0.6",
|
||||
"contentHash": "0Zn6nR/6g+90MxskZyOOMPQvnPnrrGu6bytPwkV+azDcTtCSuQ1+GJUrg8Klmnrjk1i6zMpw2lXijl+tw7Q3kA=="
|
||||
},
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
|
||||
"Microsoft.Extensions.Options": "8.0.0",
|
||||
"System.Diagnostics.DiagnosticSource": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Primitives": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Hosting.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "AG7HWwVRdCHlaA++1oKDxLsXIBxmDpMPb3VoyOoAghEWnkUvEAdYQUwnV4jJbAaa/nMYNiEh5ByoLauZBEiovg==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "8.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "8.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging.Abstractions": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.ObjectPool": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.1",
|
||||
"contentHash": "X21b8D6z58EG34OMLH955750mFaEaGs5xLGe9Vyi3059Cgb3sk+p2k/JlQXaieEBRrk+SVlFzDei3Q6PdVzJOA=="
|
||||
},
|
||||
"Microsoft.Extensions.Options": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
|
||||
"Microsoft.Extensions.Primitives": "8.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Primitives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g=="
|
||||
},
|
||||
"Serilog": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.1-dev-02373",
|
||||
"contentHash": "f0HNPaleOox5++8zqxAdi9afnUUkoznLOmd0ur/UnLbzl8bIaPyyBGOpbIJmC1kz2vHfkQ0fXh6KXMdlz7bcLQ=="
|
||||
},
|
||||
"System.Diagnostics.DiagnosticSource": {
|
||||
"type": "Transitive",
|
||||
"resolved": "8.0.0",
|
||||
"contentHash": "c9xLpVz6PL9lp/djOWtk5KPDZq3cSYpmXoJQY524EOtuFl5z9ZtsotpsyrDW40U1DRnQSYvcPKEUV0X//u6gkQ=="
|
||||
},
|
||||
"System.Text.Encodings.Web": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.5.0",
|
||||
"contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g=="
|
||||
},
|
||||
"empostor.api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "[8.0.0, )",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )",
|
||||
"NextFast.Hazel": "[1.0.2-dev, )",
|
||||
"NextFast.Hazel.Abstractions": "[1.0.2-dev, )"
|
||||
}
|
||||
},
|
||||
"NextFast.Hazel": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"BouncyCastle.Cryptography": "[2.6.1, )",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "[9.0.6, )",
|
||||
"Microsoft.Extensions.ObjectPool": "[8.0.1, )",
|
||||
"NextFast.Hazel.Abstractions": "[1.0.2-dev, )",
|
||||
"Serilog": "[4.3.1-dev-02373, )"
|
||||
}
|
||||
},
|
||||
"NextFast.Hazel.Abstractions": {
|
||||
"type": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,18 +29,24 @@ public sealed class PlayerChannelPlugin : PluginBase, IPluginLanguageProvider
|
||||
{
|
||||
["en"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.channel.description"] = "Send a message to your player channel.",
|
||||
["command.channel.usage"] = "channel <message>",
|
||||
["playerchannel.unknown_friendcode"] = "[Refuse Channel] Unknown Friendcode",
|
||||
["playerchannel.not_in_channel"] = "[Refuse Channel] Not in any channel",
|
||||
["playerchannel.message_format"] = "[{0}] {1}",
|
||||
},
|
||||
["zh_CN"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.channel.description"] = "向你的玩家频道发送消息。",
|
||||
["command.channel.usage"] = "channel <消息>",
|
||||
["playerchannel.unknown_friendcode"] = "[Refuse Channel] 未知的好友代码",
|
||||
["playerchannel.not_in_channel"] = "[Refuse Channel] 不在任何频道中",
|
||||
["playerchannel.message_format"] = "[{0}] {1}",
|
||||
},
|
||||
["zh_TW"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.channel.description"] = "向你的玩家頻道發送訊息。",
|
||||
["command.channel.usage"] = "channel <訊息>",
|
||||
["playerchannel.unknown_friendcode"] = "[Refuse Channel] 未知的好友代碼",
|
||||
["playerchannel.not_in_channel"] = "[Refuse Channel] 不在任何頻道中",
|
||||
["playerchannel.message_format"] = "[{0}] {1}",
|
||||
|
||||
@@ -29,6 +29,8 @@ public sealed class QqVerifyPlugin : PluginBase, IPluginLanguageProvider
|
||||
{
|
||||
["en"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.verify.description"] = "Verify your QQ number for group access.",
|
||||
["command.verify.usage"] = "verify <QQ number>",
|
||||
["qqverify.chinese_only"] = "This command is only available for Chinese language players.\n此功能仅支持简体/繁体中文玩家使用。",
|
||||
["qqverify.no_friendcode"] = "Unable to get your friend code. Please make sure you are logged in.",
|
||||
["qqverify.usage_message"] = "Usage: #verify <your QQ number>\nExample: #verify 123456789",
|
||||
@@ -36,6 +38,8 @@ public sealed class QqVerifyPlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_CN"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.verify.description"] = "验证你的QQ号以获取群组访问权限。",
|
||||
["command.verify.usage"] = "verify <QQ号>",
|
||||
["qqverify.chinese_only"] = "此功能仅支持简体/繁体中文玩家使用。\nThis command is only available for Chinese language players.",
|
||||
["qqverify.no_friendcode"] = "无法获取你的好友代码,请确保已登录账号。",
|
||||
["qqverify.usage_message"] = "用法:#verify <你的QQ号>\n示例:#verify 123456789",
|
||||
@@ -43,6 +47,8 @@ public sealed class QqVerifyPlugin : PluginBase, IPluginLanguageProvider
|
||||
},
|
||||
["zh_TW"] = new Dictionary<string, string>
|
||||
{
|
||||
["command.verify.description"] = "驗證你的QQ號以獲取群組存取權限。",
|
||||
["command.verify.usage"] = "verify <QQ號>",
|
||||
["qqverify.chinese_only"] = "此功能僅支援簡體/繁體中文玩家使用。\nThis command is only available for Chinese language players.",
|
||||
["qqverify.no_friendcode"] = "無法獲取你的好友代碼,請確保已登入帳號。",
|
||||
["qqverify.usage_message"] = "用法:#verify <你的QQ號>\n範例:#verify 123456789",
|
||||
|
||||
@@ -34,8 +34,8 @@ public sealed class HelpCommand : ICommand
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(ctx.GetString("command.help.entry").Format(target.Name, target.Description));
|
||||
sb.AppendLine(ctx.GetString("command.usage").Format(target.Usage));
|
||||
sb.AppendLine(ctx.GetString("command.help.entry").Format(target.Name, GetDesc(ctx, target)));
|
||||
sb.AppendLine(ctx.GetString("command.usage").Format(GetUsage(ctx, target)));
|
||||
if (target.Aliases.Length > 0)
|
||||
sb.AppendLine(ctx.GetString("command.help.aliases")
|
||||
.Format(string.Join(", ", target.Aliases.Select(a => "#" + a))));
|
||||
@@ -47,10 +47,24 @@ public sealed class HelpCommand : ICommand
|
||||
var list = new StringBuilder(ctx.GetString("command.help.list").Get() + "\n");
|
||||
foreach (var cmd in _service.All.OrderBy(c => c.Name))
|
||||
{
|
||||
list.AppendLine(ctx.GetString("command.help.entry").Format(cmd.Name, cmd.Description));
|
||||
list.AppendLine(ctx.GetString("command.help.entry").Format(cmd.Name, GetDesc(ctx, cmd)));
|
||||
}
|
||||
|
||||
await ctx.PlayerControl.SendChatToPlayerAsync(list.ToString().TrimEnd(), ctx.PlayerControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string GetDesc(CommandContext ctx, ICommand cmd)
|
||||
{
|
||||
var key = $"command.{cmd.Name}.description";
|
||||
var result = ctx.Lang.Get(key, ctx.SenderLanguage);
|
||||
return result == key ? cmd.Description : result.Get();
|
||||
}
|
||||
|
||||
private static string GetUsage(CommandContext ctx, ICommand cmd)
|
||||
{
|
||||
var key = $"command.{cmd.Name}.usage";
|
||||
var result = ctx.Lang.Get(key, ctx.SenderLanguage);
|
||||
return result == key ? cmd.Usage : result.Get();
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugin.Narrator",
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.MapVote", "Empostor.Plugins.MapVote\Empostor.Plugins.MapVote.csproj", "{9D67CAC6-D296-404C-9189-2FF9B86D287C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Message", "Empostor.Plugins.Message\Empostor.Plugins.Message.csproj", "{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -241,6 +243,18 @@ Global
|
||||
{9D67CAC6-D296-404C-9189-2FF9B86D287C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9D67CAC6-D296-404C-9189-2FF9B86D287C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9D67CAC6-D296-404C-9189-2FF9B86D287C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -257,7 +271,9 @@ Global
|
||||
{D4B6C8A2-5F3E-4C1D-9B7A-6E2F8A4C1D3F} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||
{9D1FD146-E7D9-4AFF-9B8E-25E6021A69D7} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||
{ADC4F301-51C0-45DB-B97A-BE3844DFD19B} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||
{FE6D40CC-4BE5-4E38-9DCA-E6832709FE3F} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||
{9D67CAC6-D296-404C-9189-2FF9B86D287C} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||
{D05FE3E6-1BD9-4D32-89EB-5DE02A785EF8} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DAF5625C-7E46-4DCC-AF2C-11D20D965454}
|
||||
|
||||
Reference in new issue
Block a user