Skip to content

Commit

Permalink
Save/load house unit trackers
Browse files Browse the repository at this point in the history
  • Loading branch information
ZivDero committed Nov 8, 2024
1 parent 37734e9 commit 0529915
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 14 deletions.
115 changes: 114 additions & 1 deletion src/extensions/house/houseext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
#include "debughandler.h"
#include "saveload.h"
#include "vinifera_saveload.h"
#include "storage/storageext.h"
#include "storageext.h"
#include "utracker.h"


/**
Expand Down Expand Up @@ -199,3 +200,115 @@ void HouseClassExtension::Put_Storage_Pointers()
new (reinterpret_cast<StorageClassExt*>(&This()->Tiberium)) StorageClassExt(&TiberiumStorage);
new (reinterpret_cast<StorageClassExt*>(&This()->Weed)) StorageClassExt(&WeedStorage);
}


/**
* A fake class for implementing new member functions which allow
* access to the "this" pointer of the intended class.
*
* @note: This must not contain a constructor or deconstructor!
* @note: All functions must be prefixed with "_" to prevent accidental virtualization.
*/
static class UnitTrackerClassExt final : public UnitTrackerClass
{
public:
HRESULT _Load(IStream* pStm);
HRESULT _Save(IStream* pStm);
};


/**
* Saves a unit tracker's counts
*
* @author: ZivDero
*/
HRESULT UnitTrackerClassExt::_Load(IStream* pStm)
{
int count;
HRESULT hr = pStm->Read(&count, sizeof(count), nullptr);
if (FAILED(hr)) {
return hr;
}

new (this) UnitTrackerClass(count);

for (int i = 0; i < UnitCount; i++) {
hr = pStm->Read(&UnitTotals[i], sizeof(UnitTotals[i]), nullptr);
if (FAILED(hr)) {
return hr;
}

}

return S_OK;
}


/**
* Saves a unit tracker's counts.
*
* @author: ZivDero
*/
HRESULT UnitTrackerClassExt::_Save(IStream* pStm)
{
HRESULT hr = pStm->Write(&UnitCount, sizeof(UnitCount), nullptr);
if (FAILED(hr)) {
return hr;
}

for (int i = 0; i < UnitCount; i++) {
HRESULT hr = pStm->Write(&UnitTotals[i], sizeof(UnitTotals[i]), nullptr);
if (FAILED(hr)) {
return hr;
}

}

return S_OK;
}


/**
* Reads a house's unit trackers.
*
* @author: ZivDero
*/
void HouseClassExtension::Load_Unit_Trackers(IStream* pStm)
{
/**
* Trackers store their counts in a dynamically allocated array (AARGH WW!).
* Thus, we need to save/load them manually.
* But we can't do this in the extension because ThisPtr isn't remapped yet.
*/

reinterpret_cast<UnitTrackerClassExt*>(This()->AircraftTotals)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->InfantryTotals)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->UnitTotals)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->BuildingTotals)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedAircraft)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedInfantry)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedUnits)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedBuildings)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->CapturedBuildings)->_Load(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->TotalCrates)->_Load(pStm);
}


/**
* Saves a house's unit trackers.
*
* @author: ZivDero
*/
void HouseClassExtension::Save_Unit_Trackers(IStream* pStm)
{
reinterpret_cast<UnitTrackerClassExt*>(This()->AircraftTotals)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->InfantryTotals)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->UnitTotals)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->BuildingTotals)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedAircraft)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedInfantry)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedUnits)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->DestroyedBuildings)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->CapturedBuildings)->_Save(pStm);
reinterpret_cast<UnitTrackerClassExt*>(This()->TotalCrates)->_Save(pStm);
}
2 changes: 2 additions & 0 deletions src/extensions/house/houseext.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ HouseClassExtension final : public AbstractClassExtension
virtual RTTIType What_Am_I() const override { return RTTI_HOUSE; }

