Skip to content

Commit 38d20b0

Browse files
authored
Merge pull request #308 from project-fika/dev-3.11
3.11
2 parents 43c6f10 + d2cc0d6 commit 38d20b0

File tree

239 files changed

+7540
-4740
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

239 files changed

+7540
-4740
lines changed
-155 KB
Binary file not shown.
377 KB
Binary file not shown.
-375 KB
Binary file not shown.

Fika.Core/Bundles/Files/ping.bundle

-157 KB
Binary file not shown.
-261 KB
Binary file not shown.
-305 KB
Binary file not shown.
Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// © 2025 Lacyway All Rights Reserved
22

3+
using System;
34
using System.Collections.Generic;
45
using System.IO;
56
using System.Linq;
@@ -12,42 +13,105 @@ namespace Fika.Core.Bundles
1213
/// Created by Nexus / pandahhcorp <br/>
1314
/// Refactored by Lacyway to load bundles directly from memory
1415
/// </summary>
15-
public class InternalBundleLoader
16+
internal class InternalBundleLoader
1617
{
17-
public Dictionary<string, AssetBundleCreateRequest> _loadedBundles;
1818
public static InternalBundleLoader Instance { get; private set; }
1919

20-
public void Create()
21-
{
22-
Instance = this;
23-
Awake();
24-
}
20+
private AssetBundle masterBundle;
2521

26-
private void Awake()
22+
public InternalBundleLoader()
2723
{
2824
Assembly assembly = Assembly.GetExecutingAssembly();
29-
_loadedBundles = [];
30-
3125
assembly.GetManifestResourceNames().ToList().ForEach(name =>
3226
{
3327
using Stream stream = assembly.GetManifestResourceStream(name);
3428
using MemoryStream memoryStream = new();
3529
{
3630
string bundlename = name.Replace("Fika.Core.Bundles.Files.", "").Replace(".bundle", "");
37-
stream.CopyTo(memoryStream);
38-
_loadedBundles.Add(bundlename, AssetBundle.LoadFromMemoryAsync(memoryStream.ToArray()));
31+
if (bundlename == "masterbundle")
32+
{
33+
stream.CopyTo(memoryStream);
34+
AssetBundleCreateRequest assetBundle = AssetBundle.LoadFromMemoryAsync(memoryStream.ToArray());
35+
masterBundle = assetBundle.assetBundle;
36+
}
37+
else
38+
{
39+
FikaPlugin.Instance.FikaLogger.LogFatal("Unknown bundle loaded! Terminating...");
40+
Application.Quit();
41+
}
3942
}
4043
});
44+
45+
Instance = this;
4146
}
4247

43-
public AssetBundle GetAssetBundle(string bundleName)
48+
/// <summary>
49+
/// Loads a Fika asset from the Master Bundle
50+
/// </summary>
51+
/// <typeparam name="T">The <see cref="UnityEngine.Object"/> to load</typeparam>
52+
/// <param name="asset">The <see cref="EFikaAsset"/> to load</param>
53+
/// <returns></returns>
54+
/// <exception cref="NullReferenceException">Master Bundle could not be found</exception>
55+
/// <exception cref="ArgumentOutOfRangeException"><see cref="EFikaAsset"/> was out of range</exception>
56+
internal T GetFikaAsset<T>(EFikaAsset asset) where T : UnityEngine.Object
4457
{
45-
if (_loadedBundles.TryGetValue(bundleName, out AssetBundleCreateRequest request) && request.isDone)
58+
if (masterBundle == null)
4659
{
47-
return request.assetBundle;
60+
throw new NullReferenceException("GetFikaAsset::MasterBundle did not exist!");
4861
}
4962

50-
return null;
63+
switch (asset)
64+
{
65+
case EFikaAsset.MainMenuUI:
66+
return masterBundle.LoadAsset<T>("MainMenuUI");
67+
case EFikaAsset.MatchmakerUI:
68+
return masterBundle.LoadAsset<T>("NewMatchMakerUI");
69+
case EFikaAsset.Ping:
70+
return masterBundle.LoadAsset<T>("BasePingPrefab"); ;
71+
case EFikaAsset.PlayerUI:
72+
return masterBundle.LoadAsset<T>("PlayerFriendlyUI");
73+
case EFikaAsset.SendItemMenu:
74+
return masterBundle.LoadAsset<T>("SendItemMenu");
75+
}
76+
77+
throw new ArgumentOutOfRangeException(nameof(asset), "Invalid type was given");
78+
}
79+
80+
/// <summary>
81+
/// Loads all <see cref="EFikaSprite"/> into memory and caches them
82+
/// </summary>
83+
/// <returns>All sprites in a <see cref="Dictionary{TKey, TValue}"/></returns>
84+
internal Dictionary<EFikaSprite, Sprite> GetFikaSprites()
85+
{
86+
Dictionary<EFikaSprite, Sprite> sprites = [];
87+
88+
sprites.Add(EFikaSprite.PingPoint, masterBundle.LoadAsset<Sprite>("PingPoint"));
89+
sprites.Add(EFikaSprite.PingPlayer, masterBundle.LoadAsset<Sprite>("PingPlayer"));
90+
sprites.Add(EFikaSprite.PingLootableContainer, masterBundle.LoadAsset<Sprite>("PingLootableContainer"));
91+
sprites.Add(EFikaSprite.PingDoor, masterBundle.LoadAsset<Sprite>("PingDoor"));
92+
sprites.Add(EFikaSprite.PingDeadBody, masterBundle.LoadAsset<Sprite>("PingDeadBody"));
93+
sprites.Add(EFikaSprite.PingLootItem, masterBundle.LoadAsset<Sprite>("PingLootItem"));
94+
95+
return sprites;
96+
}
97+
98+
public enum EFikaSprite
99+
{
100+
PingPoint,
101+
PingPlayer,
102+
PingLootableContainer,
103+
PingDoor,
104+
PingDeadBody,
105+
PingLootItem
106+
}
107+
108+
public enum EFikaAsset
109+
{
110+
MainMenuUI,
111+
MatchmakerUI,
112+
Ping,
113+
PlayerUI,
114+
SendItemMenu
51115
}
52116
}
53117
}

