diff --git a/vMenu/CommonFunctions.cs b/vMenu/CommonFunctions.cs
index ff3960f5..4c210a27 100644
--- a/vMenu/CommonFunctions.cs
+++ b/vMenu/CommonFunctions.cs
@@ -389,27 +389,63 @@ public static async void QuitGame()
///
///
///
- public static async void TeleportToPlayer(int playerId, bool inVehicle = false)
+ public static async Task TeleportToPlayer(IPlayer player, bool inVehicle = false)
{
// If the player exists.
- if (NetworkIsPlayerActive(playerId))
+ if (player.IsActive || player is InfinityPlayer)
{
- int playerPed = GetPlayerPed(playerId);
- if (Game.PlayerPed.Handle == playerPed)
+ Vector3 playerPos;
+ bool wasActive = true;
+
+ if (player.IsActive)
{
- Notify.Error("Sorry, you can ~r~~h~not~h~ ~s~teleport to yourself!");
- return;
- }
+ Ped playerPedObj = player.Character;
+ if (Game.PlayerPed == playerPedObj)
+ {
+ Notify.Error("Sorry, you can ~r~~h~not~h~ ~s~teleport to yourself!");
+ return;
+ }
- // Get the coords of the other player.
- Vector3 playerPos = GetEntityCoords(playerPed, true);
+ // Get the coords of the other player.
+ playerPos = GetEntityCoords(playerPedObj.Handle, true);
+ }
+ else
+ {
+ playerPos = await MainMenu.RequestPlayerCoordinates(player.ServerId);
+ wasActive = false;
+ }
// Then await the proper loading/teleporting.
await TeleportToCoords(playerPos);
+ // Wait until the player has been created.
+ while (player.Character == null)
+ {
+ await Delay(0);
+ }
+
+ var playerId = player.Handle;
+ var playerPed = player.Character.Handle;
+
// If the player should be teleported inside the other player's vehcile.
if (inVehicle)
{
+ // Wait until the target player vehicle has loaded, if they weren't active beforehand.
+ if (!wasActive)
+ {
+ var startWait = GetGameTimer();
+
+ while (!IsPedInAnyVehicle(playerPed, false))
+ {
+ await Delay(0);
+
+ if ((GetGameTimer() - startWait) > 1500)
+ {
+ break;
+ }
+ }
+ }
+
// Is the other player inside a vehicle?
if (IsPedInAnyVehicle(playerPed, false))
{
@@ -690,7 +726,7 @@ public static async void TeleportToWp()
///
///
///
- public static async void KickPlayer(Player player, bool askUserForReason, string providedReason = "You have been kicked.")
+ public static async void KickPlayer(IPlayer player, bool askUserForReason, string providedReason = "You have been kicked.")
{
if (player != null)
{
@@ -728,7 +764,7 @@ public static async void KickPlayer(Player player, bool askUserForReason, string
///
/// Player to ban.
/// Ban forever or ban temporarily.
- public static async void BanPlayer(Player player, bool forever)
+ public static async void BanPlayer(IPlayer player, bool forever)
{
string banReason = await GetUserInput(windowTitle: "Enter Ban Reason", defaultText: "Banned by staff.", maxInputLength: 200);
if (!string.IsNullOrEmpty(banReason) && banReason.Length > 1)
@@ -786,7 +822,7 @@ public static async void BanPlayer(Player player, bool forever)
/// Kill player
///
///
- public static void KillPlayer(Player player) => TriggerServerEvent("vMenu:KillPlayer", player.ServerId);
+ public static void KillPlayer(IPlayer player) => TriggerServerEvent("vMenu:KillPlayer", player.ServerId);
///
/// Kill yourself.
@@ -901,12 +937,12 @@ public static async void CommitSuicide()
/// Summon player.
///
///
- public static void SummonPlayer(Player player) => TriggerServerEvent("vMenu:SummonPlayer", player.ServerId);
+ public static void SummonPlayer(IPlayer player) => TriggerServerEvent("vMenu:SummonPlayer", player.ServerId);
#endregion
#region Spectate function
private static int currentlySpectatingPlayer = -1;
- public static async void SpectatePlayer(Player player, bool forceDisable = false)
+ public static async void SpectatePlayer(IPlayer player, bool forceDisable = false)
{
if (forceDisable)
{
@@ -914,6 +950,11 @@ public static async void SpectatePlayer(Player player, bool forceDisable = false
}
else
{
+ if (!player.IsActive)
+ {
+ await TeleportToPlayer(player);
+ }
+
if (player.Handle == Game.Player.Handle)
{
if (NetworkIsInSpectatorMode())
@@ -934,12 +975,17 @@ public static async void SpectatePlayer(Player player, bool forceDisable = false
{
if (NetworkIsInSpectatorMode())
{
- if (currentlySpectatingPlayer != player.Handle)
+ if (currentlySpectatingPlayer != player.Handle && player.Character != null)
{
DoScreenFadeOut(500);
while (IsScreenFadingOut()) await Delay(0);
- NetworkSetInSpectatorMode(false, 0);
- NetworkSetInSpectatorMode(true, player.Character.Handle);
+
+ if (player.Character != null)
+ {
+ NetworkSetInSpectatorMode(false, 0);
+ NetworkSetInSpectatorMode(true, player.Character.Handle);
+ }
+
DoScreenFadeIn(500);
Notify.Success($"You are now spectating ~g~{GetSafePlayerName(player.Name)}~s~.", false, true);
currentlySpectatingPlayer = player.Handle;
@@ -956,13 +1002,21 @@ public static async void SpectatePlayer(Player player, bool forceDisable = false
}
else
{
- DoScreenFadeOut(500);
- while (IsScreenFadingOut()) await Delay(0);
- NetworkSetInSpectatorMode(false, 0);
- NetworkSetInSpectatorMode(true, player.Character.Handle);
- DoScreenFadeIn(500);
- Notify.Success($"You are now spectating ~g~{GetSafePlayerName(player.Name)}~s~.", false, true);
- currentlySpectatingPlayer = player.Handle;
+ if (player.Character != null)
+ {
+ DoScreenFadeOut(500);
+ while (IsScreenFadingOut()) await Delay(0);
+
+ if (player.Character != null)
+ {
+ NetworkSetInSpectatorMode(false, 0);
+ NetworkSetInSpectatorMode(true, player.Character.Handle);
+ }
+
+ DoScreenFadeIn(500);
+ Notify.Success($"You are now spectating ~g~{GetSafePlayerName(player.Name)}~s~.", false, true);
+ currentlySpectatingPlayer = player.Handle;
+ }
}
}
}
diff --git a/vMenu/EventManager.cs b/vMenu/EventManager.cs
index 6c83ebd0..24e15fed 100644
--- a/vMenu/EventManager.cs
+++ b/vMenu/EventManager.cs
@@ -289,9 +289,18 @@ private void KillMe(string sourceName)
/// Teleport to the specified player.
///
///
- private void SummonPlayer(string targetPlayer)
+ private async void SummonPlayer(string targetPlayer)
{
- TeleportToPlayer(GetPlayerFromServerId(int.Parse(targetPlayer)));
+ // ensure the player list is requested in case of Infinity
+ MainMenu.PlayersList.RequestPlayerList();
+ await MainMenu.PlayersList.WaitRequested();
+
+ var player = MainMenu.PlayersList.FirstOrDefault(a => a.ServerId == int.Parse(targetPlayer));
+
+ if (player != null)
+ {
+ _ = TeleportToPlayer(player);
+ }
}
///
diff --git a/vMenu/FunctionsController.cs b/vMenu/FunctionsController.cs
index de8e0349..fb91ae84 100644
--- a/vMenu/FunctionsController.cs
+++ b/vMenu/FunctionsController.cs
@@ -24,7 +24,6 @@ class FunctionsController : BaseScript
{
private int LastVehicle = 0;
private bool SwitchedVehicle = false;
- private Dictionary playerList = new Dictionary();
private List deadPlayers = new List();
private float cameraRotationHeading = 0f;
@@ -68,12 +67,6 @@ class FunctionsController : BaseScript
///
public FunctionsController()
{
- // Load the initial playerlist.
- foreach (Player p in Players)
- {
- playerList.Add(p.Handle, p.Name);
- }
-
// Add all tick functions.
Tick += GcTick;
Tick += GeneralTasks;
@@ -90,7 +83,6 @@ public FunctionsController()
Tick += MiscSettings;
Tick += MiscRecordingKeybinds;
Tick += DeathNotifications;
- Tick += JoinQuitNotifications;
Tick += UpdateLocation;
Tick += ManageCamera;
Tick += PlayerBlipsControl;
@@ -1118,51 +1110,27 @@ private async Task MiscRecordingKeybinds()
}
}
}
- #region Join / Quit notifications
+ #region Join / Quit notifications (via events)
///
/// Runs join/quit notification checks.
///
///
- private async Task JoinQuitNotifications()
+ [EventHandler("vMenu:PlayerJoinQuit")]
+ private void OnJoinQuitNotification(string playerName, string dropReason)
{
if (MainMenu.PermissionsSetupComplete && MainMenu.MiscSettingsMenu != null)
{
// Join/Quit notifications
if (MainMenu.MiscSettingsMenu.JoinQuitNotifications && IsAllowed(Permission.MSJoinQuitNotifs))
{
- PlayerList plist = Players;
- Dictionary pl = new Dictionary();
- foreach (Player p in plist)
+ if (dropReason == null)
{
- pl.Add(p.Handle, p.Name);
- }
- await Delay(0);
- // new player joined.
- if (pl.Count > playerList.Count)
- {
- foreach (KeyValuePair player in pl)
- {
- if (!playerList.Contains(player))
- {
- Notify.Custom($"~g~{GetSafePlayerName(player.Value)}~s~ joined the server.");
- await Delay(0);
- }
- }
+ Notify.Custom($"~g~{GetSafePlayerName(playerName)}~s~ joined the server.");
}
- // player left.
- else if (pl.Count < playerList.Count)
+ else
{
- foreach (KeyValuePair player in playerList)
- {
- if (!pl.Contains(player))
- {
- Notify.Custom($"~r~{GetSafePlayerName(player.Value)}~s~ left the server.");
- await Delay(0);
- }
- }
+ Notify.Custom($"~r~{GetSafePlayerName(playerName)}~s~ left the server. ~c~({GetSafePlayerName(dropReason)})");
}
- playerList = pl;
- await Delay(100);
}
}
}
@@ -2175,7 +2143,7 @@ private async Task PlayerBlipsControl()
{
bool enabled = MainMenu.MiscSettingsMenu.ShowPlayerBlips && IsAllowed(Permission.MSPlayerBlips);
- foreach (Player p in MainMenu.PlayersList)
+ foreach (IPlayer p in MainMenu.PlayersList)
{
// continue only if this player is valid.
if (p != null && NetworkIsPlayerActive(p.Handle) && p.Character != null && p.Character.Exists())
@@ -2188,7 +2156,7 @@ private async Task PlayerBlipsControl()
// if blips are enabled and the player has permisisons to use them.
if (enabled)
{
- if (p != Game.Player)
+ if (!p.IsLocal)
{
int ped = p.Character.Handle;
int blip = GetBlipFromEntity(ped);
diff --git a/vMenu/MainMenu.cs b/vMenu/MainMenu.cs
index a85b6661..c90e91c5 100644
--- a/vMenu/MainMenu.cs
+++ b/vMenu/MainMenu.cs
@@ -48,7 +48,7 @@ public class MainMenu : BaseScript
public static VoiceChat VoiceChatSettingsMenu { get; private set; }
public static About AboutMenu { get; private set; }
public static bool NoClipEnabled { get { return NoClip.IsNoclipActive(); } set { NoClip.SetNoclipActive(value); } }
- public static PlayerList PlayersList;
+ public static IPlayerList PlayersList;
public static bool DebugMode = GetResourceMetadata(GetCurrentResourceName(), "client_debug_mode", 0) == "true" ? true : false;
public static bool EnableExperimentalFeatures = (GetResourceMetadata(GetCurrentResourceName(), "experimental_features_enabled", 0) ?? "0") == "1";
@@ -65,7 +65,7 @@ public class MainMenu : BaseScript
///
public MainMenu()
{
- PlayersList = Players;
+ PlayersList = new NativePlayerList(Players);
#region cleanup unused kvps
int tmp_kvp_handle = StartFindKvp("");
@@ -297,6 +297,52 @@ public MainMenu()
}
}
+ #region Infinity bits
+ [EventHandler("vMenu:SetServerState")]
+ public void SetServerState(IDictionary data)
+ {
+ if (data.TryGetValue("IsInfinity", out var isInfinity))
+ {
+ if (isInfinity is bool isInfinityBool)
+ {
+ if (isInfinityBool)
+ {
+ PlayersList = new InfinityPlayerList(Players);
+ }
+ }
+ }
+ }
+
+ [EventHandler("vMenu:ReceivePlayerList")]
+ public void ReceivedPlayerList(IList