Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Game start rework #243

Merged
merged 11 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 87 additions & 79 deletions Fika.Core/Coop/GameMode/CoopGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public sealed class CoopGame : BaseLocalGame<EftGamePlayerOwner>, IBotGame, IFik
public bool HasReceivedLoot { get; set; } = false;
public List<ThrowWeapItemClass> ThrownGrenades;
public bool WeatherReady;
public bool RaidStarted { get; set; }

private readonly Dictionary<int, int> botQueue = [];
private Coroutine extractRoutine;
Expand Down Expand Up @@ -578,9 +579,9 @@ public override IEnumerator vmethod_2()
server.GameStartTime = startTime;
sessionTime = GameTimer.SessionTime;

InformationPacket packet = new(false)
InformationPacket packet = new()
{
NumberOfPlayers = server.NetServer.ConnectedPeersCount,
RaidStarted = RaidStarted,
ReadyPlayers = server.ReadyClients,
HostReady = true,
GameTime = gameTime.Value,
Expand Down Expand Up @@ -684,9 +685,9 @@ private async Task WaitForOtherPlayers()
SetMatchmakerStatus(LocaleUtils.UI_WAIT_FOR_OTHER_PLAYERS.Localized(), (float)server.ReadyClients / expectedPlayers);
} while (coopHandler.AmountOfHumans < expectedPlayers);

InformationPacket packet = new(false)
InformationPacket packet = new()
{
NumberOfPlayers = server.NetServer.ConnectedPeersCount,
RaidStarted = RaidStarted,
ReadyPlayers = server.ReadyClients
};

Expand All @@ -712,9 +713,9 @@ private async Task WaitForOtherPlayers()
DynamicAI.AddHumans();
}

InformationPacket finalPacket = new(false)
InformationPacket finalPacket = new()
{
NumberOfPlayers = server.NetServer.ConnectedPeersCount,
RaidStarted = RaidStarted,
ReadyPlayers = server.ReadyClients
};

Expand All @@ -733,7 +734,7 @@ private async Task WaitForOtherPlayers()
} while (coopHandler.AmountOfHumans < expectedPlayers);


InformationPacket packet = new(true)
InformationPacket packet = new()
{
ReadyPlayers = 1
};
Expand Down Expand Up @@ -928,6 +929,51 @@ public override async Task<LocalPlayer> vmethod_3(GameWorld gameWorld, int playe
return coopPlayer;
}

/// <summary>
/// This creates a "custom" Back button so that we can back out if we get stuck
/// </summary>
/// <param name="myPlayer"></param>
/// <param name="coopPlayer"></param>
/// <param name="customButton"></param>
/// <returns></returns>
private GameObject CreateStartButton()
{
if (MenuUI.Instantiated)
{
MenuUI menuUI = MenuUI.Instance;
DefaultUIButton backButton = Traverse.Create(menuUI.MatchmakerTimeHasCome).Field<DefaultUIButton>("_cancelButton").Value;
GameObject customButton = Instantiate(backButton.gameObject, backButton.gameObject.transform.parent);
customButton.gameObject.name = "FikaStartButton";
//customButton.gameObject.transform.position = new(customButton.transform.position.x, customButton.transform.position.y - 20, customButton.transform.position.z);
customButton.gameObject.SetActive(true);
DefaultUIButton backButtonComponent = customButton.GetComponent<DefaultUIButton>();
backButtonComponent.SetHeaderText(LocaleUtils.UI_START_RAID.Localized(), 32);
backButtonComponent.SetEnabledTooltip(LocaleUtils.UI_START_RAID_DESCRIPTION.Localized());
UnityEngine.Events.UnityEvent newEvent = new();
newEvent.AddListener(() =>
{
if (isServer)
{
RaidStarted = true;
FikaBackendUtils.HostExpectedNumberOfPlayers = Singleton<FikaServer>.Instance.NetServer.ConnectedPeersCount;
return;
}

FikaClient fikaClient = Singleton<FikaClient>.Instance ?? throw new NullReferenceException("CreateStartButton::FikaClient was null!");
InformationPacket packet = new()
{
RequestStart = true
};
fikaClient.SendData(ref packet, DeliveryMethod.ReliableOrdered);
});
Traverse.Create(backButtonComponent).Field("OnClick").SetValue(newEvent);

return customButton;
}

return null;
}

