Skip to content

Commit

Permalink
Merge pull request #243 from project-fika/game-start-rework
Browse files Browse the repository at this point in the history
Game start rework
  • Loading branch information
Lacyway authored Dec 18, 2024
2 parents afe616a + a8dd1d2 commit 7f46bd0
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 113 deletions.
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

0 comments on commit 7f46bd0

Please sign in to comment.