From 3c897de8e6f500d4f6146ba9051d696a08270da1 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 14 Oct 2024 15:15:14 -0300 Subject: [PATCH 1/3] Boop * Fixing duplicated player id. * Created a new method of spawning a NPC * Added LateDestroy and DestroyAll --- EXILED/Exiled.API/Features/Npc.cs | 102 +++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.API/Features/Npc.cs b/EXILED/Exiled.API/Features/Npc.cs index 82a6c73745..e90aee33dd 100644 --- a/EXILED/Exiled.API/Features/Npc.cs +++ b/EXILED/Exiled.API/Features/Npc.cs @@ -16,7 +16,6 @@ namespace Exiled.API.Features using CentralAuth; using CommandSystem; using Exiled.API.Enums; - using Exiled.API.Extensions; using Exiled.API.Features.Components; using Exiled.API.Features.Roles; using Footprinting; @@ -142,6 +141,7 @@ public override Vector3 Position /// The userID of the NPC. /// The position to spawn the NPC. /// The spawned. + [Obsolete("This metod is marked as obsolet due to a bug that make player have the same id. Use Npc.Spawn(string) instead")] public static Npc Spawn(string name, RoleTypeId role, int id = 0, string userId = PlayerAuthenticationManager.DedicatedId, Vector3? position = null) { GameObject newObject = UnityEngine.Object.Instantiate(Mirror.NetworkManager.singleton.playerPrefab); @@ -208,18 +208,114 @@ public static Npc Spawn(string name, RoleTypeId role, int id = 0, string userId return npc; } + /// + /// Spawns an NPC based on the given parameters. + /// + /// The name of the NPC. + /// The RoleTypeId of the NPC, defaulting to None. + /// Whether the NPC should be ignored by round ending checks. + /// The userID of the NPC for authentication. Defaults to the Dedicated ID. + /// The position where the NPC should spawn. If null, the default spawn location is used. + /// The spawned. + public static Npc Spawn(string name, RoleTypeId role = RoleTypeId.None, bool ignored = false, string userId = PlayerAuthenticationManager.DedicatedId, Vector3? position = null) + { + GameObject newObject = UnityEngine.Object.Instantiate(Mirror.NetworkManager.singleton.playerPrefab); + + Npc npc = new(newObject) + { + IsNPC = true, + }; + + FakeConnection fakeConnection = new(npc.Id); + + try + { + if (userId == PlayerAuthenticationManager.DedicatedId) + { + npc.ReferenceHub.authManager.SyncedUserId = userId; + try + { + npc.ReferenceHub.authManager.InstanceMode = ClientInstanceMode.DedicatedServer; + } + catch (Exception e) + { + Log.Debug($"Ignore: {e.Message}"); + } + } + else + { + npc.ReferenceHub.authManager.InstanceMode = ClientInstanceMode.Unverified; + npc.ReferenceHub.authManager._privUserId = userId == string.Empty ? $"Dummy-{npc.Id}@localhost" : userId; + } + } + catch (Exception e) + { + Log.Debug($"Ignore: {e.Message}"); + } + + try + { + npc.ReferenceHub.roleManager.InitializeNewRole(RoleTypeId.None, RoleChangeReason.None); + } + catch (Exception e) + { + Log.Debug($"Ignore: {e.Message}"); + } + + NetworkServer.AddPlayerForConnection(fakeConnection, newObject); + + npc.ReferenceHub.nicknameSync.Network_myNickSync = name; + Dictionary.Add(newObject, npc); + + Timing.CallDelayed(0.5f, () => + { + npc.Role.Set(role, SpawnReason.RoundStart, position is null ? RoleSpawnFlags.All : RoleSpawnFlags.AssignInventory); + + if (position is not null) + npc.Position = position.Value; + }); + + if (ignored) + Round.IgnoredPlayers.Add(npc.ReferenceHub); + + return npc; + } + + /// + /// Destroys all NPCs currently spawned. + /// + public static void DestroyAll() + { + foreach (Npc npc in List) + npc.Destroy(); + } + /// /// Destroys the NPC. /// public void Destroy() { + Round.IgnoredPlayers.Remove(ReferenceHub); NetworkConnectionToClient conn = ReferenceHub.connectionToClient; - if (ReferenceHub._playerId.Value <= RecyclablePlayerId._autoIncrement) - ReferenceHub._playerId.Destroy(); ReferenceHub.OnDestroy(); CustomNetworkManager.TypedSingleton.OnServerDisconnect(conn); Dictionary.Remove(GameObject); Object.Destroy(GameObject); } + + /// + /// Schedules the destruction of the NPC after a delay. + /// + /// The delay in seconds before the NPC is destroyed. + public void LateDestroy(float time) + { + Timing.CallDelayed(time, () => + { + if (this == null) + return; + + Destroy(); + }); + } } } From 580af847abbf721c4a7b7f0a268137294eb5a479 Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 14 Oct 2024 18:29:23 -0300 Subject: [PATCH 2/3] Update Npc.cs * Try Catch on destroying ncp --- EXILED/Exiled.API/Features/Npc.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/EXILED/Exiled.API/Features/Npc.cs b/EXILED/Exiled.API/Features/Npc.cs index e90aee33dd..97c4fb1dd2 100644 --- a/EXILED/Exiled.API/Features/Npc.cs +++ b/EXILED/Exiled.API/Features/Npc.cs @@ -295,12 +295,19 @@ public static void DestroyAll() /// public void Destroy() { - Round.IgnoredPlayers.Remove(ReferenceHub); - NetworkConnectionToClient conn = ReferenceHub.connectionToClient; - ReferenceHub.OnDestroy(); - CustomNetworkManager.TypedSingleton.OnServerDisconnect(conn); - Dictionary.Remove(GameObject); - Object.Destroy(GameObject); + try + { + Round.IgnoredPlayers.Remove(ReferenceHub); + NetworkConnectionToClient conn = ReferenceHub.connectionToClient; + ReferenceHub.OnDestroy(); + CustomNetworkManager.TypedSingleton.OnServerDisconnect(conn); + Dictionary.Remove(GameObject); + Object.Destroy(GameObject); + } + catch (Exception e) + { + Log.Error($"Error while destroying a NPC: {e.Message}"); + } } /// From 1ea3e2a7af93bf9fdc8b5adcff2370f2ba9dd7ee Mon Sep 17 00:00:00 2001 From: SrLicht Date: Mon, 14 Oct 2024 18:32:55 -0300 Subject: [PATCH 3/3] Update Npc.cs --- EXILED/Exiled.API/Features/Npc.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/EXILED/Exiled.API/Features/Npc.cs b/EXILED/Exiled.API/Features/Npc.cs index 97c4fb1dd2..e79038065c 100644 --- a/EXILED/Exiled.API/Features/Npc.cs +++ b/EXILED/Exiled.API/Features/Npc.cs @@ -318,10 +318,7 @@ public void LateDestroy(float time) { Timing.CallDelayed(time, () => { - if (this == null) - return; - - Destroy(); + this?.Destroy(); }); } }