void Put_Storage_Pointers();
void Load_Unit_Trackers(IStream* pStm);
void Save_Unit_Trackers(IStream* pStm);

public:
/**
Expand Down
12 changes: 6 additions & 6 deletions src/extensions/house/houseext_hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@


/**
* A fake class for implementing new member functions which allow
* access to the "this" pointer of the intended class.
*
* @note: This must not contain a constructor or deconstructor!
* @note: All functions must be prefixed with "_" to prevent accidental virtualization.
*/
* A fake class for implementing new member functions which allow
* access to the "this" pointer of the intended class.
*
* @note: This must not contain a constructor or deconstructor!
* @note: All functions must be prefixed with "_" to prevent accidental virtualization.
*/
static class HouseClassExt final : public HouseClass
{
public:
Expand Down
49 changes: 43 additions & 6 deletions src/vinifera/vinifera_saveload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,22 +662,46 @@ bool Vinifera_Remap_Extension_Pointers()
*
* @author: ZivDero
*/
void Vinifera_Put_Storage_Pointers()
void Put_Storage_Pointers()
{
for (int i = 0; i < Technos.Count(); i++)
{
for (int i = 0; i < Technos.Count(); i++) {
const TechnoClass* techno = Technos[i];
Extension::Fetch<TechnoClassExtension>(techno)->Put_Storage_Pointers();
}

for (int i = 0; i < Houses.Count(); i++)
{
for (int i = 0; i < Houses.Count(); i++) {
const HouseClass* house = Houses[i];
Extension::Fetch<HouseClassExtension>(house)->Put_Storage_Pointers();
}
}


/**
* Saves unit trackers.
*
* @author: ZivDero
*/
void Load_Unit_Trackers(IStream* pStm)
{
for (int i = 0; i < HouseExtensions.Count(); i++) {
HouseExtensions[i]->Load_Unit_Trackers(pStm);
}
}


/**
* Saves unit trackers.
*
* @author: ZivDero
*/
void Save_Unit_Trackers(IStream* pStm)
{
for (int i = 0; i < HouseExtensions.Count(); i++) {
HouseExtensions[i]->Save_Unit_Trackers(pStm);
}
}


/**
* Saves the game to a file on the disk.
*
Expand Down Expand Up @@ -787,6 +811,13 @@ bool Vinifera_Save_Game(const char* file_name, const char* descr, bool)
DEBUG_INFO("Calling Vinifera_Put_All().\n");
bool result = Vinifera_Put_All(stream, false);

/**
* Save unit trackers in houses.
* This has to happen in the same order in which we load them,
* and we have to do that after remapping pointers.
*/
Save_Unit_Trackers(stream);

DEBUG_INFO("Unlinking content stream from compressor.\n");
hr = linkstream->Unlink_Stream(nullptr);
if (FAILED(hr)) {
Expand Down Expand Up @@ -903,8 +934,14 @@ bool Vinifera_Load_Game(const char* file_name)
linkstream->Unlink_Stream(nullptr);

SwizzleManager.Reset();

/**
* Load unit trackers in houses.
*/
Load_Unit_Trackers(stream);

Post_Load_Game();
Vinifera_Put_Storage_Pointers();
Put_Storage_Pointers();
Map.Init_IO();
Map.Activate(1);
Map.Set_Dimensions();
Expand Down
2 changes: 1 addition & 1 deletion src/vinifera/vinifera_saveload.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ extern unsigned ViniferaGameVersion;
bool Vinifera_Put_All(IStream *pStm, bool save_net = false);
bool Vinifera_Get_All(IStream *pStm, bool load_net = false);
bool Vinifera_Remap_Extension_Pointers();
void Vinifera_Put_Storage_Pointers();
void Put_Storage_Pointers();
bool Vinifera_Save_Game(const char* file_name, const char* descr, bool);
bool Vinifera_Load_Game(const char* file_name);
void SaveGame_Hooks();
Expand Down

0 comments on commit 0529915

Please sign in to comment.