mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-02 01:06:42 +00:00
[General] Implement cell records for RecordDynamic packets, part 1
New interior cells can be now be created that are either blank or based on existing interior cells.
This commit is contained in:
parent
18a7ac5940
commit
031acffcbe
6 changed files with 121 additions and 1 deletions
|
@ -32,6 +32,7 @@ LockpickRecord tempLockpick;
|
||||||
ProbeRecord tempProbe;
|
ProbeRecord tempProbe;
|
||||||
RepairRecord tempRepair;
|
RepairRecord tempRepair;
|
||||||
LightRecord tempLight;
|
LightRecord tempLight;
|
||||||
|
CellRecord tempCell;
|
||||||
|
|
||||||
BaseOverrides tempOverrides;
|
BaseOverrides tempOverrides;
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ void RecordsDynamicFunctions::ClearRecords() noexcept
|
||||||
WorldstateFunctions::writeWorldstate.probeRecords.clear();
|
WorldstateFunctions::writeWorldstate.probeRecords.clear();
|
||||||
WorldstateFunctions::writeWorldstate.repairRecords.clear();
|
WorldstateFunctions::writeWorldstate.repairRecords.clear();
|
||||||
WorldstateFunctions::writeWorldstate.lightRecords.clear();
|
WorldstateFunctions::writeWorldstate.lightRecords.clear();
|
||||||
|
WorldstateFunctions::writeWorldstate.cellRecords.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short RecordsDynamicFunctions::GetRecordType() noexcept
|
unsigned short RecordsDynamicFunctions::GetRecordType() noexcept
|
||||||
|
@ -426,6 +428,8 @@ void RecordsDynamicFunctions::SetRecordBaseId(const char* baseId) noexcept
|
||||||
tempRepair.baseId = baseId;
|
tempRepair.baseId = baseId;
|
||||||
else if (writeRecordsType == mwmp::RECORD_TYPE::LIGHT)
|
else if (writeRecordsType == mwmp::RECORD_TYPE::LIGHT)
|
||||||
tempLight.baseId = baseId;
|
tempLight.baseId = baseId;
|
||||||
|
else if (writeRecordsType == mwmp::RECORD_TYPE::CELL)
|
||||||
|
tempCell.baseId = baseId;
|
||||||
else
|
else
|
||||||
LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set baseId for record type %i which lacks that property", writeRecordsType);
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set baseId for record type %i which lacks that property", writeRecordsType);
|
||||||
}
|
}
|
||||||
|
@ -509,6 +513,8 @@ void RecordsDynamicFunctions::SetRecordName(const char* name) noexcept
|
||||||
tempRepair.data.mName = name;
|
tempRepair.data.mName = name;
|
||||||
else if (writeRecordsType == mwmp::RECORD_TYPE::LIGHT)
|
else if (writeRecordsType == mwmp::RECORD_TYPE::LIGHT)
|
||||||
tempLight.data.mName = name;
|
tempLight.data.mName = name;
|
||||||
|
else if (writeRecordsType == mwmp::RECORD_TYPE::CELL)
|
||||||
|
tempCell.data.mName = name;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set name for record type %i which lacks that property", writeRecordsType);
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Tried to set name for record type %i which lacks that property", writeRecordsType);
|
||||||
|
@ -1594,6 +1600,12 @@ void RecordsDynamicFunctions::AddRecord() noexcept
|
||||||
WorldstateFunctions::writeWorldstate.lightRecords.push_back(tempLight);
|
WorldstateFunctions::writeWorldstate.lightRecords.push_back(tempLight);
|
||||||
tempLight = {};
|
tempLight = {};
|
||||||
}
|
}
|
||||||
|
else if (writeRecordsType == mwmp::RECORD_TYPE::CELL)
|
||||||
|
{
|
||||||
|
tempCell.baseOverrides = tempOverrides;
|
||||||
|
WorldstateFunctions::writeWorldstate.cellRecords.push_back(tempCell);
|
||||||
|
tempCell = {};
|
||||||
|
}
|
||||||
|
|
||||||
effectCount = 0;
|
effectCount = 0;
|
||||||
tempOverrides = {};
|
tempOverrides = {};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/worldimp.hpp"
|
#include "../mwworld/worldimp.hpp"
|
||||||
|
|
||||||
#include "RecordHelper.hpp"
|
#include "RecordHelper.hpp"
|
||||||
|
@ -160,6 +161,13 @@ bool RecordHelper::doesLightRecordExist(const std::string& id)
|
||||||
return world->getStore().get<ESM::Light>().search(id);
|
return world->getStore().get<ESM::Light>().search(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RecordHelper::doesCellRecordExist(const std::string& id)
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
return world->getStore().get<ESM::Cell>().search(id);
|
||||||
|
}
|
||||||
|
|
||||||
std::string RecordHelper::createCreatureRecord(const ESM::Creature& record)
|
std::string RecordHelper::createCreatureRecord(const ESM::Creature& record)
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
@ -1485,6 +1493,61 @@ void RecordHelper::overrideLightRecord(const mwmp::LightRecord& record)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecordHelper::overrideCellRecord(const mwmp::CellRecord& record)
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
ESM::Cell recordData = record.data;
|
||||||
|
|
||||||
|
if (recordData.mName.empty())
|
||||||
|
{
|
||||||
|
LOG_APPEND(TimedLog::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr playerPtr = world->getPlayerPtr();
|
||||||
|
bool isCurrentCell = Misc::StringUtils::ciEqual(recordData.mName, playerPtr.getCell()->getCell()->mName);
|
||||||
|
|
||||||
|
if (record.baseId.empty())
|
||||||
|
{
|
||||||
|
recordData.mData.mFlags |= ESM::Cell::Flags::Interior;
|
||||||
|
|
||||||
|
world->unloadCell(recordData);
|
||||||
|
world->clearCellStore(recordData);
|
||||||
|
world->getModifiableStore().overrideRecord(recordData);
|
||||||
|
}
|
||||||
|
else if (doesCellRecordExist(record.baseId))
|
||||||
|
{
|
||||||
|
const ESM::Cell *baseData = world->getStore().get<ESM::Cell>().search(record.baseId);
|
||||||
|
ESM::Cell finalData = *baseData;
|
||||||
|
finalData.mName = recordData.mName;
|
||||||
|
|
||||||
|
world->unloadCell(finalData);
|
||||||
|
world->clearCellStore(finalData);
|
||||||
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(TimedLog::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCurrentCell)
|
||||||
|
{
|
||||||
|
// As a temporary solution, move the player to exterior 0, 0, but
|
||||||
|
// fix this once it's possible to override exteriors cells as well
|
||||||
|
ESM::Position tempPos;
|
||||||
|
tempPos.pos[0] = 0;
|
||||||
|
tempPos.pos[1] = 0;
|
||||||
|
tempPos.pos[2] = 0;
|
||||||
|
|
||||||
|
ESM::Position playerPos = playerPtr.getRefData().getPosition();
|
||||||
|
|
||||||
|
world->changeToExteriorCell(tempPos, true, true);
|
||||||
|
world->changeToInteriorCell(recordData.mName, playerPos, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RecordHelper::overrideCreatureRecord(const ESM::Creature& record)
|
void RecordHelper::overrideCreatureRecord(const ESM::Creature& record)
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
@ -1624,3 +1687,10 @@ void RecordHelper::overrideLightRecord(const ESM::Light& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(record);
|
world->getModifiableStore().overrideRecord(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecordHelper::overrideCellRecord(const ESM::Cell& record)
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
world->getModifiableStore().overrideRecord(record);
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace RecordHelper
|
||||||
bool doesProbeRecordExist(const std::string& id);
|
bool doesProbeRecordExist(const std::string& id);
|
||||||
bool doesRepairRecordExist(const std::string& id);
|
bool doesRepairRecordExist(const std::string& id);
|
||||||
bool doesLightRecordExist(const std::string& id);
|
bool doesLightRecordExist(const std::string& id);
|
||||||
|
bool doesCellRecordExist(const std::string& id);
|
||||||
|
|
||||||
std::string createCreatureRecord(const ESM::Creature& record);
|
std::string createCreatureRecord(const ESM::Creature& record);
|
||||||
std::string createNpcRecord(const ESM::NPC& record);
|
std::string createNpcRecord(const ESM::NPC& record);
|
||||||
|
@ -65,6 +66,7 @@ namespace RecordHelper
|
||||||
void overrideProbeRecord(const mwmp::ProbeRecord& record);
|
void overrideProbeRecord(const mwmp::ProbeRecord& record);
|
||||||
void overrideRepairRecord(const mwmp::RepairRecord& record);
|
void overrideRepairRecord(const mwmp::RepairRecord& record);
|
||||||
void overrideLightRecord(const mwmp::LightRecord& record);
|
void overrideLightRecord(const mwmp::LightRecord& record);
|
||||||
|
void overrideCellRecord(const mwmp::CellRecord& record);
|
||||||
|
|
||||||
void overrideCreatureRecord(const ESM::Creature& record);
|
void overrideCreatureRecord(const ESM::Creature& record);
|
||||||
void overrideNpcRecord(const ESM::NPC& record);
|
void overrideNpcRecord(const ESM::NPC& record);
|
||||||
|
@ -91,6 +93,7 @@ namespace RecordHelper
|
||||||
void overrideProbeRecord(const ESM::Probe& record);
|
void overrideProbeRecord(const ESM::Probe& record);
|
||||||
void overrideRepairRecord(const ESM::Repair& record);
|
void overrideRepairRecord(const ESM::Repair& record);
|
||||||
void overrideLightRecord(const ESM::Light& record);
|
void overrideLightRecord(const ESM::Light& record);
|
||||||
|
void overrideCellRecord(const ESM::Cell& record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -278,6 +278,18 @@ void Worldstate::addRecords()
|
||||||
RecordHelper::overrideLightRecord(record);
|
RecordHelper::overrideLightRecord(record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (recordsType == mwmp::RECORD_TYPE::CELL)
|
||||||
|
{
|
||||||
|
for (auto &&record : cellRecords)
|
||||||
|
{
|
||||||
|
bool hasBaseId = !record.baseId.empty();
|
||||||
|
|
||||||
|
LOG_APPEND(TimedLog::LOG_INFO, "- cell record %s\n-- baseId is %s", record.data.mName.c_str(),
|
||||||
|
hasBaseId ? record.baseId.c_str() : "empty");
|
||||||
|
|
||||||
|
RecordHelper::overrideCellRecord(record);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Worldstate::containsExploredMapTile(int cellX, int cellY)
|
bool Worldstate::containsExploredMapTile(int cellX, int cellY)
|
||||||
|
|
|
@ -51,7 +51,8 @@ namespace mwmp
|
||||||
LOCKPICK,
|
LOCKPICK,
|
||||||
PROBE,
|
PROBE,
|
||||||
REPAIR,
|
REPAIR,
|
||||||
LIGHT
|
LIGHT,
|
||||||
|
CELL
|
||||||
};
|
};
|
||||||
|
|
||||||
// When using an existing record as a base, this struct tracks which changes
|
// When using an existing record as a base, this struct tracks which changes
|
||||||
|
@ -154,6 +155,13 @@ namespace mwmp
|
||||||
BaseOverrides baseOverrides;
|
BaseOverrides baseOverrides;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CellRecord
|
||||||
|
{
|
||||||
|
ESM::Cell data;
|
||||||
|
std::string baseId;
|
||||||
|
BaseOverrides baseOverrides;
|
||||||
|
};
|
||||||
|
|
||||||
struct ClothingRecord
|
struct ClothingRecord
|
||||||
{
|
{
|
||||||
ESM::Clothing data;
|
ESM::Clothing data;
|
||||||
|
@ -331,6 +339,7 @@ namespace mwmp
|
||||||
std::vector<ApparatusRecord> apparatusRecords;
|
std::vector<ApparatusRecord> apparatusRecords;
|
||||||
std::vector<ArmorRecord> armorRecords;
|
std::vector<ArmorRecord> armorRecords;
|
||||||
std::vector<BookRecord> bookRecords;
|
std::vector<BookRecord> bookRecords;
|
||||||
|
std::vector<CellRecord> cellRecords;
|
||||||
std::vector<ClothingRecord> clothingRecords;
|
std::vector<ClothingRecord> clothingRecords;
|
||||||
std::vector<ContainerRecord> containerRecords;
|
std::vector<ContainerRecord> containerRecords;
|
||||||
std::vector<CreatureRecord> creatureRecords;
|
std::vector<CreatureRecord> creatureRecords;
|
||||||
|
|
|
@ -60,6 +60,8 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send)
|
||||||
worldstate->recordsCount = Utils::getVectorSize(worldstate->repairRecords);
|
worldstate->recordsCount = Utils::getVectorSize(worldstate->repairRecords);
|
||||||
else if (worldstate->recordsType == mwmp::RECORD_TYPE::LIGHT)
|
else if (worldstate->recordsType == mwmp::RECORD_TYPE::LIGHT)
|
||||||
worldstate->recordsCount = Utils::getVectorSize(worldstate->lightRecords);
|
worldstate->recordsCount = Utils::getVectorSize(worldstate->lightRecords);
|
||||||
|
else if (worldstate->recordsType == mwmp::RECORD_TYPE::CELL)
|
||||||
|
worldstate->recordsCount = Utils::getVectorSize(worldstate->cellRecords);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Processed invalid ID_RECORD_DYNAMIC packet about unimplemented recordsType %i",
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_ERROR, "Processed invalid ID_RECORD_DYNAMIC packet about unimplemented recordsType %i",
|
||||||
|
@ -120,6 +122,8 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send)
|
||||||
Utils::resetVector(worldstate->repairRecords, worldstate->recordsCount);
|
Utils::resetVector(worldstate->repairRecords, worldstate->recordsCount);
|
||||||
else if (worldstate->recordsType == mwmp::RECORD_TYPE::LIGHT)
|
else if (worldstate->recordsType == mwmp::RECORD_TYPE::LIGHT)
|
||||||
Utils::resetVector(worldstate->lightRecords, worldstate->recordsCount);
|
Utils::resetVector(worldstate->lightRecords, worldstate->recordsCount);
|
||||||
|
else if (worldstate->recordsType == mwmp::RECORD_TYPE::CELL)
|
||||||
|
Utils::resetVector(worldstate->cellRecords, worldstate->recordsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (worldstate->recordsType == mwmp::RECORD_TYPE::SPELL)
|
if (worldstate->recordsType == mwmp::RECORD_TYPE::SPELL)
|
||||||
|
@ -773,6 +777,16 @@ void PacketRecordDynamic::Packet(RakNet::BitStream *bs, bool send)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (worldstate->recordsType == mwmp::RECORD_TYPE::CELL)
|
||||||
|
{
|
||||||
|
for (auto &&record : worldstate->cellRecords)
|
||||||
|
{
|
||||||
|
auto &recordData = record.data;
|
||||||
|
|
||||||
|
RW(record.baseId, send, true);
|
||||||
|
RW(record.data.mName, send, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketRecordDynamic::ProcessEffects(ESM::EffectList &effectList, bool send)
|
void PacketRecordDynamic::ProcessEffects(ESM::EffectList &effectList, bool send)
|
||||||
|
|
Loading…
Reference in a new issue