diff --git a/MVPMusicBox.sln b/MVPMusicBox.sln new file mode 100644 index 0000000..19b8091 --- /dev/null +++ b/MVPMusicBox.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MVPMusicBox", "MVPMusicBox\MVPMusicBox.csproj", "{120E5B85-75F0-4D97-91A6-203AF884BAAC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {120E5B85-75F0-4D97-91A6-203AF884BAAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {120E5B85-75F0-4D97-91A6-203AF884BAAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {120E5B85-75F0-4D97-91A6-203AF884BAAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {120E5B85-75F0-4D97-91A6-203AF884BAAC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/MVPMusicBox/Config.cs b/MVPMusicBox/Config.cs new file mode 100644 index 0000000..dd55c17 --- /dev/null +++ b/MVPMusicBox/Config.cs @@ -0,0 +1,13 @@ +using Exiled.API.Interfaces; +using System.ComponentModel; + +namespace MVPMusicBox +{ + public class Config : IConfig + { + [Description("启动MVP音乐盒")] + public bool IsEnabled { get; set ; } = true; + [Description("启动MVP音乐盒-Debug")] + public bool Debug { get; set; } = false; + } +} diff --git a/MVPMusicBox/EventHandlers.cs b/MVPMusicBox/EventHandlers.cs new file mode 100644 index 0000000..a5eb72b --- /dev/null +++ b/MVPMusicBox/EventHandlers.cs @@ -0,0 +1,130 @@ +using Exiled.API.Features; +using Exiled.Events.EventArgs.Player; +using Exiled.Events.EventArgs.Server; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace MVPMusicBox +{ + public class EventHandlers + { + public class MVPList + { + public string UserId { get; set; } + public string MusicName { get; set; } + public string BroadcastName { get; set; } + } + public class MVPMusic + { + public static bool MusicBox = true; + public static List MVPInfos = new List(); + public static Dictionary Kills = new Dictionary(); + public static void RegMusic() + { + ReadJson(); + Exiled.Events.Handlers.Server.RoundStarted += RoundStart; + Exiled.Events.Handlers.Server.RoundEnded += RoundEnded; + Exiled.Events.Handlers.Player.Dying += PlayerDying; + Exiled.Events.Handlers.Player.Spawned += PlayerSpawn; + } + public static void UnRegMusic() + { + Exiled.Events.Handlers.Server.RoundStarted -= RoundStart; + Exiled.Events.Handlers.Server.RoundEnded -= RoundEnded; + Exiled.Events.Handlers.Player.Dying -= PlayerDying; + Exiled.Events.Handlers.Player.Spawned -= PlayerSpawn; + } + public static void RoundStart() + { + foreach (Player player in Player.List) + { + Kills[player] = 0; + } + Kills.Clear(); + ReadJson(); + } + public static void PlayerSpawn(SpawnedEventArgs Args) + { + if (!Kills.ContainsKey(Args.Player) && Args.Player.IsVerified && !Args.Player.IsNPC) + { + Kills.Add(Args.Player, 0); + } + } + public static void PlayerDying(DyingEventArgs Args) + { + if (Args.Player != null && Args.Attacker != null) + { + if (Args.Player != Args.Attacker) + { + if (Kills.ContainsKey(Args.Attacker)) + { + Kills[Args.Attacker]++; + } + else + { + Kills[Args.Attacker] = 1; + } + } + } + } + public static void MusicBoxPlayer(Player player) + { + MVPList mvpList = MVPInfos.FirstOrDefault(x => x.UserId == player.UserId); + if (mvpList != null) + { + Log.Info($"[MVP][玩家 {player.Nickname}][击杀 {Kills[player]} 人][播放音乐 {mvpList.MusicName} ][播报名 {mvpList.BroadcastName}]"); + Map.Broadcast(10, $"=----------------= MVP 时刻 =----------------=\n本回合MVP: {player.Nickname} \n总共击杀了 {Kills[player]} 人 \n正在播放MVP音乐: 「 {mvpList.BroadcastName} 」 "); + MusicAPI.PlayMusic.GlobalPlayMusic(Paths.Exiled + "\\音乐盒\\音乐文件", mvpList.MusicName, $"{player.Nickname}的音乐盒"); + return; + } + else + { + Log.Info($"[MVP][玩家 {player.Nickname}][击杀 {Kills[player]} 人]"); + Map.Broadcast(10, $"=----------------= MVP 时刻 =----------------=\n本回合MVP: {player.Nickname} \n总共击杀了 {Kills[player]} 人 "); + return; + } + } + public static void RoundEnded(RoundEndedEventArgs ev) + { + if (MusicBox == false) + return; + MusicBox = false; + ReadJson(); + foreach (Player player in Player.List) + if (!Kills.ContainsKey(player)) + Kills.Add(player, 0); + MusicBoxPlayer(Kills.OrderByDescending(x => x.Value).First().Key); + } + public static void ReadJson() + { + string JsonPath = Paths.Exiled + "\\音乐盒\\Config.json"; + if (!Directory.Exists(Paths.Exiled + "\\音乐盒")) + { + Directory.CreateDirectory(Paths.Exiled + "\\音乐盒"); + } + if (!Directory.Exists(Paths.Exiled + "\\音乐盒\\音乐文件")) + { + Directory.CreateDirectory(Paths.Exiled + "\\音乐盒\\音乐文件"); + } + if (!File.Exists(JsonPath)) + { + MVPInfos.Add(new MVPList() + { + UserId = "76561199208302036@steam", + MusicName = "76561199208302036", + BroadcastName = "[DEBUG]", + }); + File.WriteAllText(JsonPath, JsonConvert.SerializeObject((object)MVPInfos)); + Log.Info($"生成音乐盒模板至 => [{JsonPath}]"); + } + else + { + MVPInfos = JsonConvert.DeserializeObject>(File.ReadAllText(JsonPath)); + Log.Info($"读取音乐盒数量:{MVPInfos.Count}"); + } + } + } + } +} diff --git a/MVPMusicBox/MVPMusicBox.csproj b/MVPMusicBox/MVPMusicBox.csproj new file mode 100644 index 0000000..7107adc --- /dev/null +++ b/MVPMusicBox/MVPMusicBox.csproj @@ -0,0 +1,91 @@ + + + + + Debug + AnyCPU + {120E5B85-75F0-4D97-91A6-203AF884BAAC} + Library + Properties + MVPMusicBox + MVPMusicBox + v4.8 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x64 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Assembly-CSharp.dll + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Assembly-CSharp-firstpass.dll + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\CommandSystem.Core.dll + + + C:\Users\Administrator\AppData\Roaming\SCP Secret Laboratory\PluginAPI\plugins\7777\dependencies\Exiled.API.dll + + + C:\Users\Administrator\AppData\Roaming\EXILED\Plugins\Exiled.Events.dll + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Mirror.dll + + + False + ..\..\..\Game\sister30days_Data\Managed\Newtonsoft.Json.dll + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\PluginAPI.dll + + + C:\Users\Administrator\Desktop\SCPSLAudioApi.dll + + + + + + + + + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.dll + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.CoreModule.dll + + + ..\..\..\SteamLibrary\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\UnityEngine.PhysicsModule.dll + + + + + + + + + + + + + \ No newline at end of file diff --git a/MVPMusicBox/MusicAPI/FakeConnection.cs b/MVPMusicBox/MusicAPI/FakeConnection.cs new file mode 100644 index 0000000..44e2675 --- /dev/null +++ b/MVPMusicBox/MusicAPI/FakeConnection.cs @@ -0,0 +1,25 @@ +using Mirror; +using System; + +namespace MVPMusicBox.MusicAPI +{ + internal class FakeConnection : NetworkConnectionToClient + { + public FakeConnection(int networkConnectionId) : base(networkConnectionId) + { + + } + + public override string address => "localhost"; + + public override void Send(ArraySegment segment, int channelId = 0) + { + + } + + public override void Disconnect() + { + + } + } +} diff --git a/MVPMusicBox/MusicAPI/PlayMusic.cs b/MVPMusicBox/MusicAPI/PlayMusic.cs new file mode 100644 index 0000000..301e39a --- /dev/null +++ b/MVPMusicBox/MusicAPI/PlayMusic.cs @@ -0,0 +1,40 @@ +using Exiled.API.Features; +using Mirror; +using PlayerRoles; +using SCPSLAudioApi.AudioCore; +using System.Collections.Generic; +using UnityEngine; +using VoiceChat; + +namespace MVPMusicBox.MusicAPI +{ + public static class PlayMusic + { + public static List audios = new List(); + public static AudioPlayerBase GlobalPlayMusic(string Path,string musicname,string Name = "Unknown") + { + GameObject player1 = Object.Instantiate(NetworkManager.singleton.playerPrefab); + int networkConnectionId = new System.Random().Next(250, 301); + NetworkServer.AddPlayerForConnection(new FakeConnection(networkConnectionId), player1); + ReferenceHub component = player1.GetComponent(); + Player player = Player.Get(component); + player.DisplayNickname = Name; + AudioPlayerBase audioPlayerBase = AudioPlayerBase.Get(component); + string str = Path + "\\" + musicname + ".ogg"; + audioPlayerBase.Enqueue(str, -1); + audioPlayerBase.LogDebug = false; + audioPlayerBase.Volume = 50; + audioPlayerBase.BroadcastChannel = VoiceChatChannel.Intercom; + audioPlayerBase.Loop = false; + audioPlayerBase.Play(-1); + component.roleManager.InitializeNewRole(RoleTypeId.Overwatch, RoleChangeReason.RemoteAdmin); + audios.Add(new WarppedAudio() + { + Player = audioPlayerBase, + Music = musicname, + Verfiy = $"{musicname}-{networkConnectionId}@server" + }); + return audioPlayerBase; + } + } +} diff --git a/MVPMusicBox/MusicAPI/WarppedAudio.cs b/MVPMusicBox/MusicAPI/WarppedAudio.cs new file mode 100644 index 0000000..43bf5c2 --- /dev/null +++ b/MVPMusicBox/MusicAPI/WarppedAudio.cs @@ -0,0 +1,11 @@ +using SCPSLAudioApi.AudioCore; + +namespace MVPMusicBox.MusicAPI +{ + public class WarppedAudio + { + public AudioPlayerBase Player { get; set; } + public string Music { get; set; } + public string Verfiy { get; set; } + } +} diff --git a/MVPMusicBox/Plugin.cs b/MVPMusicBox/Plugin.cs new file mode 100644 index 0000000..8cf034c --- /dev/null +++ b/MVPMusicBox/Plugin.cs @@ -0,0 +1,21 @@ +using Exiled.API.Features; + +namespace MVPMusicBox +{ + public class Plugin : Plugin + { + public override string Author { get; } = "萌新社区服务器"; + public override string Name { get; } = "MVPMusicBox"; + public override void OnEnabled() + { + Log.Info("加载MVP音乐盒插件! By 萌新社区服务器"); + EventHandlers.MVPMusic.RegMusic(); + base.OnEnabled(); + } + public override void OnDisabled() + { + EventHandlers.MVPMusic.UnRegMusic(); + base.OnDisabled(); + } + } +} diff --git a/MVPMusicBox/Properties/AssemblyInfo.cs b/MVPMusicBox/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5dc0194 --- /dev/null +++ b/MVPMusicBox/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("MVPMusicBox")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("萌新社区服务器")] +[assembly: AssemblyProduct("MVPMusicBox")] +[assembly: AssemblyCopyright("©萌新社区服务器 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("120e5b85-75f0-4d97-91a6-203af884baac")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")]