diff --git a/Exemple-Plugin/Exemple-Plugin.csproj b/Exemple-Plugin/Exemple-Plugin.csproj index 79cb81e..9e4765b 100644 --- a/Exemple-Plugin/Exemple-Plugin.csproj +++ b/Exemple-Plugin/Exemple-Plugin.csproj @@ -35,19 +35,19 @@ ..\packages\Lib.Harmony.2.2.1\lib\net48\0Harmony.dll - ..\packages\SynapseSL.2.9.0\lib\net472\Assembly-CSharp.dll + ..\packages\SynapseSL.2.10.0\lib\net472\Assembly-CSharp.dll - ..\packages\SynapseSL.2.9.0\lib\net472\Assembly-CSharp-firstpass.dll + ..\packages\SynapseSL.2.10.0\lib\net472\Assembly-CSharp-firstpass.dll ..\packages\LiteDB.5.0.11\lib\net45\LiteDB.dll - ..\packages\SynapseSL.2.9.0\lib\net472\Mirror.dll + ..\packages\SynapseSL.2.10.0\lib\net472\Mirror.dll - - ..\packages\SynapseSL.2.9.0\lib\net472\Synapse.dll + + ..\packages\SynapseSL.2.10.0\lib\net472\Synapse.dll @@ -59,13 +59,13 @@ - ..\packages\SynapseSL.2.9.0\lib\net472\UnityEngine.dll + ..\packages\SynapseSL.2.10.0\lib\net472\UnityEngine.dll - ..\packages\SynapseSL.2.9.0\lib\net472\UnityEngine.CoreModule.dll + ..\packages\SynapseSL.2.10.0\lib\net472\UnityEngine.CoreModule.dll - ..\packages\SynapseSL.2.9.0\lib\net472\UnityEngine.PhysicsModule.dll + ..\packages\SynapseSL.2.10.0\lib\net472\UnityEngine.PhysicsModule.dll ..\packages\YamlDotNet.11.2.1\lib\net45\YamlDotNet.dll diff --git a/Exemple-Plugin/packages.config b/Exemple-Plugin/packages.config index 3d5dd8f..27c73f5 100644 --- a/Exemple-Plugin/packages.config +++ b/Exemple-Plugin/packages.config @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/VT-Api/Config/Config.cs b/VT-Api/Config/Config.cs index e2a842a..68a02c1 100644 --- a/VT-Api/Config/Config.cs +++ b/VT-Api/Config/Config.cs @@ -26,7 +26,8 @@ internal void Init() NotANumber = "Das Argument muss eine Zahl sein. Beispiel : 1", RankOver = "GIB ANWEISUNGEN", RankSame = "GLEICHER RANG", - RankUnder = "FOLGE ANWEISUNGEN" + RankUnder = "FOLGE ANWEISUNGEN", + DefaultDeathMessage = "Du wurdest gertöet von\\n%PlayerName%\\nals\\n%RoleName%" }, "GERMAN"); VtTranslation.AddTranslation(new VtApiTranslation { @@ -34,7 +35,8 @@ internal void Init() NotANumber = "L'argument doit être un nombre. Exemple : 1", RankOver = "VOUS POUVEZ LUI DONNER DES ORDRES", RankSame = "MÊME NIVEAU D'ACCRÉDITATION", - RankUnder = "SUIVEZ SES ORDRES" + RankUnder = "SUIVEZ SES ORDRES", + DefaultDeathMessage = "Vous avez été tué par:\\n%PlayerName%\\nen tent que:\\n%RoleName%" }, "FRENCH"); diff --git a/VT-Api/Config/VtApiConfiguration.cs b/VT-Api/Config/VtApiConfiguration.cs index 5524e9c..04323d8 100644 --- a/VT-Api/Config/VtApiConfiguration.cs +++ b/VT-Api/Config/VtApiConfiguration.cs @@ -10,8 +10,8 @@ namespace VT_Api.Config { public class VtApiConfiguration : AbstractConfigSection { - [Description("Juste a stupide Test ¯\\_(ツ)_/¯ ")] - public bool Train { get; set; } = true; + [Description("If active then the plugins and the api this metron is up to date on its own")] + public bool AutoUpdate { get; set; } = true; } } diff --git a/VT-Api/Config/VtApiTranslation.cs b/VT-Api/Config/VtApiTranslation.cs index 7babdfb..c210043 100644 --- a/VT-Api/Config/VtApiTranslation.cs +++ b/VT-Api/Config/VtApiTranslation.cs @@ -6,12 +6,15 @@ namespace VT_Api.Config public class VtApiTranslation : IPluginTranslation { [Description("Message returned when a player has no power for their role")] - public string NoPower = "You don't have any power"; - public string NotANumber = "The argument must be a number. exemple : 1"; + public string NoPower { get; set; } = "You don't have any power"; + public string NotANumber { get; set; } = "The argument must be a number. exemple : 1"; [Description("The info about levels of accreditation")] - public string RankOver = "GIVE ORDERS"; - public string RankSame = "SAME RANK"; - public string RankUnder = "FOLLOW ORDERS"; + public string RankOver { get; set; } = "GIVE ORDERS"; + public string RankSame { get; set; } = "SAME RANK"; + public string RankUnder { get; set; } = "FOLLOW ORDERS"; + + [Description("The death message when you are kill by a custom class of the VT-API")] + public string DefaultDeathMessage { get; set; } = "You were killed by\\n%PlayerName%\\nas\\n%RoleName%"; } } diff --git a/VT-Api/Core/Behaviour/Display.cs b/VT-Api/Core/Behaviour/Display.cs index 08d05a4..3e10f0f 100644 --- a/VT-Api/Core/Behaviour/Display.cs +++ b/VT-Api/Core/Behaviour/Display.cs @@ -215,11 +215,13 @@ public string BuildCustomInfo() displayWhitHierachy += Config.Config.Get.VtTranslation.ActiveTranslation.RankSame; } NetworkLiar.Get.SendDisplayInfo(Player, displayWhitHierachy, new List() { player }); + NetworkLiar.Get.SebdInfoToDisplay(Player, PlayerInfoArea.CustomInfo, Server.Get.Players); } } else { NetworkLiar.Get.SendDisplayInfo(Player, display, Server.Get.Players); + NetworkLiar.Get.SebdInfoToDisplay(Player, PlayerInfoArea.CustomInfo, Server.Get.Players); } } #endregion diff --git a/VT-Api/Core/Behaviour/RepeatingBehaviour.cs b/VT-Api/Core/Behaviour/RepeatingBehaviour.cs index 940289b..0332774 100644 --- a/VT-Api/Core/Behaviour/RepeatingBehaviour.cs +++ b/VT-Api/Core/Behaviour/RepeatingBehaviour.cs @@ -27,8 +27,15 @@ public RepeatingBehaviour() : base() { } #region Methods public override void Kill() { - OnDisable(); - base.Kill(); + try + { + OnDisable(); + base.Kill(); + } + catch (Exception e) + { + Synapse.Api.Logger.Get.Error($"Vt-Event: RepeatingBehaviour kill faild!!\n{e}\nStackTrace:\n{e.StackTrace}"); + } } /// @@ -64,8 +71,11 @@ private void ActionExecute() private void ActionStop() { - _Started = false; - CancelInvoke("BehaviourAction"); + if (_Started) + { + CancelInvoke("BehaviourAction"); + _Started = false; + } } #endregion } diff --git a/VT-Api/Core/Behaviour/RoundBehaviour.cs b/VT-Api/Core/Behaviour/RoundBehaviour.cs index fda712a..8c63584 100644 --- a/VT-Api/Core/Behaviour/RoundBehaviour.cs +++ b/VT-Api/Core/Behaviour/RoundBehaviour.cs @@ -21,6 +21,7 @@ public virtual void Kill() { try { + Server.Get.Events.Round.RoundRestartEvent -= Kill; Destroy(this); } catch (Exception e) diff --git a/VT-Api/Core/Command/CommandHandler.cs b/VT-Api/Core/Command/CommandHandler.cs index b2c8e4a..1be781d 100644 --- a/VT-Api/Core/Command/CommandHandler.cs +++ b/VT-Api/Core/Command/CommandHandler.cs @@ -12,9 +12,8 @@ public class CommandHandler internal void Init() { + RegisterVtCommands(); Synapse.Api.Events.EventHandler.Get.Round.WaitingForPlayersEvent += RegisterSubCommand; - - RegisterVtCommands(); } public static CommandHandler Get { get => VtController.Get.Commands; } @@ -101,6 +100,7 @@ private void RegisterVtCommands() { if (!_firstLoad) return; + Logger.Get.Info("Register Command"); RegisterSynapseCommand(new CallPower(), false); } diff --git a/VT-Api/Core/Command/Commands/CallPower.cs b/VT-Api/Core/Command/Commands/CallPower.cs index 892c5ac..7102545 100644 --- a/VT-Api/Core/Command/Commands/CallPower.cs +++ b/VT-Api/Core/Command/Commands/CallPower.cs @@ -14,7 +14,7 @@ namespace VT_Api.Core.Command.Commands Description = "Call the power of your role", Usage = "no argument if you want to call your main power, if not add the id of the power", Permission = "", - Platforms = new[] { Platform.RemoteAdmin, Platform.ServerConsole }, + Platforms = new[] { Platform.ServerConsole }, Arguments = new[] { "(powerId)" } )] public class CallPower : ISynapseCommand diff --git a/VT-Api/Core/Enum/AudioStatus.cs b/VT-Api/Core/Enum/AudioStatus.cs new file mode 100644 index 0000000..2ef36ff --- /dev/null +++ b/VT-Api/Core/Enum/AudioStatus.cs @@ -0,0 +1,9 @@ +namespace VT_Api.Core.Enum +{ + public enum AudioStatus + { + Stopped, + Playing, + Paused, + } +} diff --git a/VT-Api/Core/Enum/RoleID.cs b/VT-Api/Core/Enum/RoleID.cs index 5d54166..897d10a 100644 --- a/VT-Api/Core/Enum/RoleID.cs +++ b/VT-Api/Core/Enum/RoleID.cs @@ -92,8 +92,10 @@ public enum RoleID /// TestClass = 200, /// - /// Class201 is only use for dev test or Exemple of code + /// Class 201 is only use for dev test or Exemple of code /// Class201 = 201, + SaphirLeader = 300, + SaphirPrivate = 301, } } diff --git a/VT-Api/Core/Enum/TeamID.cs b/VT-Api/Core/Enum/TeamID.cs index fcf8242..64f6991 100644 --- a/VT-Api/Core/Enum/TeamID.cs +++ b/VT-Api/Core/Enum/TeamID.cs @@ -21,5 +21,6 @@ public enum TeamID ASI = 17, AL1 = 18, GOC = 19, + SAP = 20, } } diff --git a/VT-Api/Core/Events/EventArguments/PlayerEventArgs.cs b/VT-Api/Core/Events/EventArguments/PlayerEventArgs.cs index 6d9e715..8c2b5b7 100644 --- a/VT-Api/Core/Events/EventArguments/PlayerEventArgs.cs +++ b/VT-Api/Core/Events/EventArguments/PlayerEventArgs.cs @@ -13,6 +13,14 @@ public class PlayerDamagePostEventArgs : Synapse.Api.Events.EventHandler.ISynaps public DamageType DamageType { get; internal set; } public bool Allow { get; set; } } + public class PlayerDeathPostEventArgs : Synapse.Api.Events.EventHandler.ISynapseEventArgs + { + public Player Killer { get; internal set; } + public Player Victim { get; internal set; } + public DamageType DamageType { get; internal set; } + public bool Allow { get; set; } + } + public class PlayerDestroyEventArgs : Synapse.Api.Events.EventHandler.ISynapseEventArgs { @@ -36,11 +44,4 @@ public class PlayerSetClassAdvEventArgs : Synapse.Api.Events.EventHandler.ISynap public RoleType Role { get; internal set; } } - - public class PlayerSetClassEventArgs : Synapse.Api.Events.EventHandler.ISynapseEventArgs - { - public Player Player { get; internal set; } - public int OldID { get; internal set; } - public int NewID { get; internal set; } - } } diff --git a/VT-Api/Core/Events/ItemEvents.cs b/VT-Api/Core/Events/ItemEvents.cs index 5f82a3c..01214b3 100644 --- a/VT-Api/Core/Events/ItemEvents.cs +++ b/VT-Api/Core/Events/ItemEvents.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using VT_Api.Core.Events.EventArguments; +using VT_Api.Extension; namespace VT_Api.Core.Events { diff --git a/VT-Api/Core/Events/PlayerEvents.cs b/VT-Api/Core/Events/PlayerEvents.cs index f001b45..6f0d833 100644 --- a/VT-Api/Core/Events/PlayerEvents.cs +++ b/VT-Api/Core/Events/PlayerEvents.cs @@ -11,6 +11,7 @@ internal PlayerEvents() { } #region Events public event Synapse.Api.Events.EventHandler.OnSynapseEvent PlayerDamagePostEvent; + public event Synapse.Api.Events.EventHandler.OnSynapseEvent PlayerDeathPostEvent; public event Synapse.Api.Events.EventHandler.OnSynapseEvent PlayerUnloadEvent; public event Synapse.Api.Events.EventHandler.OnSynapseEvent PlayerSpeakIntercomEvent; public event Synapse.Api.Events.EventHandler.OnSynapseEvent PlayerSetClassAdvEvent; @@ -29,6 +30,21 @@ internal void InvokePlayerSetClassAdvEvent(Player player, RoleType role) PlayerSetClassAdvEvent?.Invoke(ev); } + internal void InvokePlayerDeathPostEvent(Player victim, Player killer, DamageType type, ref bool allow) + { + var ev = new PlayerDeathPostEventArgs + { + Allow = allow, + DamageType = type, + Killer = killer, + Victim = victim + }; + + PlayerDeathPostEvent?.Invoke(ev); + + allow = ev.Allow; + } + internal void InvokePlayerSpeakIntercomEvent(Player player, ref bool allow) { var ev = new PlayerSpeakIntercomEventEventArgs diff --git a/VT-Api/Core/Items/ItemManager.cs b/VT-Api/Core/Items/ItemManager.cs index 13488a1..6843e77 100644 --- a/VT-Api/Core/Items/ItemManager.cs +++ b/VT-Api/Core/Items/ItemManager.cs @@ -81,8 +81,16 @@ public IWeapon GetWeaponScript(SynapseItem item) => item?.ItemData[KeySynapseItemData] as IWeapon; /// if item ave no script or if is else return - public bool TryGetScript(SynapseItem item, out IItem script) - => (script = GetScript(item)) != null; + public bool TryGetScript(SynapseItem item, out IItem script) + { + if (item?.ItemData == null || !item.ItemData.TryGetValue(KeySynapseItemData, out var data)) + { + script = null; + return false; + } + script = data as IItem; + return true; + } /// if item ave no script as a or if is else return public bool TryGetWeaponScript(SynapseItem item, out IWeapon script) diff --git a/VT-Api/Core/MapAndRoundManger.cs b/VT-Api/Core/MapAndRoundManger.cs index 82c1439..0f48c1e 100644 --- a/VT-Api/Core/MapAndRoundManger.cs +++ b/VT-Api/Core/MapAndRoundManger.cs @@ -12,6 +12,9 @@ using UERandom = UnityEngine.Random; using Logger = Synapse.Api.Logger; using SynRagdoll = Synapse.Api.Ragdoll; +using MEC; +using InventorySystem.Items.Firearms; +using Synapse.Api.Enum; namespace VT_Api.Core { @@ -67,7 +70,7 @@ public Vector3[] AirbombPos } } - public IEnumerator AirBomb(int waitforready, int limit) + private IEnumerator AirBomb(int waitforready, int limit, Player player) { if (isAirBombCurrently) yield break; @@ -91,10 +94,11 @@ public IEnumerator AirBomb(int waitforready, int limit) int throwcount = 0; while (isAirBombCurrently) { - List randampos = AirbombPos.OrderBy(x => Guid.NewGuid()).ToList(); + List randampos = AirbombPos.ToList(); + randampos.ShuffleList(); foreach (var pos in randampos) { - Map.Get.SpawnGrenade(pos, Vector3.zero, 0.1f); + Map.Get.SpawnGrenade(pos, Vector3.zero, 0.1f, player : player); yield return MEC.Timing.WaitForSeconds(0.1f); } throwcount++; @@ -169,8 +173,8 @@ public int GetVoltage() return (int)totalvoltagefloat; } - public void StartAirBombardement(int waitforready = 10, int limit = 5) - => MEC.Timing.RunCoroutine(MapAndRoundManger.Get.AirBomb(waitforready, limit)); + public void StartAirBombardement(int waitforready = 10, int limit = 5, Player player = null) + => MEC.Timing.RunCoroutine(MapAndRoundManger.Get.AirBomb(waitforready, limit, player)); public void PlayAmbientSound(int id) => Server.Get.Host.GetComponent().RpcPlaySound(id); @@ -190,85 +194,101 @@ public void ResetRoomsLightColor() room.ResetRoomLightColor(); } + const float MtfRespawnTimeEffect = 17.95f; + const float ChiRespawnTimeEffect = 13.49f; + public void MtfRespawn(bool isCI, List players, bool useTicket = true) // TODO { - SpawnableTeamType Team = isCI ? SpawnableTeamType.ChaosInsurgency : SpawnableTeamType.NineTailedFox; - Logger.Get.Debug("MtfRespawn 1"); - players.RemoveAll(p => p.OverWatch); - Logger.Get.Debug("MtfRespawn 2"); - if (!players.Any()) return; - Logger.Get.Debug("MtfRespawn 3"); - Queue queueToFill = new Queue(); - SpawnableTeamHandlerBase spawnableTeamHandlerBase = RespawnWaveGenerator.SpawnableTeams[Team]; - spawnableTeamHandlerBase.GenerateQueue(queueToFill, players.Count); - Logger.Get.Debug("MtfRespawn 4"); - if (useTicket) + if (isCI) + Round.Get.PlayChaosSpawnSound(); + Round.Get.SpawnVehicle(isCI); + + Timing.CallDelayed(isCI ? ChiRespawnTimeEffect : MtfRespawnTimeEffect, () => { - Logger.Get.Debug("MtfRespawn 4.1"); - if (Round.Get.PrioritySpawn) - players = players.OrderBy(p => p.DeathTime).ToList(); - else - players.ShuffleList(); - Logger.Get.Debug("MtfRespawn 4.2"); - - int tickets = RespawnTickets.Singleton.GetAvailableTickets(Team); - if (tickets == 0) + var Team = isCI ? SpawnableTeamType.ChaosInsurgency : SpawnableTeamType.NineTailedFox; + players.RemoveAll(p => p.OverWatch); + if (!players.Any()) return; + var queueToFill = new Queue(); + var spawnableTeamHandlerBase = RespawnWaveGenerator.SpawnableTeams[Team]; + spawnableTeamHandlerBase.GenerateQueue(queueToFill, players.Count); + if (useTicket) { - tickets = 5; - RespawnTickets.Singleton.GrantTickets(SpawnableTeamType.ChaosInsurgency, 5, true); - } + if (Round.Get.PrioritySpawn) + players = players.OrderBy(p => p.DeathTime).ToList(); + else + players.ShuffleList(); - Logger.Get.Debug("MtfRespawn 4.3"); - int num = Mathf.Min(tickets, spawnableTeamHandlerBase.MaxWaveSize); - while (players.Count > num) - players.RemoveAt(players.Count - 1); + int tickets = RespawnTickets.Singleton.GetAvailableTickets(Team); + if (tickets == 0) + { + tickets = 5; + RespawnTickets.Singleton.GrantTickets(SpawnableTeamType.ChaosInsurgency, 5, true); + } - Logger.Get.Debug("MtfRespawn 4.4"); - } - players.ShuffleList(); - Logger.Get.Debug("MtfRespawn 5"); - string unityName = ""; - bool setUnite = UnitNamingRules.TryGetNamingRule(Team, out UnitNamingRule rule); - Logger.Get.Debug("MtfRespawn 6"); + int num = Mathf.Min(tickets, spawnableTeamHandlerBase.MaxWaveSize); + while (players.Count > num) + players.RemoveAt(players.Count - 1); - if (setUnite) - { - rule.GenerateNew(Team, out unityName); - rule.PlayEntranceAnnouncement(unityName); - } - Logger.Get.Debug("MtfRespawn 7"); + } + players.ShuffleList(); + var unityName = ""; + var setUnite = UnitNamingRules.TryGetNamingRule(Team, out UnitNamingRule rule); - foreach (var player in players) - { - try + if (setUnite) { - Logger.Get.Debug($"MtfRespawn {player.name}"); + rule.GenerateNew(Team, out unityName); + rule.PlayEntranceAnnouncement(unityName); + } - if (player == null) + foreach (var player in players) + { + try { - Logger.Get.Error("Couldn't spawn a player - target's is null."); - continue; + if (player == null) + { + Logger.Get.Error("Couldn't spawn a player - target's is null."); + continue; + } + + player.RoleID = (int)queueToFill.Dequeue(); + + if (setUnite) + { + player.ClassManager.NetworkCurSpawnableTeamType = (byte)Team; + player.UnitName = unityName; + } } - - player.RoleID = (int)queueToFill.Dequeue(); - - if (setUnite) + catch (Exception e) { - player.ClassManager.NetworkCurSpawnableTeamType = (byte)Team; - player.UnitName = unityName; + Logger.Get.Error($"Player {player.name} couldn't be spawned. Err msg: {e.Message}"); } } - catch (Exception e) + RespawnManager.Singleton.RestartSequence(); + }); + } + + public void PlayShoot(ShootSound sound, Vector3 position, byte shootSoundDistance = 25) + { + foreach (var player in Server.Get.Players) + { + var msg = new GunAudioMessage(player, 0, shootSoundDistance, player); + var to = position - player.Position; + + if (player.RoleType != RoleType.Spectator && to.sqrMagnitude > 1760f) { - Logger.Get.Error($"Player {player.name} couldn't be spawned. Err msg: {e.Message}"); + to.y = 0f; + var num = Vector3.Angle(Vector3.forward, to); + if (Vector3.Dot(to.normalized, Vector3.left) > 0f) + num = 360f - num; + + msg.ShooterDirection = (byte)Mathf.RoundToInt(num / 1.44f); + msg.ShooterRealDistance = (byte)Mathf.RoundToInt(Mathf.Min(to.magnitude, 255f)); } - } - Logger.Get.Debug("MtfRespawn 8"); - RespawnEffectsController.ExecuteAllEffects(RespawnEffectsController.EffectType.UponRespawn, Team); - RespawnManager.Singleton.RestartSequence(); - Logger.Get.Debug("MtfRespawn 9"); + msg.Weapon = (ItemType)sound; + player.Connection.Send(msg); + } } } } diff --git a/VT-Api/Core/MiniGame/MiniGameManager.cs b/VT-Api/Core/MiniGame/MiniGameManager.cs index 3960786..18f9b96 100644 --- a/VT-Api/Core/MiniGame/MiniGameManager.cs +++ b/VT-Api/Core/MiniGame/MiniGameManager.cs @@ -41,6 +41,7 @@ internal void Init() Synapse.Api.Events.EventHandler.Get.Round.RoundEndEvent += OnEndRound; Synapse.Api.Events.EventHandler.Get.Round.RoundCheckEvent += OnCheckEnd; } + public string GetMiniGameName(int id) { if (!IsIDRegistered(id)) diff --git a/VT-Api/Core/NetworkLiar.cs b/VT-Api/Core/NetworkLiar.cs index 59fa282..ffd2ab8 100644 --- a/VT-Api/Core/NetworkLiar.cs +++ b/VT-Api/Core/NetworkLiar.cs @@ -49,6 +49,43 @@ public void SendRole(Player player, RoleType info, List players) SendAndRecycle(owner, observer, players, player); } + public void SebdInfoToDisplay(Player player, PlayerInfoArea info, List players) + { + const byte bytecodes = 4; + + var owner = NetworkWriterPool.GetWriter(); + var observer = NetworkWriterPool.GetWriter(); + + // Get behavior and index of it + GetBehaviour(player.Hub.networkIdentity, out var behaviourIndex, out var behaviour); + + // Writ + owner.WriteByte((byte)behaviourIndex); + + var positionRef = owner.Position; + owner.WriteInt32(0); + var positionData = owner.Position; + + behaviour.SerializeObjectsDelta(owner); + + // Write var + owner.WriteUInt64(bytecodes); + owner.WriteByte((byte)info); + + // Write syncdata position data + WritePostion(owner, positionRef, positionData); + + // Copy owner to observer + if (behaviour.syncMode != SyncMode.Observers) + { + var arraySegment = owner.ToArraySegment(); + observer.WriteBytes(arraySegment.Array, positionRef, owner.Position - positionRef); + } + + //send + SendAndRecycle(owner, observer, players, player); + } + public void SendDisplayInfo(Player player, string info, List players) { const byte bytecodes = 2; diff --git a/VT-Api/Core/Plugin/AutoRegisterManager.cs b/VT-Api/Core/Plugin/AutoRegisterManager.cs index d6fd514..df81366 100644 --- a/VT-Api/Core/Plugin/AutoRegisterManager.cs +++ b/VT-Api/Core/Plugin/AutoRegisterManager.cs @@ -13,7 +13,7 @@ public class AutoRegisterManager internal AutoRegisterManager() { } - readonly IContextProcessor[] AddedRegisterProcesses = { new CommandProcess(), new ItemProcess(), new MiniGameProcess(), new RoleProcess(), new TeamProcess(), new DebugCheckProcess() }; + readonly IContextProcessor[] AddedRegisterProcesses = { new CommandProcess(), new ItemProcess(), new MiniGameProcess(), new RoleProcess(), new TeamProcess(), new DebugCheckProcess(), new AutoUpdatePorecess() }; internal void Init() { diff --git a/VT-Api/Core/Plugin/Process/AutoUpdatePorecess.cs b/VT-Api/Core/Plugin/Process/AutoUpdatePorecess.cs index c50dfe6..791b8c7 100644 --- a/VT-Api/Core/Plugin/Process/AutoUpdatePorecess.cs +++ b/VT-Api/Core/Plugin/Process/AutoUpdatePorecess.cs @@ -9,16 +9,22 @@ internal class AutoUpdatePorecess : IContextProcessor { public void Process(PluginLoadContext context) { + if (!VtController.Get.Configs.VtConfiguration.AutoUpdate) + return; + foreach (Type autoUpdate in context.Classes) { try { - if (!typeof(IAutoUpdate).IsAssignableFrom(autoUpdate) || autoUpdate.GetCustomAttribute() != null) + if (!typeof(IAutoUpdate).IsAssignableFrom(autoUpdate) || autoUpdate.GetCustomAttribute(false) != null) continue; var autoUpdater = (IAutoUpdate)Activator.CreateInstance(autoUpdate); - autoUpdater.Update(); + var isUpdate = autoUpdater.Update(); + + if (isUpdate) + Synapse.Api.Logger.Get.Warn($"Plugin {context.Plugin.Information.Name} is now Update ! You need to restart the server for use the new version"); } catch (Exception e) { diff --git a/VT-Api/Core/Plugin/Process/ItemProcess.cs b/VT-Api/Core/Plugin/Process/ItemProcess.cs index 17b8bda..d71c4ad 100644 --- a/VT-Api/Core/Plugin/Process/ItemProcess.cs +++ b/VT-Api/Core/Plugin/Process/ItemProcess.cs @@ -14,7 +14,7 @@ public void Process(PluginLoadContext context) foreach (var itemType in context.Classes) { - if (!typeof(IItem).IsAssignableFrom(itemType) || itemType.GetCustomAttribute() != null) + if (!typeof(IItem).IsAssignableFrom(itemType) || itemType.GetCustomAttribute(false) != null) continue; try diff --git a/VT-Api/Core/Plugin/Process/MiniGameProcess.cs b/VT-Api/Core/Plugin/Process/MiniGameProcess.cs index 3ac1756..2a75eef 100644 --- a/VT-Api/Core/Plugin/Process/MiniGameProcess.cs +++ b/VT-Api/Core/Plugin/Process/MiniGameProcess.cs @@ -14,7 +14,7 @@ public void Process(PluginLoadContext context) foreach (var miniGameType in context.Classes) { - if (!typeof(IMiniGame).IsAssignableFrom(miniGameType) || miniGameType.GetCustomAttribute() != null) + if (!typeof(IMiniGame).IsAssignableFrom(miniGameType) || miniGameType.GetCustomAttribute(false) != null) continue; try diff --git a/VT-Api/Core/Plugin/Process/RoleProcess.cs b/VT-Api/Core/Plugin/Process/RoleProcess.cs index b9a23e3..b11af91 100644 --- a/VT-Api/Core/Plugin/Process/RoleProcess.cs +++ b/VT-Api/Core/Plugin/Process/RoleProcess.cs @@ -16,7 +16,7 @@ public void Process(PluginLoadContext context) foreach (var roleType in context.Classes) { - if (!typeof(IRole).IsAssignableFrom(roleType) || roleType.GetCustomAttribute() != null) + if (!typeof(IRole).IsAssignableFrom(roleType) || roleType.GetCustomAttribute(false) != null) continue; try diff --git a/VT-Api/Core/Plugin/Process/TeamProcess.cs b/VT-Api/Core/Plugin/Process/TeamProcess.cs index ca05af4..a37adbe 100644 --- a/VT-Api/Core/Plugin/Process/TeamProcess.cs +++ b/VT-Api/Core/Plugin/Process/TeamProcess.cs @@ -16,7 +16,7 @@ public void Process(PluginLoadContext context) foreach (var teamType in context.Classes) { - if (!typeof(Synapse.Api.Teams.ISynapseTeam).IsAssignableFrom(teamType) || teamType.GetCustomAttribute() != null) + if (!typeof(Synapse.Api.Teams.ISynapseTeam).IsAssignableFrom(teamType) || teamType.GetCustomAttribute(false) != null) continue; try diff --git a/VT-Api/Core/Plugin/Updater/AbstractAutoUpdater.cs b/VT-Api/Core/Plugin/Updater/AbstractAutoUpdater.cs index 137d171..020aa68 100644 --- a/VT-Api/Core/Plugin/Updater/AbstractAutoUpdater.cs +++ b/VT-Api/Core/Plugin/Updater/AbstractAutoUpdater.cs @@ -1,4 +1,5 @@ -using Synapse.Api.Plugin; +using Synapse; +using Synapse.Api.Plugin; using System; using System.Collections.Generic; using System.Linq; @@ -9,14 +10,14 @@ namespace VT_Api.Core.Plugin.Updater { - internal abstract class AbstractAutoUpdater : AbstractUpdateHandler, IAutoUpdate + public abstract class AbstractAutoUpdater : AbstractUpdateHandler, IAutoUpdate where T : IPlugin { public abstract long GithubID { get; } public abstract bool Prerealase { get; } - public bool Update() + public virtual bool Update() { HttpClient client = new HttpClient(); client.Timeout = TimeSpan.FromSeconds(500); @@ -25,22 +26,23 @@ public bool Update() var githubVerison = GetGitVersion(client, string.Format(GitHubPage, GithubID), out var release, Prerealase); var pluginVersion = GetPluginVersion(); + var pluginName = typeof(T).Assembly.GetName().Name; if (!NeedToUpdate(pluginVersion, githubVerison)) return false; - if (!TryDownload(client, release, typeof(T).Assembly.GetName().Name, out var filePath)) + if (!TryDownload(client, release, pluginName, out var filePath)) return false; - - var pluginName = typeof(T).GetType().Assembly.GetName().Name; - var plugin = SynapseController.PluginLoader.GetFieldValueOrPerties>("_plugins").FirstOrDefault(p => p.GetType() == typeof(T)); if (plugin == null) throw new Exception("AutoUpdater : Plugin note found !"); - base.Replace(filePath, pluginName, plugin.PluginDirectory); + var shared = plugin.Information.GetFieldValueOrPerties("shared"); + var pluginPath = shared ? Server.Get.Files.SharedPluginDirectory : Server.Get.Files.PluginDirectory; + + base.Replace(filePath, pluginName, pluginPath); return true; } diff --git a/VT-Api/Core/Plugin/Updater/AbstractUpdateHandler.cs b/VT-Api/Core/Plugin/Updater/AbstractUpdateHandler.cs index af1dcae..fa15a49 100644 --- a/VT-Api/Core/Plugin/Updater/AbstractUpdateHandler.cs +++ b/VT-Api/Core/Plugin/Updater/AbstractUpdateHandler.cs @@ -20,8 +20,9 @@ public abstract class AbstractUpdateHandler : IUpdateHandler { #region Properties & Variable public const string Unknow = "Unknown"; - public const string GitHubPage = "https://api.github.com/repositories/{0}/releases/?per_page=20&page=1"; - public const string DefaultsRegexVersion = @"[v,V]?(?\d+)\.(?\d+)\.(?\d+)"; + public const string GitHubPage = "https://api.github.com/repositories/{0}/releases?per_page=20&page=1"; + + private static bool FirstLoad { get; set; } = true; private string _tempDirectory; public string TempDirectory @@ -84,7 +85,7 @@ private set } } - public virtual string RegexExpressionVersion { get; } = DefaultsRegexVersion; + public virtual string RegexExpressionVersion { get; } = PluginVersion.DefaultsRegexVersion; #endregion #region Constructor & Destructor @@ -93,18 +94,37 @@ public AbstractUpdateHandler() TempDirectory = Path.Combine(Server.Get.Files.SynapseDirectory, "temp"); DownloadDirectory = Path.Combine(_tempDirectory, "download"); OldDllDirectory = Path.Combine(_tempDirectory, "old"); + DeletetTempDirectory(); } #endregion #region Methods public void DeletetTempDirectory() { - if (!Directory.Exists(_tempDirectory)) + if (Directory.Exists(_tempDirectory) && FirstLoad) { - Directory.Delete(_tempDirectory); + DeleteDirectory(_tempDirectory); + FirstLoad = false; } } + private void DeleteDirectory(string target_dir) + { + var files = Directory.GetFiles(target_dir); + var dirs = Directory.GetDirectories(target_dir); + + foreach (var file in files) + { + File.SetAttributes(file, FileAttributes.Normal); + File.Delete(file); + } + + foreach (var dir in dirs) + DeleteDirectory(dir); + + Directory.Delete(target_dir, false); + } + public virtual bool TryDownload(HttpClient client, Release release, string name, out string filePath) { var asset = release.Assets.FirstOrDefault(r => r.Name.Contains(name) && r.Name.Contains(".dll")); @@ -125,7 +145,7 @@ public virtual bool TryDownload(HttpClient client, Release release, string name, return true; } - public virtual Version GetPluginVersion() + public virtual PluginVersion GetPluginVersion() { var info = (PluginInformation)Attribute.GetCustomAttribute(typeof(T), typeof(PluginInformation)); if (info.Version == Unknow) @@ -135,20 +155,20 @@ public virtual Version GetPluginVersion() else throw new VtUnknownVersionException($"Vt-AutoUppdate : The plugin {info.Name} in the assembly {typeof(T).Assembly.GetName().Name} did not set its version", typeof(T).Assembly.FullName, info.Name); } - return new Version(info.Version, RegexExpressionVersion); + return new PluginVersion(info.Version, RegexExpressionVersion); } - public virtual Version GetGitVersion(HttpClient client, string link, out Release release, bool prerealase = false) + public virtual PluginVersion GetGitVersion(HttpClient client, string link, out Release release, bool prerealase = false) { var realases = GetRealases(client, link); - Version highestVersion = new Version(0,0,0); + PluginVersion highestVersion = new PluginVersion(0,0,0); Release highestRelease = null; foreach (var realase in realases) { if (!prerealase && realase.PreRelease) continue; - if (Version.TryParse(realase.TagName, out var version) && version > highestVersion) + if (PluginVersion.TryParse(realase.TagName, out var version) && version > highestVersion) { highestVersion = version; highestRelease = realase; @@ -170,7 +190,7 @@ private List GetRealases(HttpClient client, string link) return JsonSerializer.Deserialize(stream).OrderByDescending(r => r.CreatedAt.Ticks).ToList(); } - public virtual bool NeedToUpdate(Version PluginVersion, Version GitVersion) + public virtual bool NeedToUpdate(PluginVersion PluginVersion, PluginVersion GitVersion) => PluginVersion < GitVersion; public virtual void Replace(string newPluginPath, string pluinName, string pluginDirectory) diff --git a/VT-Api/Core/Plugin/Updater/IUpdateHandler.cs b/VT-Api/Core/Plugin/Updater/IUpdateHandler.cs index 0f30101..20775c5 100644 --- a/VT-Api/Core/Plugin/Updater/IUpdateHandler.cs +++ b/VT-Api/Core/Plugin/Updater/IUpdateHandler.cs @@ -8,9 +8,9 @@ public interface IUpdateHandler string RegexExpressionVersion { get; } void DeletetTempDirectory(); - Version GetPluginVersion(); - Version GetGitVersion(HttpClient client, string link, out Release release, bool ignorePrerealase = true); - bool NeedToUpdate(Version PluginVersion, Version GitVersion); + PluginVersion GetPluginVersion(); + PluginVersion GetGitVersion(HttpClient client, string link, out Release release, bool ignorePrerealase = true); + bool NeedToUpdate(PluginVersion PluginVersion, PluginVersion GitVersion); bool TryDownload(HttpClient client, Release release, string name, out string filePath); void Replace(string newPluginPath, string pluinName, string pluginDirectory); } diff --git a/VT-Api/Core/Plugin/Updater/Release.cs b/VT-Api/Core/Plugin/Updater/Models/Release.cs similarity index 96% rename from VT-Api/Core/Plugin/Updater/Release.cs rename to VT-Api/Core/Plugin/Updater/Models/Release.cs index 54f9222..3365f7e 100644 --- a/VT-Api/Core/Plugin/Updater/Release.cs +++ b/VT-Api/Core/Plugin/Updater/Models/Release.cs @@ -8,12 +8,16 @@ public class Release { [DataMember(Name = "id")] public readonly int Id; + [DataMember(Name = "tag_name")] public readonly string TagName; + [DataMember(Name = "prerelease")] public readonly bool PreRelease; + [DataMember(Name = "created_at")] public readonly DateTime CreatedAt; + [DataMember(Name = "assets")] public readonly ReleaseAsset[] Assets; diff --git a/VT-Api/Core/Plugin/Updater/ReleaseAsset.cs b/VT-Api/Core/Plugin/Updater/Models/ReleaseAsset.cs similarity index 95% rename from VT-Api/Core/Plugin/Updater/ReleaseAsset.cs rename to VT-Api/Core/Plugin/Updater/Models/ReleaseAsset.cs index b1b5e4a..94f3ab3 100644 --- a/VT-Api/Core/Plugin/Updater/ReleaseAsset.cs +++ b/VT-Api/Core/Plugin/Updater/Models/ReleaseAsset.cs @@ -7,12 +7,16 @@ public readonly struct ReleaseAsset { [DataMember(Name = "id")] public readonly int Id; + [DataMember(Name = "name")] public readonly string Name; + [DataMember(Name = "size")] public readonly int Size; + [DataMember(Name = "url")] public readonly string Url; + [DataMember(Name = "browser_download_url")] public readonly string BrowserDownloadUrl; diff --git a/VT-Api/Core/Plugin/Updater/Version.cs b/VT-Api/Core/Plugin/Updater/PluginVersion.cs similarity index 69% rename from VT-Api/Core/Plugin/Updater/Version.cs rename to VT-Api/Core/Plugin/Updater/PluginVersion.cs index 6ac8104..fd65db9 100644 --- a/VT-Api/Core/Plugin/Updater/Version.cs +++ b/VT-Api/Core/Plugin/Updater/PluginVersion.cs @@ -2,22 +2,24 @@ namespace VT_Api.Core.Plugin.Updater { - public struct Version + public struct PluginVersion { #region Properties & Variable + public const string DefaultsRegexVersion = @"[v,V]?(?\d+)\.(?\d+)\.(?\d+)"; + int Major; int Minor; int Patch; #endregion #region Constructor & Destructor - public Version(int major, int minor, int patch = 0) + public PluginVersion(int major, int minor, int patch = 0) { Major = major; Minor = minor; Patch = patch; } - public Version(string version, string expression = @"[v,V]?(?\d+)\.(?\d+)\.(?\d+))") + public PluginVersion(string version, string expression = DefaultsRegexVersion) { var pattern = new Regex(expression); var match = pattern.Match(version); @@ -28,42 +30,42 @@ public Version(string version, string expression = @"[v,V]?(?\d+)\.(?\d+)\.(?\d+)\.(?\d+))") + public static PluginVersion Parse(string s, string expression = DefaultsRegexVersion) { var pattern = new Regex(expression); var match = pattern.Match(s); - return new Version(int.Parse(match.Groups["major"].Value), int.Parse(match.Groups["minor"].Value), int.Parse(match.Groups["patch"].Value)); + return new PluginVersion(int.Parse(match.Groups["major"].Value), int.Parse(match.Groups["minor"].Value), int.Parse(match.Groups["patch"].Value)); } - public static bool TryParse(string s, out Version version, string expression = @"[v,V]?(?\d+)\.(?\d+)\.(?\d+))") + public static bool TryParse(string s, out PluginVersion version, string expression = DefaultsRegexVersion) { var pattern = new Regex(expression); var match = pattern.Match(s); if (!match.Success) { - version = new Version(); + version = new PluginVersion(); return false; } if (!int.TryParse(match.Groups["major"].Value, out int major)) { - version = new Version(); + version = new PluginVersion(); return false; } if (!int.TryParse(match.Groups["minor"].Value, out int minor)) { - version = new Version(); + version = new PluginVersion(); return false; } if (!int.TryParse(match.Groups["patch"].Value, out int patch)) { - version = new Version(); + version = new PluginVersion(); return false; } - version = new Version(major, minor, patch); + version = new PluginVersion(major, minor, patch); return true; } @@ -88,14 +90,18 @@ public override bool Equals(object obj) else return false; } - else if (obj is Version version) + else if (obj is PluginVersion version) return version == this; return false; } + + public override string ToString() + => $"{Major}.{Minor}.{Patch}"; + #endregion #region operator - public static bool operator >(Version a, Version b) + public static bool operator >(PluginVersion a, PluginVersion b) { if (a.Major > b.Major) return true; @@ -110,7 +116,7 @@ public override bool Equals(object obj) return false; } - public static bool operator <(Version a, Version b) + public static bool operator <(PluginVersion a, PluginVersion b) { if (a.Major < b.Major) return true; @@ -125,10 +131,10 @@ public override bool Equals(object obj) return false; } - public static bool operator ==(Version a, Version b) + public static bool operator ==(PluginVersion a, PluginVersion b) => a.Patch == b.Patch && a.Minor == b.Minor && a.Major == b.Major; - public static bool operator !=(Version a, Version b) + public static bool operator !=(PluginVersion a, PluginVersion b) => a.Patch != b.Patch || a.Minor != b.Minor || a.Major != b.Major; #endregion } diff --git a/VT-Api/Core/Roles/AbstractRole.cs b/VT-Api/Core/Roles/AbstractRole.cs index 7cc0d8f..642eb01 100644 --- a/VT-Api/Core/Roles/AbstractRole.cs +++ b/VT-Api/Core/Roles/AbstractRole.cs @@ -34,16 +34,37 @@ public abstract class AbstractRole : Synapse.Api.Roles.Role, IVtRole public sealed override int GetRoleID() => RoleId; public sealed override string GetRoleName() => RoleName; public sealed override int GetTeamID() => RoleTeam; - - public virtual bool CallPower(byte power, out string message) - { - message = VtController.Get.Configs.VtTranslation.ActiveTranslation.NoPower; - return false; - } - + [Obsolete] + public sealed override List GetFriends() => new List(); + [Obsolete] + public sealed override List GetEnemys() => new List(); + [Obsolete] + public sealed override int GetEscapeRole() => 0; + [Obsolete] + public sealed override Team GetTeam() => Team.RIP; + public bool Spawned { get; set; } = false; - private static bool _fristSpawn = true; + private static List _firstSpawnClass = new List(); + + private bool _fristSpawn + { + get + { + return !_firstSpawnClass.Any(p => p == this.GetType()); + } + set + { + if (!value && !_firstSpawnClass.Any(p => p == this.GetType())) + { + _firstSpawnClass.Add(this.GetType()); + } + else if (value && _firstSpawnClass.Any(p => p == this.GetType())) + { + _firstSpawnClass.Remove(this.GetType()); + } + } + } #endregion #region Constructors & Destructor @@ -83,41 +104,21 @@ protected T ActiveComponent() [API] protected virtual void AditionalInit(PlayerSetClassEventArgs ev) { } - - public sealed override void Spawn() - { - Player.RoleType = RoleType; - - if (!string.IsNullOrEmpty(SpawnMessage)) - { - string message = Regex.Replace(SpawnMessage, "%RoleName%", RoleName, RegexOptions.IgnoreCase); - Player.OpenReportWindow(message.Replace("\\n", "\n")); - } - - SetDisplayInfo(); - } - - public virtual void SetDisplayInfo() + [API] + public virtual bool CallPower(byte power, out string message) { - Player.SetDisplayInfoRole(RoleName); + message = VtController.Get.Configs.VtTranslation.ActiveTranslation.NoPower; + return false; } /// - /// Dont call it if you dont no what you are dowing + /// Is called when the player ave the corect roleType. + /// Call the base to apply the config. /// - public void InitAll(PlayerSetClassEventArgs ev) + [API] + public virtual void Spawning() { - Spawned = true; - - if (_fristSpawn) - { - InitEvent(); - _fristSpawn = false; - } - - PlayerInit(ev); - AditionalInit(ev); } /** @@ -139,7 +140,57 @@ public void InitAll(PlayerSetClassEventArgs ev) * */ [API] - protected virtual void InitEvent() { } + protected virtual void InitEvent() + { + + } + + public virtual void SetDisplayInfo() + { + Player.SetDisplayInfoRole(RoleName); + } + + public sealed override void Spawn() + { + if (_fristSpawn) + { + InitEvent(); + _fristSpawn = false; + } + + Player.RoleType = RoleType; + + if (!string.IsNullOrEmpty(SpawnMessage)) + { + string message = Regex.Replace(SpawnMessage, "%RoleName%", RoleName, RegexOptions.IgnoreCase); + Player.OpenReportWindow(message.Replace("\\n", "\n")); + } + + SetDisplayInfo(); + if (Config != null) + { + if (Config.Health != null) + Player.Health = (float)Config.Health; + Player.MaxHealth = Config.MaxHealth ?? Player.Health; + + if (Config.ArtificialHealth != null) + Player.ArtificialHealth = (float)Config.ArtificialHealth; + if (Config.MaxArtificialHealth != null) + Player.MaxArtificialHealth = (int)Config.MaxArtificialHealth; + } + + Spawning(); + } + + public void InitAll(PlayerSetClassEventArgs ev) + { + if (Spawned) return; + Spawned = true; + + PlayerInit(ev); + + AditionalInit(ev); + } private void PlayerInit(PlayerSetClassEventArgs ev) { @@ -155,16 +206,6 @@ private void PlayerInit(PlayerSetClassEventArgs ev) if (postion != null) ev.Position = postion.Position; - - if (Config.Health != null) - ev.Player.Health = (float)Config.Health; - ev.Player.MaxHealth = Config.MaxHealth ?? ev.Player.Health; - - if (Config.ArtificialHealth != null) - ev.Player.ArtificialHealth = (float)Config.ArtificialHealth; - if (Config.MaxArtificialHealth != null) - ev.Player.MaxArtificialHealth = (int)Config.MaxArtificialHealth; - } catch (Exception e) { @@ -192,6 +233,8 @@ private void CheckItems(SerializedPlayerInventory inventory) [API] public override void DeSpawn() { + if (Player == null) + return; Player.DisplayInfo = null; Player.AddDisplayInfo(PlayerInfoArea.Role); Player.AddDisplayInfo(PlayerInfoArea.UnitName); diff --git a/VT-Api/Core/Roles/ICustomPhysicalRole.cs b/VT-Api/Core/Roles/ICustomPhysicalRole.cs new file mode 100644 index 0000000..d183e02 --- /dev/null +++ b/VT-Api/Core/Roles/ICustomPhysicalRole.cs @@ -0,0 +1,9 @@ +using Synapse.Api.Roles; + +namespace VT_Api.Core.Roles +{ + public interface ICustomPhysicalRole : IRole + { + void UpdateBody(); + } +} diff --git a/VT-Api/Core/Roles/IUtrRole.cs b/VT-Api/Core/Roles/IUtrRole.cs index b20dde7..487bca5 100644 --- a/VT-Api/Core/Roles/IUtrRole.cs +++ b/VT-Api/Core/Roles/IUtrRole.cs @@ -1,13 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Synapse.Api.Roles; namespace VT_Api.Core.Roles { - public interface IUtrRole + public interface IUtrRole : ICustomPhysicalRole { - + } } diff --git a/VT-Api/Core/Roles/IVtRole.cs b/VT-Api/Core/Roles/IVtRole.cs index d9d5bb6..1faaa23 100644 --- a/VT-Api/Core/Roles/IVtRole.cs +++ b/VT-Api/Core/Roles/IVtRole.cs @@ -1,14 +1,14 @@ using Synapse.Api.Events.SynapseEventArguments; +using Synapse.Api.Roles; namespace VT_Api.Core.Roles { - public interface IVtRole + public interface IVtRole : IRole { void InitAll(PlayerSetClassEventArgs ev); bool CallPower(byte power, out string message); bool Spawned { get; set; } - } } diff --git a/VT-Api/Core/Roles/RoleManager.cs b/VT-Api/Core/Roles/RoleManager.cs index 8577138..6498766 100644 --- a/VT-Api/Core/Roles/RoleManager.cs +++ b/VT-Api/Core/Roles/RoleManager.cs @@ -1,11 +1,20 @@ -using Synapse; +using Mirror; +using PlayerStatsSystem; +using Respawning; +using Respawning.NamingRules; +using Subtitles; +using Synapse; using Synapse.Api; using Synapse.Api.Events.SynapseEventArguments; using Synapse.Api.Roles; using System; using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; using UnityEngine; using VT_Api.Core.Enum; +using VT_Api.Core.Events.EventArguments; +using VT_Api.Core.Teams; using VT_Api.Extension; using SynRoleManager = Synapse.Api.Roles.RoleManager; @@ -14,22 +23,31 @@ namespace VT_Api.Core.Roles public class RoleManager { + #region Properties & Variable public Dictionary OldPlayerRole { get; } = new Dictionary(); + public List CustomPhysicaleRoles { get; } = new List(); + public static int[] VanilaScpID { get; } = { (int)RoleType.Scp049, (int)RoleType.Scp0492, (int)RoleType.Scp079, (int)RoleType.Scp096, (int)RoleType.Scp106, (int)RoleType.Scp173, (int)RoleType.Scp93953, (int)RoleType.Scp93989 }; public static RoleManager Get => VtController.Get.Role; + #endregion - + #region Constructor & Destructor internal RoleManager() { } + #endregion + #region Methods internal void Init() { Synapse.Api.Events.EventHandler.Get.Player.PlayerSetClassEvent += OnSetClass; - Synapse.Api.Events.EventHandler.Get.Player.PlayerDeathEvent += OnPlayerDeath; Synapse.Api.Events.EventHandler.Get.Player.PlayerKeyPressEvent += OnPressKey; + Synapse.Api.Events.EventHandler.Get.Server.UpdateEvent += OnUpdate; + Synapse.Api.Events.EventHandler.Get.Server.TransmitPlayerDataEvent += OnTransmitPlayerData; + VtController.Get.Events.Player.PlayerDeathPostEvent += OnPlayerDeath; + } public bool IsVanilla(int roleID) @@ -69,7 +87,9 @@ public int OldTeam(Player player) } return (int)TeamID.None; } + #endregion + #region Events private void OnPressKey(PlayerKeyPressEventArgs ev) { if (ev.Player.CustomRole is IVtRole role) @@ -102,22 +122,73 @@ private void OnSetClass(PlayerSetClassEventArgs ev) { if (ev.Player.CustomRole is IVtRole role && !role.Spawned) { - role.InitAll(ev); + try + { + role.InitAll(ev); + } + catch (Exception ex) + { + Synapse.Api.Logger.Get.Error($"Fail to init the role {role.GetRoleName()} (ID : {role.GetRoleID()}) :\n{ex}"); + } + } + if (ev.Player.CustomRole is ICustomPhysicalRole customPhyRole) + { + if (!CustomPhysicaleRoles.Contains(customPhyRole)) + CustomPhysicaleRoles.Add(customPhyRole); + } + else + { + customPhyRole = CustomPhysicaleRoles.FirstOrDefault(r => r?.Player == ev.Player); + if (customPhyRole != null) + CustomPhysicaleRoles.Remove(customPhyRole); } } - private void OnPlayerDeath(PlayerDeathEventArgs ev) + private void OnPlayerDeath(PlayerDeathPostEventArgs ev) { + if (!ev.Allow) + return; + if (OldPlayerRole.ContainsKey(ev.Victim)) - OldPlayerRole[ev.Victim] = ev.Victim.RoleID; - else OldPlayerRole.Add(ev.Victim, ev.Victim.RoleID); - + OldPlayerRole[ev.Victim] = ev.Victim.RoleID; + else + OldPlayerRole.Add(ev.Victim, ev.Victim.RoleID); + + if (ev.Killer?.CustomRole is IVtRole role) + { + var message = VtController.Get.Configs.VtTranslation.ActiveTranslation.DefaultDeathMessage.Replace("\\n", "\n"); + message = Regex.Replace(message, "%PlayerName%", ev.Killer.DisplayName, RegexOptions.IgnoreCase); + message = Regex.Replace(message, "%RoleName%", role.GetRoleName(), RegexOptions.IgnoreCase); + + Patches.VtPatch.CustomDeathReasonPatch.CustomReason = message; + } + if (ev.Victim.CustomRole is IScpDeathAnnonce scpDeathAnnonce) - { + { var scpName = scpDeathAnnonce.ScpName; var unityName = ev.Killer?.Team == Team.MTF ? ev.Killer.UnitName : "UNKNOWN"; Server.Get.Map.AnnounceScpDeath(scpName, ev.DamageType.GetScpRecontainmentType(ev.Killer), unityName); } } + + private void OnUpdate() + { + foreach (var utr in CustomPhysicaleRoles) + { + utr.UpdateBody(); + } + } + + private void OnTransmitPlayerData(TransmitPlayerDataEventArgs ev) + { + if (ev.PlayerToShow == ev.Player) + return; + var utr = CustomPhysicaleRoles.FirstOrDefault(p => p.Player == ev.PlayerToShow); + if (utr == null) + return; + if (ev.Player.RoleID != (int)RoleID.Staff) + ev.Invisible = false; + } + #endregion } } diff --git a/VT-Api/Core/Structur/StructureManager.cs b/VT-Api/Core/Structur/StructureManager.cs deleted file mode 100644 index 5d8b5d4..0000000 --- a/VT-Api/Core/Structur/StructureManager.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Mirror; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace VT_Api.Core.Structur -{ - internal class StructureManager - { - internal StructureManager() { } - - internal void init() - { - - } - // TODO : do som stuff here - - } -} diff --git a/VT-Api/Core/Updater.cs b/VT-Api/Core/Updater.cs new file mode 100644 index 0000000..ec14e10 --- /dev/null +++ b/VT-Api/Core/Updater.cs @@ -0,0 +1,38 @@ +using Synapse; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using VT_Api.Core.Plugin.Updater; + +namespace VT_Api.Core +{ + internal class Updater : AbstractUpdateHandler, IAutoUpdate + { + public const long GithubID = 442298975; + + public bool Update() + { + HttpClient client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(500); + client.DefaultRequestHeaders.Add("User-Agent", $"VT-API"); + + var githubVerison = GetGitVersion(client, string.Format(GitHubPage, GithubID), out var release); + var curentVersion = VtVersion.GetVersion(); + var assmeblyName = this.GetType().Assembly.GetName().Name; + + if (!NeedToUpdate(curentVersion, githubVerison)) + return false; + + if (!TryDownload(client, release, assmeblyName, out var filePath)) + return false; + + var depedencyPath = Path.Combine(Server.Get.Files.SynapseDirectory, "dependencies"); + + base.Replace(filePath, assmeblyName, depedencyPath); + + return true; + } + } +} diff --git a/VT-Api/Core/VtExtensions.cs b/VT-Api/Core/VtExtensions.cs index 036895e..b566675 100644 --- a/VT-Api/Core/VtExtensions.cs +++ b/VT-Api/Core/VtExtensions.cs @@ -265,36 +265,16 @@ public static bool TryPickup(this Player.PlayerAmmoBox ammos, SynapseItem item) public static void SetDisplayInfoRole(this Player player, string roleName) { - /* - * TODO Rework This : - * - * Badge "pas touche" - * - * Nickname - * Role (Unit) - * CustomInfo - * - * PowerStatus - */ - - // to - - /* - * - * NickName - * CustomInfo - * - * - * - * - */ - player.RemoveDisplayInfo(PlayerInfoArea.Role); if (player.Team == Team.MTF) { + if (string.IsNullOrWhiteSpace(player.UnitName)) + player.DisplayInfo = $"{roleName} ({player.UnitName})"; + else + player.DisplayInfo = roleName; + player.RemoveDisplayInfo(PlayerInfoArea.UnitName); - player.DisplayInfo = $"{roleName} ({player.UnitName})"; } else { diff --git a/VT-Api/Core/VtExtensionsReflexion.cs b/VT-Api/Core/VtExtensionsReflexion.cs index b44edbf..5c31772 100644 --- a/VT-Api/Core/VtExtensionsReflexion.cs +++ b/VT-Api/Core/VtExtensionsReflexion.cs @@ -47,7 +47,7 @@ public static T GetFieldOrPropertyValue(this Type element, string fieldName) { return (T)prop.GetValue(null); } - FieldInfo field = element.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static); + var field = element.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static); if (field != null) { return (T)field.GetValue(null); @@ -141,5 +141,27 @@ public static void CallEvent(this object element, string eventName, params objec Synapse.Api.Logger.Get.Error("Vt-Reflexion: CallEvent failed!! \n eventsField null"); } } + + public static T CopyPropertyAndFeild(this T element, T elementToCopy) + { + var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + if (props.Length != 0) + { + foreach (var prop in props) + { + if (prop.SetMethod != null) + prop.SetValue(element, prop.GetValue(elementToCopy)); + } + } + var fields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + if (fields.Length != 0) + { + foreach (var field in fields) + { + field.SetValue(element, field.GetValue(elementToCopy)); + } + } + return element; + } } } diff --git a/VT-Api/Patches/VtEvent/ItemPatches/RemoveExceedingLimitsPatch.cs b/VT-Api/Patches/VtEvent/ItemPatches/RemoveExceedingLimitsPatch.cs index 856da0c..6356071 100644 --- a/VT-Api/Patches/VtEvent/ItemPatches/RemoveExceedingLimitsPatch.cs +++ b/VT-Api/Patches/VtEvent/ItemPatches/RemoveExceedingLimitsPatch.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; +using VT_Api.Extension; namespace VT_Api.Patches.VtEvent.ItemPatches { @@ -17,16 +18,14 @@ namespace VT_Api.Patches.VtEvent.ItemPatches class RemoveExceedingLimitsPatch { - [HarmonyPrefix]// TODO And When Player try to pickup Item - private static bool ItemLimitPatch(Inventory inv, BodyArmor armor, bool removeItems = true, bool removeAmmo = true) + [HarmonyPrefix] + private static bool ItemLimitPatch(Inventory inv, BodyArmor armor, bool removeItems = true, bool removeAmmo = true) // TODO fix this { try { - //SynapseController.Server.Logger.Debug("ItemLimitPatch"); var player = inv.GetPlayer(); - //Item if (removeItems) RemovItems(inv, armor, player); diff --git a/VT-Api/Patches/VtEvent/MapPaches/StoppingWarHeadPatch.cs b/VT-Api/Patches/VtEvent/MapPaches/StoppingWarHeadPatch.cs index fb13300..a2a28d5 100644 --- a/VT-Api/Patches/VtEvent/MapPaches/StoppingWarHeadPatch.cs +++ b/VT-Api/Patches/VtEvent/MapPaches/StoppingWarHeadPatch.cs @@ -2,12 +2,14 @@ using HarmonyLib; using Interactables.Interobjects.DoorUtils; using Mirror; +using Subtitles; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; +using Utils.Networking; namespace VT_Api.Patches.VtEvent.MapPaches { @@ -19,37 +21,32 @@ private static bool NukeCancelButon(AlphaWarheadController __instance, GameObjec { try { - if (!__instance.inProgress) + ServerLogs.AddLog(ServerLogs.Modules.Warhead, "Detonation cancelled.", ServerLogs.ServerLogType.GameEvent); + + var flag = __instance.inProgress && __instance.timeToDetonation > 10f && !__instance._isLocked; + + VtController.Get.Events.Map.InvokeWarheadStopEvent(disabler?.GetPlayer(), ref flag); + + if (!flag) return false; - if (disabler != null) - { - bool flag = __instance.timeToDetonation > 10.0 && !__instance._isLocked; - VtController.Get.Events.Map.InvokeWarheadStopEvent(disabler.GetPlayer(), ref flag); - if (!flag) - return false; + if (__instance.timeToDetonation <= 15f && disabler != null) + AchievementHandlerBase.ServerAchieve(disabler.GetComponent().connectionToClient, AchievementName.ThatWasClose); - if (__instance.timeToDetonation <= 15f && disabler != null) - { - AchievementHandlerBase.ServerAchieve(disabler.GetComponent().connectionToClient, AchievementName.ThatWasClose); - } + for (sbyte b = 0; b < __instance.scenarios_resume.Length; b = (sbyte)(b + 1)) + if (__instance.scenarios_resume[b].SumTime() > __instance.timeToDetonation && __instance.scenarios_resume[b].SumTime() < __instance.scenarios_start[AlphaWarheadController._startScenario].SumTime()) + __instance.NetworksyncResumeScenario = b; - for (sbyte b = 0; b < __instance.scenarios_resume.Length; b = (sbyte)(b + 1)) + __instance.NetworktimeToDetonation = ((AlphaWarheadController._resumeScenario < 0) ? __instance.scenarios_start[AlphaWarheadController._startScenario].SumTime() : __instance.scenarios_resume[AlphaWarheadController._resumeScenario].SumTime()) + (float)__instance.cooldown; + __instance.NetworkinProgress = false; + DoorEventOpenerExtension.TriggerAction(DoorEventOpenerExtension.OpenerEventType.WarheadCancel); + if (NetworkServer.active) + { + __instance._autoDetonate = false; + NetworkUtils.SendToAuthenticated(new SubtitleMessage(new SubtitlePart[1] { - if (__instance.scenarios_resume[b].SumTime() > __instance.timeToDetonation - && __instance.scenarios_resume[b].SumTime() < __instance.scenarios_start[AlphaWarheadController._startScenario].SumTime()) - { - __instance.NetworksyncResumeScenario = b; - } - } - - __instance.NetworktimeToDetonation = ((AlphaWarheadController._resumeScenario < 0) ? - __instance.scenarios_start[AlphaWarheadController._startScenario].SumTime() : - __instance.scenarios_resume[AlphaWarheadController._resumeScenario].SumTime()) + __instance.cooldown; - __instance.NetworkinProgress = false; - DoorEventOpenerExtension.TriggerAction(DoorEventOpenerExtension.OpenerEventType.WarheadCancel); - if (NetworkServer.active) - __instance._autoDetonate = false; + new SubtitlePart(SubtitleType.AlphaWarheadCancelled, null) + })); } return false; } diff --git a/VT-Api/Patches/VtEvent/PlayerPatches/SynapseDamagePatch.cs b/VT-Api/Patches/VtEvent/PlayerPatches/SynapseDamagePatch.cs index 06deae7..5f45dbe 100644 --- a/VT-Api/Patches/VtEvent/PlayerPatches/SynapseDamagePatch.cs +++ b/VT-Api/Patches/VtEvent/PlayerPatches/SynapseDamagePatch.cs @@ -19,34 +19,39 @@ class SynapseDamagePatch [HarmonyPrefix] private static bool DamageEventPatch(PlayerEvents __instance, Player victim, Player killer, ref float damage, DamageType type, out bool allow) { + var ev = new PlayerDamageEventArgs + { + Damage = damage, + }; + try { - var ev = new PlayerDamageEventArgs - { - Damage = damage, - }; ev.SetProperty("Killer", killer); ev.SetProperty("Victim", victim); ev.SetProperty("Damage", damage); ev.SetProperty("DamageType", type); __instance.CallEvent("PlayerDamageEvent", ev); - + + allow = ev.Allow; damage = ev.Damage; + } + catch (Exception e) + { + Synapse.Api.Logger.Get.Error($"Synapse-Event: PlayerDamage event failed!!\n{e}"); allow = ev.Allow; - + return false; + } + try + { VtController.Get.Events.Player.InvokePlayerDamagePostEvent(victim, killer, ref damage, type, ref allow); - ev.Damage = damage; - ev.Allow = allow; - return false; } catch (Exception e) { Synapse.Api.Logger.Get.Error($"Vt-Event: PlayerDamagePost failed!!\n{e}\nStackTrace:\n{e.StackTrace}"); - allow = true; - return true; + return false; } } diff --git a/VT-Api/Patches/VtEvent/PlayerPatches/SynapseDeathPatch.cs b/VT-Api/Patches/VtEvent/PlayerPatches/SynapseDeathPatch.cs new file mode 100644 index 0000000..074dfb6 --- /dev/null +++ b/VT-Api/Patches/VtEvent/PlayerPatches/SynapseDeathPatch.cs @@ -0,0 +1,55 @@ +using HarmonyLib; +using Synapse.Api; +using Synapse.Api.Enum; +using Synapse.Api.Events; +using Synapse.Api.Events.SynapseEventArguments; +using Synapse.Api.Items; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VT_Api.Reflexion; + +namespace VT_Api.Patches.VtEvent.PlayerPatches +{ + [HarmonyPatch(typeof(PlayerEvents), "InvokePlayerDeathEvent")] + class SynapseDeathPatch + { + [HarmonyPrefix] + private static bool DeathEventPatch(PlayerEvents __instance, Player victim, Player killer, DamageType type, out bool allow) + { + var ev = new PlayerDeathEventArgs(); + try + { + + ev.Allow = true; + ev.SetProperty("Killer", killer); + ev.SetProperty("Victim", victim); + ev.SetProperty("DamageType", type); + + __instance.CallEvent("PlayerDeathEvent", ev); + + allow = ev.Allow; + } + catch (Exception e) + { + allow = ev.Allow; + Logger.Get.Error($"Synapse-Event: PlayerDeath event failed!!\n{e}"); + return false; + } + try + { + VtController.Get.Events.Player.InvokePlayerDeathPostEvent(victim, killer, type, ref allow); + + return false; + } + catch (Exception e) + { + Synapse.Api.Logger.Get.Error($"Vt-Event: PlayerDamagePost failed!!\n{e}\nStackTrace:\n{e.StackTrace}"); + return true; + } + } + + } +} diff --git a/VT-Api/Patches/VtPatch/CustomDeathReasonPatch.cs b/VT-Api/Patches/VtPatch/CustomDeathReasonPatch.cs new file mode 100644 index 0000000..8e1d8c2 --- /dev/null +++ b/VT-Api/Patches/VtPatch/CustomDeathReasonPatch.cs @@ -0,0 +1,27 @@ +using HarmonyLib; +using Mirror; +using PlayerStatsSystem; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VT_Api.Patches.VtPatch +{ + [HarmonyPatch(typeof(PlayerStats), nameof(PlayerStats.TargetReceiveSpecificDeathReason))] + class CustomDeathReasonPatch + { + public static string CustomReason { get; set; } + + [HarmonyPrefix] + public static void TargetReceiveSpecificDeathReason(PlayerStats __instance, DamageHandlerBase handler) + { + if (CustomReason != null) + { + handler = new CustomReasonDamageHandler(CustomReason); + CustomReason = null; + } + } + } +} diff --git a/VT-Api/Properties/AssemblyInfo.cs b/VT-Api/Properties/AssemblyInfo.cs index db3b3e2..6b67918 100644 --- a/VT-Api/Properties/AssemblyInfo.cs +++ b/VT-Api/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut // en utilisant '*', comme indiqué ci-dessous : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.0.0")] -[assembly: AssemblyFileVersion("1.1.0.0")] +[assembly: AssemblyVersion("1.2.0.0")] +[assembly: AssemblyFileVersion("1.2.0.0")] diff --git a/VT-Api/VT-Api.csproj b/VT-Api/VT-Api.csproj index ec720b2..270f20a 100644 --- a/VT-Api/VT-Api.csproj +++ b/VT-Api/VT-Api.csproj @@ -51,6 +51,7 @@ + @@ -102,11 +103,12 @@ - - - + + + + @@ -116,10 +118,10 @@ - + @@ -142,8 +144,10 @@ + + @@ -153,12 +157,17 @@ + + - + + ..\ref\DissonanceVoip-Publicized.dll + Dissonance + ..\ref\NorthwoodLib-Publicized.dll diff --git a/VT-Api/VtController.cs b/VT-Api/VtController.cs index a014d28..2468f03 100644 --- a/VT-Api/VtController.cs +++ b/VT-Api/VtController.cs @@ -58,10 +58,23 @@ public static void InitApi() VtController.Get.LogMessage(); VtController.Get.AplidePatch(); VtController.Get.InitAll(); + VtController.Get.CheckUpdate(); Logger.Get.Info("Vt-API is now ready!"); } + private void CheckUpdate() + { + if (!Configs.VtConfiguration.AutoUpdate) + return; + + var updater = new Updater(); + var isUpdate = updater.Update(); + + if (isUpdate) + Logger.Get.Warn("The VT-API is update on the last version !"); + } + private void LogMessage() { ServerConsole.AddLog("Vt-API Initialising!", System.ConsoleColor.Yellow); @@ -75,21 +88,21 @@ private void LogMessage() private void InitAll() { + var i = 0; try { - AutoRegister.Init(); - MinGames.Init(); - Events.Init(); - Commands.Init(); - Configs.Init(); - Team.Init(); - Role.Init(); - Item.Init(); - + AutoRegister.Init(); i++; + MinGames.Init(); i++; + Events.Init(); i++; + Commands.Init(); i++; + Configs.Init(); i++; + Team.Init(); i++; + Role.Init(); i++; + Item.Init(); i++; } catch (Exception e) { - throw new VtInitAllHandlerExceptions($"Vt-init: Error while Initialising the handlers!\n Please fix the Issue and restart your Server!\n{e}\nStackTrace:\n{e.StackTrace}", e); + throw new VtInitAllHandlerExceptions($"Vt-init: Error while Initialising the handlers #{i} !\n Please fix the Issue and restart your Server!\n{e}\nStackTrace:\n{e.StackTrace}", e); } } diff --git a/VT-Api/VtVersion.cs b/VT-Api/VtVersion.cs index ea311dd..661e322 100644 --- a/VT-Api/VtVersion.cs +++ b/VT-Api/VtVersion.cs @@ -1,10 +1,12 @@ // copy past of SynapseVersion +using VT_Api.Core.Plugin.Updater; + public static class VtVersion { public const int Major = 1; - public const int Minor = 1; + public const int Minor = 2; public const int Patch = 0; @@ -30,6 +32,9 @@ public static class VtVersion SynapseVersion.Debug; #endif + public static PluginVersion GetVersion() + => new PluginVersion(Major, Minor, Patch); + public static string GetVersionName() { var version = $"{Major}.{Minor}.{Patch}"; diff --git a/ref/DissonanceVoip-Publicized.dll b/ref/DissonanceVoip-Publicized.dll new file mode 100644 index 0000000..be48484 Binary files /dev/null and b/ref/DissonanceVoip-Publicized.dll differ