/// <summary>
/// This creates a "custom" Back button so that we can back out if we get stuck
/// </summary>
Expand Down Expand Up @@ -1101,7 +1147,7 @@ public async Task InitPlayer(BotControllerSettings botsSettings, string backendU
}
}

await WaitForPlayersToConnect();
await WaitForHostToStart();

LocationSettingsClass.Location location = localRaidSettings_0.selectedLocation;
if (isServer)
Expand Down Expand Up @@ -1163,7 +1209,7 @@ private async Task WaitForHostToLoad()
{
FikaClient client = Singleton<FikaClient>.Instance;

InformationPacket packet = new(true);
InformationPacket packet = new();
do
{
SetMatchmakerStatus(LocaleUtils.UI_WAIT_FOR_HOST_INIT.Localized());
Expand Down Expand Up @@ -1338,88 +1384,53 @@ private async Task InitInteractables()


/// <summary>
/// <see cref="Task"/> used to wait for all other players to join the game
/// <see cref="Task"/> used to wait for host to start the raid
/// </summary>
/// <returns></returns>
private async Task WaitForPlayersToConnect()
private async Task WaitForHostToStart()
{
Logger.LogInfo("Starting task to wait for other players.");

SetMatchmakerStatus(LocaleUtils.UI_INIT_COOP_GAME.Localized());
int numbersOfPlayersToWaitFor = 0;
Logger.LogInfo("Starting task to wait for host to start the raid.");

string localizedPlayer = LocaleUtils.UI_WAIT_FOR_PLAYER.Localized();
string localizedPlayers = LocaleUtils.UI_WAIT_FOR_PLAYERS.Localized();
SetMatchmakerStatus("Waiting for host to start the raid...");

GameObject startButton = null;
if (isServer)
{
startButton = CreateStartButton() ?? throw new NullReferenceException("Start button could not be created!");
FikaServer server = Singleton<FikaServer>.Instance;
server.RaidInitialized = true;

do
while (!RaidStarted)
{
numbersOfPlayersToWaitFor = FikaBackendUtils.HostExpectedNumberOfPlayers - (server.NetServer.ConnectedPeersCount + 1);
if (numbersOfPlayersToWaitFor > 0)
{
bool multiple = numbersOfPlayersToWaitFor > 1;
SetMatchmakerStatus(string.Format(multiple ? localizedPlayers : localizedPlayer,
numbersOfPlayersToWaitFor));
}
else
{
SetMatchmakerStatus(LocaleUtils.UI_ALL_PLAYERS_JOINED.Localized());
}
await Task.Delay(100);
} while (numbersOfPlayersToWaitFor > 0);
}
else
{
FikaClient client = Singleton<FikaClient>.Instance;

while (client.NetClient == null)
{
await Task.Delay(500);
await Task.Yield();
}

int connectionAttempts = 0;

while (client.ServerConnection == null && connectionAttempts < 5)
if (startButton != null)
{
// Server retries 10 times with a 500ms interval, we give it 5 seconds to try
SetMatchmakerStatus(LocaleUtils.UI_WAITING_FOR_CONNECT.Localized());
connectionAttempts++;
await Task.Delay(1000);

if (client.ServerConnection == null && connectionAttempts == 5)
{
Singleton<PreloaderUI>.Instance.ShowErrorScreen(LocaleUtils.UI_ERROR_CONNECTING.Localized(),
LocaleUtils.UI_ERROR_CONNECTING_TO_RAID.Localized());
}
Destroy(startButton);
}

while (client == null)
{
await Task.Delay(500);
}
SetStatusModel status = new(FikaBackendUtils.GroupId, LobbyEntry.ELobbyStatus.IN_GAME);
await FikaRequestHandler.UpdateSetStatus(status);
return;
}

InformationPacket packet = new(true);
if (FikaBackendUtils.IsDedicatedRequester)
{
startButton = CreateStartButton() ?? throw new NullReferenceException("Start button could not be created!");
}
FikaClient client = Singleton<FikaClient>.Instance;
InformationPacket packet = new();
client.SendData(ref packet, DeliveryMethod.ReliableUnordered);
while (!RaidStarted)
{
await Task.Delay(250);
client.SendData(ref packet, DeliveryMethod.ReliableUnordered);
do
{
numbersOfPlayersToWaitFor = FikaBackendUtils.HostExpectedNumberOfPlayers - (client.ConnectedClients + 1);
if (numbersOfPlayersToWaitFor > 0)
{
bool multiple = numbersOfPlayersToWaitFor > 1;
SetMatchmakerStatus(string.Format(multiple ? localizedPlayers : localizedPlayer,
numbersOfPlayersToWaitFor));
}
else
{
SetMatchmakerStatus(LocaleUtils.UI_ALL_PLAYERS_JOINED.Localized());
}
client.SendData(ref packet, DeliveryMethod.ReliableUnordered);
await Task.Delay(1000);
} while (numbersOfPlayersToWaitFor > 0);
}

if (startButton != null)
{
Destroy(startButton);
}
}

Expand Down Expand Up @@ -1545,11 +1556,7 @@ public override async Task vmethod_1(BotControllerSettings controllerSettings, I
botsController_0.EventsController.SpawnAction();

FikaPlugin.DynamicAI.SettingChanged += DynamicAI_SettingChanged;
FikaPlugin.DynamicAIRate.SettingChanged += DynamicAIRate_SettingChanged;

SetStatusModel status = new(FikaBackendUtils.GroupId, LobbyEntry.ELobbyStatus.IN_GAME);

await FikaRequestHandler.UpdateSetStatus(status);
FikaPlugin.DynamicAIRate.SettingChanged += DynamicAIRate_SettingChanged;
}

// Add FreeCamController to GameWorld GameObject
Expand Down Expand Up @@ -2454,11 +2461,12 @@ private void CleanUpFikaBackendUtils()
{
FikaBackendUtils.HostExpectedNumberOfPlayers = 1;
FikaBackendUtils.IsSpectator = false;
FikaBackendUtils.IsDedicatedRequester = false;
}

FikaBackendUtils.RequestFikaWorld = false;
FikaBackendUtils.IsReconnect = false;
FikaBackendUtils.ReconnectPosition = Vector3.zero;
FikaBackendUtils.ReconnectPosition = Vector3.zero;
}

private class ExitManager : Class1491
Expand Down
9 changes: 5 additions & 4 deletions Fika.Core/Coop/Utils/FikaBackendUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ public static class FikaBackendUtils
public static string PMCName { get; internal set; }
public static EMatchmakerType MatchingType { get; internal set; } = EMatchmakerType.Single;
public static bool IsDedicated = false;
public static bool IsReconnect { get; internal set; } = false;
public static bool IsReconnect { get; internal set; }
public static bool IsDedicatedGame { get; set; } = false;
public static bool IsTransit { get; internal set; } = false;
public static bool IsSpectator { get; internal set; } = false;
public static bool IsHostNatPunch { get; internal set; } = false;
public static bool IsDedicatedRequester { get; set; }
public static bool IsTransit { get; internal set; }
public static bool IsSpectator { get; internal set; }
public static bool IsHostNatPunch { get; internal set; }
public static int HostExpectedNumberOfPlayers { get; set; } = 1;
public static string RemoteIp { get; internal set; }
public static int RemotePort { get; internal set; }
Expand Down
24 changes: 11 additions & 13 deletions Fika.Core/Networking/FikaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@
using Fika.Core.Coop.Utils;
using Fika.Core.Modding;
using Fika.Core.Modding.Events;
using Fika.Core.Networking.Packets;
using Fika.Core.Utils;
using FlyingWormConsole3;
using HarmonyLib;
using LiteNetLib;
using LiteNetLib.Utils;
Expand All @@ -46,7 +44,6 @@ public class FikaClient : MonoBehaviour, INetEventListener, IFikaNetworkManager
public CoopPlayer MyPlayer;
public int Ping = 0;
public int ServerFPS = 0;
public int ConnectedClients = 0;
public int ReadyClients = 0;
public bool HostReady = false;
public bool HostLoaded = false;
Expand Down Expand Up @@ -1060,18 +1057,19 @@ private void OnHealthSyncPacketReceived(HealthSyncPacket packet)

private void OnInformationPacketReceived(InformationPacket packet)
{
if (!packet.IsRequest)
CoopGame coopGame = CoopHandler.LocalGameInstance;
if (coopGame != null)
{
ConnectedClients = packet.NumberOfPlayers;
ReadyClients = packet.ReadyPlayers;
HostReady = packet.HostReady;
HostLoaded = packet.HostLoaded;
coopGame.RaidStarted = packet.RaidStarted;
FikaBackendUtils.HostExpectedNumberOfPlayers = packet.ReadyPlayers;
}
ReadyClients = packet.ReadyPlayers;
HostReady = packet.HostReady;
HostLoaded = packet.HostLoaded;

if (packet.HostReady)
{
CoopGame coopGame = (CoopGame)Singleton<IFikaGame>.Instance;
coopGame.SetClientTime(packet.GameTime, packet.SessionTime);
}
if (packet.HostReady)
{
coopGame.SetClientTime(packet.GameTime, packet.SessionTime);
}
}

Expand Down
12 changes: 9 additions & 3 deletions Fika.Core/Networking/FikaServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -985,16 +985,22 @@ private void OnInformationPacketReceived(InformationPacket packet, NetPeer peer)
{
ReadyClients += packet.ReadyPlayers;

bool hostReady = coopHandler != null && coopHandler.LocalGameInstance != null && coopHandler.LocalGameInstance.Status == GameStatus.Started;
bool gameExists = coopHandler != null && coopHandler.LocalGameInstance != null;
bool hostReady = gameExists && coopHandler.LocalGameInstance.Status == GameStatus.Started;

InformationPacket respondPackage = new(false)
InformationPacket respondPackage = new()
{
NumberOfPlayers = netServer.ConnectedPeersCount,
RaidStarted = gameExists && coopHandler.LocalGameInstance.RaidStarted,
ReadyPlayers = ReadyClients,
HostReady = hostReady,
HostLoaded = RaidInitialized
};

if (gameExists && packet.RequestStart)
{
coopHandler.LocalGameInstance.RaidStarted = true;
}

if (hostReady)
{
respondPackage.GameTime = gameStartTime.Value;
Expand Down
20 changes: 10 additions & 10 deletions Fika.Core/Networking/Packets/Backend/InformationPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

namespace Fika.Core.Networking
{
public struct InformationPacket(bool isRequest) : INetSerializable
public struct InformationPacket : INetSerializable
{
public bool IsRequest = isRequest;
public int NumberOfPlayers = 0;
public int ReadyPlayers = 0;
public bool HostReady = false;
public bool HostLoaded = false;
public bool RaidStarted;
public bool RequestStart;
public int ReadyPlayers;
public bool HostReady;
public bool HostLoaded;
public DateTime GameTime;
public TimeSpan SessionTime;

public void Deserialize(NetDataReader reader)
{
IsRequest = reader.GetBool();
NumberOfPlayers = reader.GetInt();
RaidStarted = reader.GetBool();
RequestStart = reader.GetBool();
ReadyPlayers = reader.GetInt();
HostReady = reader.GetBool();
if (HostReady)
Expand All @@ -31,8 +31,8 @@ public void Deserialize(NetDataReader reader)

public void Serialize(NetDataWriter writer)
{
writer.Put(IsRequest);
writer.Put(NumberOfPlayers);
writer.Put(RaidStarted);
writer.Put(RequestStart);
writer.Put(ReadyPlayers);
writer.Put(HostReady);
if (HostReady)
Expand Down
Loading
Loading