aboutsummaryrefslogtreecommitdiff
path: root/primedev/core/filesystem/rpakfilesystem.h
blob: 87a41e7b16dc0ce158f03c2a2e673972e6b6acdc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#pragma once

#include <regex>

enum PakHandle : int
{
	INVALID = -1,
};

struct ModPak_t
{
	std::string m_modName;

	std::string m_path;
	size_t m_pathHash = 0;

	// If the map being loaded matches this regex, this pak will be loaded.
	std::regex m_mapRegex;
	// If a pak with a hash matching this is loaded, this pak will be loaded.
	size_t m_dependentPakHash = 0;
	// If this is set, this pak will be loaded whenever any other pak is loaded.
	bool m_preload = false;

	// If this is set, the Pak will be unloaded on next map load
	bool m_markedForDelete = false;
	// The current rpak handle associated with this Pak
	PakHandle m_handle = PakHandle::INVALID;
};

class PakLoadManager
{
public:
	void UnloadAllModPaks();
	void TrackModPaks(Mod& mod);

	void CleanUpUnloadedPaks();
	void UnloadMarkedPaks();

	void LoadModPaksForMap(const char* mapName);
	void UnloadModPaks();

	// Whether the current context is a vanilla call to a function, or a modded one
	bool IsVanillaCall() const { return m_reentranceCounter == 0; }
	// Whether paks will be forced to reload on the next map load
	bool GetForceReloadOnMapLoad() const { return m_forceReloadOnMapLoad; }
	void SetForceReloadOnMapLoad(bool value) { m_forceReloadOnMapLoad = value; }

	void OnPakLoaded(std::string& originalPath, std::string& resultingPath, PakHandle resultingHandle);
	void OnPakUnloading(PakHandle handle);

	void FixupPakPath(std::string& path);

	void LoadPreloadPaks();
	void ReloadPostloadPaks();

	void* OpenFile(const char* path);

private:
	void LoadDependentPaks(std::string& path, PakHandle handle);
	void UnloadDependentPaks(PakHandle handle);

	// All paks that vanilla has attempted to load. (they may have been aliased away)
	// Also known as a list of rpaks that the vanilla game would have loaded at this point in time.
	std::vector<std::pair<std::string, PakHandle>> m_vanillaPaks;

	// All mod Paks that are currently tracked
	std::vector<ModPak_t> m_modPaks;
	// Hashes of the currently loaded map mod paks
	std::vector<size_t> m_mapPaks;
	// Currently loaded Pak path hashes that depend on a handle to remain loaded (Postload)
	std::vector<std::pair<PakHandle, size_t>> m_dependentPaks;

	// Used to force rpaks to be unloaded and reloaded on the next map load.
	// Vanilla behaviour is to not do this when loading into mp_lobby, or loading into the same map you were last in.
	bool m_forceReloadOnMapLoad = false;
	// Used to track if the current hook call is a vanilla call or not.
	// When loading/unloading a mod Pak, increment this before doing so, and decrement afterwards.
	int m_reentranceCounter = 0;
};

extern PakLoadManager* g_pPakLoadManager;