diff --git a/marketplace/Impostor.Plugins.PlayerChannel.dll b/marketplace/Impostor.Plugins.PlayerChannel.dll new file mode 100644 index 0000000..d94b466 Binary files /dev/null and b/marketplace/Impostor.Plugins.PlayerChannel.dll differ diff --git a/marketplace/plugins.json b/marketplace/plugins.json index 178b932..8e04ca7 100644 --- a/marketplace/plugins.json +++ b/marketplace/plugins.json @@ -89,6 +89,19 @@ "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Impostor.Plugins.Titles.dll" } ] + }, + { + "id": "cn.hayashiume.playerchannel", + "name": "Player Channel", + "description": "using /s to send an only channel message by friendcode", + "author": "HayashiUme", + "versions": [ + { + "version": "1.0.0", + "impostor_version": "2.0.0", + "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Impostor.Plugins.PlayerChannel.dll" + } + ] }, { "id": "cn.hayashiume.qqverify", diff --git a/src/Impostor.Api.Innersloth.Generator/packages.lock.json b/src/Impostor.Api.Innersloth.Generator/packages.lock.json index fb68fad..aedf17e 100644 --- a/src/Impostor.Api.Innersloth.Generator/packages.lock.json +++ b/src/Impostor.Api.Innersloth.Generator/packages.lock.json @@ -150,6 +150,7 @@ "System.Runtime.CompilerServices.Unsafe": "4.5.3" } } - } + }, + ".NETStandard,Version=v2.0/linux-x64": {} } } \ No newline at end of file diff --git a/src/Impostor.Api/packages.lock.json b/src/Impostor.Api/packages.lock.json index 9d991b4..9c8d1b7 100644 --- a/src/Impostor.Api/packages.lock.json +++ b/src/Impostor.Api/packages.lock.json @@ -34,6 +34,12 @@ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.27, )", + "resolved": "8.0.27", + "contentHash": "rQi9TxifHRnXP7lVRZH05DxD2/XGbJp12q0ozcbrlBlBnyyzssFTH/2vLhtKWUp2CT1qVscTrcYTFiwTyKPKRg==" + }, "StyleCop.Analyzers": { "type": "Direct", "requested": "[1.2.0-beta.556, )", @@ -139,6 +145,7 @@ "NextFast.Hazel.Abstractions": { "type": "Project" } - } + }, + "net8.0/linux-x64": {} } } \ No newline at end of file diff --git a/src/Impostor.Plugins.PlayerChannel/Impostor.Plugins.PlayerChannel.csproj b/src/Impostor.Plugins.PlayerChannel/Impostor.Plugins.PlayerChannel.csproj new file mode 100644 index 0000000..a35718e --- /dev/null +++ b/src/Impostor.Plugins.PlayerChannel/Impostor.Plugins.PlayerChannel.csproj @@ -0,0 +1,10 @@ + + + net8.0 + Impostor.Plugins.PlayerChannel + enable + + + + + diff --git a/src/Impostor.Plugins.PlayerChannel/PlayerChannelCommand.cs b/src/Impostor.Plugins.PlayerChannel/PlayerChannelCommand.cs new file mode 100644 index 0000000..8f57b1b --- /dev/null +++ b/src/Impostor.Plugins.PlayerChannel/PlayerChannelCommand.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Impostor.Api.Commands; + +namespace Impostor.Plugins.PlayerChannel; + +public sealed class PlayerChannelCommand : ICommand +{ + private readonly Dictionary _fcToChannel; + + public PlayerChannelCommand(PlayerChannelConfig config) + { + _fcToChannel = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var channel in config.Channels) + { + foreach (var fc in channel.FriendCodes) + { + if (!string.IsNullOrWhiteSpace(fc)) + _fcToChannel[fc] = channel; + } + } + } + + public string Name => "s"; + + public string Description => "Send a message to your player channel."; + + public string Usage => "s "; + + public async ValueTask ExecuteAsync(CommandContext ctx) + { + var text = ctx.RawArgs; + if (string.IsNullOrWhiteSpace(text)) + return false; + + var senderFc = ctx.Sender.Client.FriendCode; + if (string.IsNullOrEmpty(senderFc)) + { + await ctx.PlayerControl.SendChatToPlayerAsync( + "[Refuse Channel] Unnkown Friendcode", ctx.PlayerControl); + return true; + } + + if (!_fcToChannel.TryGetValue(senderFc, out var channel)) + { + await ctx.PlayerControl.SendChatToPlayerAsync( + "[Refuse Channel] No exsit in any Channnel", ctx.PlayerControl); + return true; + } + + var prefixed = $"[{channel.Name}] {text}"; + + foreach (var player in ctx.Game.Players) + { + var fc = player.Client.FriendCode; + if (string.IsNullOrEmpty(fc)) continue; + if (!channel.FriendCodes.Contains(fc)) continue; + + var targetCtrl = player.Character; + if (targetCtrl == null) continue; + + await ctx.PlayerControl.SendChatToPlayerAsync(prefixed, targetCtrl); + } + + return true; + } +} diff --git a/src/Impostor.Plugins.PlayerChannel/PlayerChannelConfig.cs b/src/Impostor.Plugins.PlayerChannel/PlayerChannelConfig.cs new file mode 100644 index 0000000..7169ddd --- /dev/null +++ b/src/Impostor.Plugins.PlayerChannel/PlayerChannelConfig.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Impostor.Plugins.PlayerChannel; + +public sealed class PlayerChannelConfig +{ + [JsonPropertyName("channels")] + public List Channels { get; set; } = new() + { + new ChannelEntry + { + Name = "Example Channel", + FriendCodes = new List { "kami#1337", "nofinalsus#8469" }, + }, + }; +} + +public sealed class ChannelEntry +{ + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + [JsonPropertyName("friendCodes")] + public List FriendCodes { get; set; } = new(); +} diff --git a/src/Impostor.Plugins.PlayerChannel/PlayerChannelPlugin.cs b/src/Impostor.Plugins.PlayerChannel/PlayerChannelPlugin.cs new file mode 100644 index 0000000..1f1a4d7 --- /dev/null +++ b/src/Impostor.Plugins.PlayerChannel/PlayerChannelPlugin.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Impostor.Api.Plugins; +using Microsoft.Extensions.Logging; + +namespace Impostor.Plugins.PlayerChannel; + +[ImpostorPlugin("cn.hayashiume.playerchannel", "Player Channel", "HayashiUme", "1.0.0")] +public sealed class PlayerChannelPlugin : PluginBase +{ + private readonly ILogger _logger; + + public PlayerChannelPlugin(ILogger logger) + { + _logger = logger; + } + + public override ValueTask EnableAsync() + { + _logger.LogInformation("[PlayerChannel] Enabled."); + return default; + } + + public override ValueTask DisableAsync() => default; +} diff --git a/src/Impostor.Plugins.PlayerChannel/PlayerChannelStartup.cs b/src/Impostor.Plugins.PlayerChannel/PlayerChannelStartup.cs new file mode 100644 index 0000000..98b863c --- /dev/null +++ b/src/Impostor.Plugins.PlayerChannel/PlayerChannelStartup.cs @@ -0,0 +1,24 @@ +using Impostor.Api.Commands; +using Impostor.Api.Plugins; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Impostor.Plugins.PlayerChannel; + +public sealed class PlayerChannelStartup : IPluginStartup +{ + private string _configPath = "[Player Channel]Config.json"; + + public void SetConfigPath(string configPath) => _configPath = configPath; + + public void ConfigureHost(IHostBuilder host) { } + + public void ConfigureServices(IServiceCollection services) + { + var config = PluginConfigLoader.Load(_configPath); + services.AddSingleton(config); + services.AddSingleton(); + services.AddSingleton( + sp => sp.GetRequiredService()); + } +} diff --git a/src/Impostor.Plugins.PlayerChannel/packages.lock.json b/src/Impostor.Plugins.PlayerChannel/packages.lock.json new file mode 100644 index 0000000..8e2baba --- /dev/null +++ b/src/Impostor.Plugins.PlayerChannel/packages.lock.json @@ -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==" + }, + "impostor.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" + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Server/packages.lock.json b/src/Impostor.Server/packages.lock.json index d4e3919..249a849 100644 --- a/src/Impostor.Server/packages.lock.json +++ b/src/Impostor.Server/packages.lock.json @@ -58,6 +58,12 @@ "resolved": "8.0.1", "contentHash": "X21b8D6z58EG34OMLH955750mFaEaGs5xLGe9Vyi3059Cgb3sk+p2k/JlQXaieEBRrk+SVlFzDei3Q6PdVzJOA==" }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.27, )", + "resolved": "8.0.27", + "contentHash": "rQi9TxifHRnXP7lVRZH05DxD2/XGbJp12q0ozcbrlBlBnyyzssFTH/2vLhtKWUp2CT1qVscTrcYTFiwTyKPKRg==" + }, "Serilog.Extensions.Hosting": { "type": "Direct", "requested": "[8.0.0, )", diff --git a/src/Impostor.sln b/src/Impostor.sln index 3212414..63546fa 100644 --- a/src/Impostor.sln +++ b/src/Impostor.sln @@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Impostor.Plugins.Titles", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Impostor.Plugins.QqVerify", "Impostor.Plugins.QqVerify\Impostor.Plugins.QqVerify.csproj", "{B8A5D7C3-1F4E-4A2B-9C6D-8E3F5A7B1D2E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Impostor.Plugins.PlayerChannel", "Impostor.Plugins.PlayerChannel\Impostor.Plugins.PlayerChannel.csproj", "{D4B6C8A2-5F3E-4C1D-9B7A-6E2F8A4C1D3F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -78,6 +80,10 @@ Global {B8A5D7C3-1F4E-4A2B-9C6D-8E3F5A7B1D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8A5D7C3-1F4E-4A2B-9C6D-8E3F5A7B1D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8A5D7C3-1F4E-4A2B-9C6D-8E3F5A7B1D2E}.Release|Any CPU.Build.0 = Release|Any CPU + {D4B6C8A2-5F3E-4C1D-9B7A-6E2F8A4C1D3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4B6C8A2-5F3E-4C1D-9B7A-6E2F8A4C1D3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4B6C8A2-5F3E-4C1D-9B7A-6E2F8A4C1D3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4B6C8A2-5F3E-4C1D-9B7A-6E2F8A4C1D3F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -91,6 +97,7 @@ Global {70CD7AC9-1DE3-CD23-602A-EFD504B91450} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} {3038597E-E1A1-2958-1CF7-C4203A85F424} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} {B8A5D7C3-1F4E-4A2B-9C6D-8E3F5A7B1D2E} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} + {D4B6C8A2-5F3E-4C1D-9B7A-6E2F8A4C1D3F} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DAF5625C-7E46-4DCC-AF2C-11D20D965454}