Fika.Core/Console/FikaCommands.cs

Lines changed: 78 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using EFT.UI;
66
using Fika.Core.Coop.Components;
77
using Fika.Core.Coop.GameMode;
8+
using Fika.Core.Coop.HostClasses;
89
using Fika.Core.Coop.Players;
910
using Fika.Core.Coop.Utils;
1011
using Fika.Core.Networking;
@@ -83,7 +84,7 @@ public static void God([ConsoleArgument(false, "true or false to toggle god mode
8384
[ConsoleCommand("extract", "", null, "Extract from raid", [])]
8485
public static void Extract()
8586
{
86-
CoopGame coopGame = (CoopGame)Singleton<IFikaGame>.Instance;
87+
CoopGame coopGame = CoopGame.Instance;
8788

8889
if (coopGame == null)
8990
{
@@ -105,56 +106,61 @@ public static void Extract()
105106
[ConsoleCommand("despawnallai", "", null, "Despawns all AI bots", [])]
106107
public static void DespawnAllAI()
107108
{
108-
if (Singleton<IFikaGame>.Instance is CoopGame game)
109+
CoopGame coopGame = CoopGame.Instance;
110+
if (coopGame != null)
109111
{
110112
if (!FikaBackendUtils.IsServer)
111113
{
112114
ConsoleScreen.LogWarning("You are not the host.");
113115
return;
114116
}
115117

116-
CoopHandler.TryGetCoopHandler(out CoopHandler coopHandler);
117-
118-
List<IPlayer> Bots = new(game.BotsController.Players);
119-
120-
foreach (Player bot in Bots)
118+
if (CoopHandler.TryGetCoopHandler(out CoopHandler coopHandler))
121119
{
122-
if (bot.AIData.BotOwner == null)
120+
foreach (Player bot in coopGame.Bots.Values)
123121
{
124-
continue;
125-
}
122+
if (bot.AIData.BotOwner == null)
123+
{
124+
continue;
125+
}
126126

127-
ConsoleScreen.Log($"Despawning: {bot.Profile.Nickname}");
127+
ConsoleScreen.Log($"Despawning: {bot.Profile.Nickname}");
128128

129-
game.DespawnBot(coopHandler, bot);
129+
coopGame.DespawnBot(coopHandler, bot);
130+
}
131+
return;
130132
}
133+
134+
ConsoleScreen.LogError("Could not find CoopHandler!");
131135
}
132136
}
133137

134138
[ConsoleCommand("stoptimer", "", null, "Stops the game timer", [])]
135139
public static void StopTimer()
136140
{
137-
if (Singleton<IFikaGame>.Instance is CoopGame game)
141+
CoopGame coopGame = CoopGame.Instance;
142+
if (coopGame != null)
138143
{
139-
if (game.GameTimer.Status == GameTimerClass.EGameTimerStatus.Stopped)
144+
if (coopGame.GameTimer.Status == GameTimerClass.EGameTimerStatus.Stopped)
140145
{
141-
ConsoleScreen.LogError("GameTimer is already stopped at: " + game.GameTimer.PastTime.ToString());
146+
ConsoleScreen.LogError("GameTimer is already stopped at: " + coopGame.GameTimer.PastTime.ToString());
142147
return;
143148
}
144-
game.GameTimer.TryStop();
145-
if (game.GameTimer.Status == GameTimerClass.EGameTimerStatus.Stopped)
149+
coopGame.GameTimer.TryStop();
150+
if (coopGame.GameTimer.Status == GameTimerClass.EGameTimerStatus.Stopped)
146151
{
147-
ConsoleScreen.Log("GameTimer stopped at: " + game.GameTimer.PastTime.ToString());
152+
ConsoleScreen.Log("GameTimer stopped at: " + coopGame.GameTimer.PastTime.ToString());
148153
}
149154
}
150155
}
151156

152157
[ConsoleCommand("goToBTR", "", null, "Teleports you to the BTR if active", [])]
153158
public static void GoToBTR()
154159
{
155-
if (Singleton<IFikaGame>.Instance is CoopGame game)
160+
CoopGame coopGame = CoopGame.Instance;
161+
if (coopGame != null)
156162
{
157-
GameWorld gameWorld = game.GameWorld_0;
163+
GameWorld gameWorld = coopGame.GameWorld_0;
158164
if (gameWorld != null)
159165
{
160166
if (gameWorld.BtrController != null)
@@ -280,19 +286,67 @@ public static void SpawnItem([ConsoleArgument("", "The templateId to spawn an it
280286
WithCheckMinMax = false
281287
};
282288

283-
284289
IBotGame botController = (IBotGame)Singleton<AbstractGame>.Instance;
285290
botController.BotsController.BotSpawner.ActivateBotsByWave(newBotData);
286291
ConsoleScreen.Log($"SpawnNPC completed. {amount} bots spawned.");
287292
}
288293

294+
[ConsoleCommand("spawnAirdrop", "", null, "Spawns an airdrop")]
295+
public static void SpawnAirdrop()
296+
{
297+
if (!CheckForGame())
298+
{
299+
return;
300+
}
301+
302+
if (!FikaBackendUtils.IsServer)
303+
{
304+
ConsoleScreen.LogWarning("You cannot spawn an airdrop as a client!");
305+
return;
306+
}
307+
308+
CoopHostGameWorld gameWorld = (CoopHostGameWorld)Singleton<GameWorld>.Instance;
309+
if (gameWorld == null)
310+
{
311+
ConsoleScreen.LogError("GameWorld does not exist or you are a client!");
312+
return;
313+
}
314+
315+
GClass2459 serverAirdropManager = gameWorld.ClientSynchronizableObjectLogicProcessor.ServerAirdropManager;
316+
if (serverAirdropManager == null)
317+
{
318+
ConsoleScreen.LogError("ServerAirdropManager was null!");
319+
return;
320+
}
321+
322+
if (!serverAirdropManager.Boolean_0)
323+
{
324+
ConsoleScreen.LogError("Airdrops are disabled!");
325+
return;
326+
}
327+
328+
List<Vector3> dropPoints = serverAirdropManager.list_2;
329+
if (dropPoints != null && dropPoints.Count > 0)
330+
{
331+
string templateId = serverAirdropManager.string_0;
332+
serverAirdropManager.method_5(serverAirdropManager.Single_0);
333+
gameWorld.InitAirdrop(templateId, true, serverAirdropManager.method_6());
334+
serverAirdropManager.string_0 = null;
335+
dropPoints.Clear();
336+
ConsoleScreen.Log("Started airdrop");
337+
return;
338+
}
339+
340+
serverAirdropManager.method_5(serverAirdropManager.Single_0);
341+
gameWorld.InitAirdrop();
342+
ConsoleScreen.Log("Started airdrop");
343+
}
289344
#endif
290345

291346
[ConsoleCommand("debug", "", null, "Toggle debug window", [])]
292347
public static void Debug(bool state)
293348
{
294-
CoopGame coopGame = (CoopGame)Singleton<IFikaGame>.Instance;
295-
349+
CoopGame coopGame = CoopGame.Instance;
296350
if (coopGame == null)
297351
{
298352
ConsoleScreen.LogWarning("You are not in a game.");
@@ -316,8 +370,7 @@ public static void Clear()
316370

317371
private static bool CheckForGame()
318372
{
319-
CoopGame coopGame = (CoopGame)Singleton<IFikaGame>.Instance;
320-
373+
CoopGame coopGame = CoopGame.Instance;
321374
if (coopGame == null)
322375
{
323376
ConsoleScreen.LogWarning("You are not in a game.");

Fika.Core/Coop/BotClasses/CoopBotHealthController.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using EFT;
44
using EFT.InventoryLogic;
55
using Fika.Core.Coop.Players;
6+
using Fika.Core.Networking;
67

78
namespace Fika.Core.Coop.ClientClasses
89
{
@@ -22,14 +23,20 @@ public override void SendNetworkSyncPacket(NetworkHealthSyncPacketStruct packet)
2223
{
2324
if (packet.SyncType == NetworkHealthSyncPacketStruct.ESyncType.IsAlive && !packet.Data.IsAlive.IsAlive)
2425
{
25-
coopBot.PacketSender.HealthSyncPackets.Enqueue(coopBot.SetupCorpseSyncPacket(packet));
26+
HealthSyncPacket deathPacket = coopBot.SetupCorpseSyncPacket(packet);
27+
coopBot.PacketSender.SendPacket(ref deathPacket);
2628
return;
2729
}
2830

29-
coopBot.PacketSender.HealthSyncPackets.Enqueue(new(coopBot.NetId)
31+
if (packet.SyncType is NetworkHealthSyncPacketStruct.ESyncType.DestroyedBodyPart or NetworkHealthSyncPacketStruct.ESyncType.ApplyDamage or NetworkHealthSyncPacketStruct.ESyncType.BodyHealth)
3032
{
31-
Packet = packet
32-
});
33+
HealthSyncPacket netPacket = new()
34+
{
35+
NetId = coopBot.NetId,
36+
Packet = packet
37+
};
38+
coopBot.PacketSender.SendPacket(ref netPacket);
39+
}
3340
}
3441
}
3542
}

Fika.Core/Coop/BotClasses/CoopBotInventoryController.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public CoopBotInventoryController(Player player, Profile profile, bool examined,
2929
coopBot = (CoopBot)player;
3030
mongoID_0 = currentId;
3131
ushort_0 = nextOperationId;
32-
searchController = new GClass1973(profile);
32+
searchController = new BotSearchControllerClass(profile);
3333
}
3434

3535
public override IPlayerSearchController PlayerSearchController
@@ -49,20 +49,21 @@ public override void vmethod_1(BaseInventoryOperationClass operation, [CanBeNull
4949
{
5050
// Check for GClass increments
5151
// Tripwire kit is always null on AI so we cannot use ToDescriptor as it throws a nullref
52-
if (operation is not GClass3210)
52+
if (operation is not GClass3281)
5353
{
5454
#if DEBUG
5555
FikaPlugin.Instance.FikaLogger.LogInfo($"Sending bot operation {operation.GetType()} from {coopBot.Profile.Nickname}");
5656
#endif
57-
GClass1198 writer = new();
58-
writer.WritePolymorph(operation.ToDescriptor());
57+
FikaWriter eftWriter = EFTSerializationManager.GetWriter();
58+
eftWriter.WritePolymorph(operation.ToDescriptor());
5959
InventoryPacket packet = new()
6060
{
61+
NetId = coopBot.NetId,
6162
CallbackId = operation.Id,
62-
OperationBytes = writer.ToArray()
63+
OperationBytes = eftWriter.ToArray()
6364
};
6465

65-
coopBot.PacketSender.InventoryPackets.Enqueue(packet);
66+
coopBot.PacketSender.SendPacket(ref packet);
6667
}
6768
HandleOperation(operation, callback).HandleExceptions();
6869
}
@@ -90,7 +91,7 @@ private void RunBotOperation(BaseInventoryOperationClass operation, Callback cal
9091

9192
public override SearchContentOperation vmethod_2(SearchableItemItemClass item)
9293
{
93-
return new GClass3232(method_12(), this, PlayerSearchController, Profile, item);
94+
return new GClass3303(method_12(), this, PlayerSearchController, Profile, item);
9495
}
9596

9697
private class BotInventoryOperationHandler(CoopBotInventoryController controller, BaseInventoryOperationClass operation, Callback callback)

0 commit comments

Comments
 (0)