Noggit3 : extendable array: prevent use after extend

https://github.com/wowdev/noggit3/pull/91
+ adspartan mapchunk: store pointer to the header when saving f7e5f8396f
This commit is contained in:
T1ti
2024-08-31 05:35:09 +02:00
parent 2c3c98add7
commit 61b607bb5c
17 changed files with 231 additions and 113 deletions

View File

@@ -120,7 +120,7 @@ void ChunkWater::fromFile(BlizzardArchive::ClientFile &f, size_t basePos)
}
void ChunkWater::save(sExtendableArray& adt, int base_pos, int& header_pos, int& current_pos)
void ChunkWater::save(util::sExtendableArray& adt, int base_pos, int& header_pos, int& current_pos)
{
MH2O_Header header;
@@ -159,7 +159,7 @@ void ChunkWater::save(sExtendableArray& adt, int base_pos, int& header_pos, int&
}
}
memcpy(adt.GetPointer<char>(header_pos), &header, sizeof(MH2O_Header));
memcpy(adt.GetPointer<char>(header_pos).get(), &header, sizeof(MH2O_Header));
header_pos += sizeof(MH2O_Header);
}

View File

@@ -4,12 +4,12 @@
#include <noggit/liquid_layer.hpp>
#include <noggit/MapHeaders.h>
#include <noggit/tool_enums.hpp>
#include <util/sExtendableArray.hpp>
#include <vector>
#include <set>
#include <optional>
class sExtendableArray;
class MapChunk;
class TileWater;
@@ -31,7 +31,7 @@ public:
void from_mclq(std::vector<mclq>& layers);
void fromFile(BlizzardArchive::ClientFile& f, size_t basePos);
void save(sExtendableArray& adt, int base_pos, int& header_pos, int& current_pos);
void save(util::sExtendableArray& adt, int base_pos, int& header_pos, int& current_pos);
bool is_visible ( const float& cull_distance
, const math::frustum& frustum

View File

@@ -1427,7 +1427,7 @@ void MapChunk::setFlag(bool changeto, uint32_t flag)
registerChunkUpdate(ChunkUpdateFlags::FLAGS);
}
void MapChunk::save(sExtendableArray& lADTFile
void MapChunk::save(util::sExtendableArray& lADTFile
, int& lCurrentPosition
, int& lMCIN_Position
, std::map<std::string, int> &lTextures
@@ -1443,7 +1443,7 @@ void MapChunk::save(sExtendableArray& lADTFile
// MCNK data
// lADTFile.Insert(lCurrentPosition + 8, 0x80, reinterpret_cast<char*>(&(header)));
MapChunkHeader *lMCNK_header = lADTFile.GetPointer<MapChunkHeader>(lCurrentPosition + 8);
auto const lMCNK_header = lADTFile.GetPointer<MapChunkHeader>(lCurrentPosition + 8);
header_flags.flags.do_not_fix_alpha_map = 1;
@@ -1505,9 +1505,13 @@ void MapChunk::save(sExtendableArray& lADTFile
lADTFile.Extend(8 + lMCVT_Size);
SetChunkHeader(lADTFile, lCurrentPosition, 'MCVT', lMCVT_Size);
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsHeight = lCurrentPosition - lMCNK_Position;
// lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsHeight = lCurrentPosition - lMCNK_Position;
float* lHeightmap = lADTFile.GetPointer<float>(lCurrentPosition + 8);
auto header_ptr = lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8);
header_ptr->ofsHeight = lCurrentPosition - lMCNK_Position;
auto const lHeightmap = lADTFile.GetPointer<float>(lCurrentPosition + 8);
for (int i = 0; i < mapbufsize; ++i)
lHeightmap[i] = mVertices[i].y - mVertices[0].y;
@@ -1522,15 +1526,15 @@ void MapChunk::save(sExtendableArray& lADTFile
lMCCV_Size = mapbufsize * sizeof(unsigned int);
lADTFile.Extend(8 + lMCCV_Size);
SetChunkHeader(lADTFile, lCurrentPosition, 'MCCV', lMCCV_Size);
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsMCCV = lCurrentPosition - lMCNK_Position;
header_ptr->ofsMCCV = lCurrentPosition - lMCNK_Position;
unsigned int *lmccv = lADTFile.GetPointer<unsigned int>(lCurrentPosition + 8);
auto const lmccv = lADTFile.GetPointer<unsigned int>(lCurrentPosition + 8);
for (int i = 0; i < mapbufsize; ++i)
{
*lmccv++ = ((unsigned char)(mccv[i].z * 127.0f) & 0xFF)
+ (((unsigned char)(mccv[i].y * 127.0f) & 0xFF) << 8)
+ (((unsigned char)(mccv[i].x * 127.0f) & 0xFF) << 16);
lmccv[i] = (((unsigned char)(mccv[i].z * 127.0f) & 0xFF) << 0)
+ (((unsigned char)(mccv[i].y * 127.0f) & 0xFF) << 8)
+ (((unsigned char)(mccv[i].x * 127.0f) & 0xFF) << 16);
}
lCurrentPosition += 8 + lMCCV_Size;
@@ -1538,7 +1542,7 @@ void MapChunk::save(sExtendableArray& lADTFile
}
else
{
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsMCCV = 0;
header_ptr->ofsMCCV = 0;
}
// MCNR
@@ -1547,9 +1551,9 @@ void MapChunk::save(sExtendableArray& lADTFile
lADTFile.Extend(8 + lMCNR_Size);
SetChunkHeader(lADTFile, lCurrentPosition, 'MCNR', lMCNR_Size);
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsNormal = lCurrentPosition - lMCNK_Position;
header_ptr->ofsNormal = lCurrentPosition - lMCNK_Position;
char * lNormals = lADTFile.GetPointer<char>(lCurrentPosition + 8);
auto const lNormals = lADTFile.GetPointer<char>(lCurrentPosition + 8);
auto& tile_buffer = mt->getChunkHeightmapBuffer();
int chunk_start = (px * 16 + py) * mapbufsize * 4;
@@ -1582,8 +1586,8 @@ void MapChunk::save(sExtendableArray& lADTFile
lADTFile.Extend(static_cast<long>(8 + lMCLY_Size));
SetChunkHeader(lADTFile, lCurrentPosition, 'MCLY', static_cast<int>(lMCLY_Size));
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsLayer = lCurrentPosition - lMCNK_Position;
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nLayers = texture_set ? static_cast<std::uint32_t>(texture_set->num()) : 0;
header_ptr->ofsLayer = lCurrentPosition - lMCNK_Position;
header_ptr->nLayers = texture_set ? static_cast<std::uint32_t>(texture_set->num()) : 0;
std::vector<std::vector<uint8_t>> alphamaps;
@@ -1596,7 +1600,7 @@ void MapChunk::save(sExtendableArray& lADTFile
// MCLY data
for (size_t j = 0; j < texture_set->num(); ++j)
{
ENTRY_MCLY * lLayer = lADTFile.GetPointer<ENTRY_MCLY>(lCurrentPosition + 8 + 0x10 * static_cast<unsigned long>(j));
auto const lLayer = lADTFile.GetPointer<ENTRY_MCLY>(lCurrentPosition + 8 + 0x10 * static_cast<unsigned long>(j));
lLayer->textureID = lTextures.find(texture_set->filename(j))->second;
lLayer->flags = texture_set->flag(j);
@@ -1659,12 +1663,12 @@ void MapChunk::save(sExtendableArray& lADTFile
lADTFile.Extend(8 + lMCRF_Size);
SetChunkHeader(lADTFile, lCurrentPosition, 'MCRF', lMCRF_Size);
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsRefs = lCurrentPosition - lMCNK_Position;
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nDoodadRefs = static_cast<std::uint32_t>(lDoodadIDs.size());
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nMapObjRefs = static_cast<std::uint32_t>(lObjectIDs.size());
header_ptr->ofsRefs = lCurrentPosition - lMCNK_Position;
header_ptr->nDoodadRefs = static_cast<std::uint32_t>(lDoodadIDs.size());
header_ptr->nMapObjRefs = static_cast<std::uint32_t>(lObjectIDs.size());
// MCRF data
int *lReferences = lADTFile.GetPointer<int>(lCurrentPosition + 8);
auto const lReferences = lADTFile.GetPointer<int>(lCurrentPosition + 8);
lID = 0;
for (std::list<int>::iterator it = lDoodadIDs.begin(); it != lDoodadIDs.end(); ++it)
@@ -1692,13 +1696,13 @@ void MapChunk::save(sExtendableArray& lADTFile
lADTFile.Extend(8 + lMCSH_Size);
SetChunkHeader(lADTFile, lCurrentPosition, 'MCSH', lMCSH_Size);
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsShadow = lCurrentPosition - lMCNK_Position;
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->sizeShadow = 0x200;
header_ptr->ofsShadow = lCurrentPosition - lMCNK_Position;
header_ptr->sizeShadow = 0x200;
char * lLayer = lADTFile.GetPointer<char>(lCurrentPosition + 8);
auto const lLayer = lADTFile.GetPointer<char>(lCurrentPosition + 8);
auto shadow_map = compressed_shadow_map();
memcpy(lLayer, shadow_map.data(), 0x200);
memcpy(lLayer.get(), shadow_map.data(), 0x200);
lCurrentPosition += 8 + lMCSH_Size;
lMCNK_Size += 8 + lMCSH_Size;
@@ -1706,22 +1710,22 @@ void MapChunk::save(sExtendableArray& lADTFile
else
{
header_flags.flags.has_mcsh = 0;
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsShadow = 0;
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->sizeShadow = 0;
header_ptr->ofsShadow = 0;
header_ptr->sizeShadow = 0;
}
// MCAL
lADTFile.Extend(8 + lMCAL_Size);
SetChunkHeader(lADTFile, lCurrentPosition, 'MCAL', lMCAL_Size);
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsAlpha = lCurrentPosition - lMCNK_Position;
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->sizeAlpha = 8 + lMCAL_Size;
header_ptr->ofsAlpha = lCurrentPosition - lMCNK_Position;
header_ptr->sizeAlpha = 8 + lMCAL_Size;
char * lAlphaMaps = lADTFile.GetPointer<char>(lCurrentPosition + 8);
auto lAlphaMaps = lADTFile.GetPointer<char>(lCurrentPosition + 8);
for (auto& alpha : alphamaps)
{
memcpy(lAlphaMaps, alpha.data(), alpha.size());
memcpy(lAlphaMaps.get(), alpha.data(), alpha.size());
lAlphaMaps += alpha.size();
}
@@ -1737,14 +1741,14 @@ void MapChunk::save(sExtendableArray& lADTFile
lADTFile.Extend(8 + lMCSE_Size);
SetChunkHeader(lADTFile, lCurrentPosition, 'MCSE', lMCSE_Size);
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsSndEmitters = lCurrentPosition - lMCNK_Position;
lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nSndEmitters = lMCSE_Size / 0x1C;
header_ptr->ofsSndEmitters = lCurrentPosition - lMCNK_Position;
header_ptr->nSndEmitters = lMCSE_Size / 0x1C;
lCurrentPosition += 8;
for (auto& sound_emitter : sound_emitters)
{
ENTRY_MCSE* MCSE = lADTFile.GetPointer<ENTRY_MCSE>(lCurrentPosition);
auto const MCSE = lADTFile.GetPointer<ENTRY_MCSE>(lCurrentPosition);
MCSE->soundId = sound_emitter.soundId;

View File

@@ -3,16 +3,19 @@
#pragma once
#include <noggit/map_enums.hpp>
#include <noggit/MapTile.h> // MapTile
#include <noggit/Misc.h>
#include <noggit/ModelInstance.h>
#include <noggit/Selection.h>
#include <noggit/TextureManager.h>
#include <noggit/WMOInstance.h>
#include <noggit/map_enums.hpp>
#include <noggit/texture_set.hpp>
#include <noggit/tool_enums.hpp>
#include <noggit/ContextObject.hpp>
#include <opengl/scoped.hpp>
#include <opengl/texture.hpp>
#include <noggit/Misc.h>
#include <util/sExtendableArray.hpp>
#include <optional>
#include <map>
#include <memory>
@@ -31,7 +34,6 @@ namespace math
}
class Brush;
class ChunkWater;
class sExtendableArray;
class QPixmap;
using StripType = uint16_t;
@@ -194,7 +196,7 @@ public:
void clearHeight();
//! \todo this is ugly create a build struct or sth
void save(sExtendableArray &lADTFile
void save(util::sExtendableArray &lADTFile
, int &lCurrentPosition
, int &lMCIN_Position
, std::map<std::string, int> &lTextures

View File

@@ -122,8 +122,8 @@ struct ENTRY_MODF
struct MapChunkHeader {
uint32_t flags = 0;
uint32_t ix;
uint32_t iy;
uint32_t ix = 0;
uint32_t iy = 0;
uint32_t nLayers = 0;
uint32_t nDoodadRefs = 0;
uint32_t ofsHeight = 0;
@@ -143,9 +143,9 @@ struct MapChunkHeader {
uint32_t nSndEmitters = 0;
uint32_t ofsLiquid = 0;
uint32_t sizeLiquid = 0;
float zpos;
float xpos;
float ypos;
float zpos = 0.0f;
float xpos = 0.0f;
float ypos = 0.0f;
uint32_t ofsMCCV = 0;
uint32_t unused1 = 0;
uint32_t unused2 = 0;

View File

@@ -18,6 +18,7 @@
#include <opengl/shader.hpp>
#include <external/tracy/Tracy.hpp>
#include <util/CurrentFunction.hpp>
#include <util/sExtendableArray.hpp>
#include <noggit/World.inl>
#include <QtCore/QSettings>
@@ -275,6 +276,8 @@ void MapTile::finishLoading()
assert(fourcc == 'MH2O');
Water.readFromFile(theFile, ofsW);
// Water.update_underground_vertices_depth();
}
// - MFBO ----------------------------------------------
@@ -633,7 +636,7 @@ void MapTile::saveTile(World* world)
texture.second = lID++;
// Now write the file.
sExtendableArray lADTFile;
util::sExtendableArray lADTFile;
int lCurrentPosition = 0;
@@ -709,7 +712,7 @@ void MapTile::saveTile(World* world)
// MMID data
// WMO model names
int * lMMID_Data = lADTFile.GetPointer<int>(lCurrentPosition + 8);
auto const lMMID_Data = lADTFile.GetPointer<int>(lCurrentPosition + 8);
lID = 0;
for (auto const& model : lModels)
@@ -744,7 +747,7 @@ void MapTile::saveTile(World* world)
lADTFile.GetPointer<MHDR>(lMHDR_Position + 8)->mwid = lCurrentPosition - 0x14;
// MWID data
int * lMWID_Data = lADTFile.GetPointer<int>(lCurrentPosition + 8);
auto const lMWID_Data = lADTFile.GetPointer<int>(lCurrentPosition + 8);
lID = 0;
for (auto const& object : lObjects)
@@ -759,7 +762,7 @@ void MapTile::saveTile(World* world)
lADTFile.GetPointer<MHDR>(lMHDR_Position + 8)->mddf = lCurrentPosition - 0x14;
// MDDF data
ENTRY_MDDF* lMDDF_Data = lADTFile.GetPointer<ENTRY_MDDF>(lCurrentPosition + 8);
auto const lMDDF_Data = lADTFile.GetPointer<ENTRY_MDDF>(lCurrentPosition + 8);
if(world->mapIndex.sort_models_by_size_class())
{
@@ -803,7 +806,7 @@ void MapTile::saveTile(World* world)
lADTFile.GetPointer<MHDR>(lMHDR_Position + 8)->modf = lCurrentPosition - 0x14;
// MODF data
ENTRY_MODF *lMODF_Data = lADTFile.GetPointer<ENTRY_MODF>(lCurrentPosition + 8);
auto const lMODF_Data = lADTFile.GetPointer<ENTRY_MODF>(lCurrentPosition + 8);
lID = 0;
for (auto const& object : lObjectInstances)
@@ -864,7 +867,7 @@ void MapTile::saveTile(World* world)
SetChunkHeader(lADTFile, lCurrentPosition, 'MFBO', static_cast<int>(chunkSize));
lADTFile.GetPointer<MHDR>(lMHDR_Position + 8)->mfbo = lCurrentPosition - 0x14;
int16_t *lMFBO_Data = lADTFile.GetPointer<int16_t>(lCurrentPosition + 8);
auto const lMFBO_Data = lADTFile.GetPointer<int16_t>(lCurrentPosition + 8);
lID = 0;
@@ -883,9 +886,9 @@ void MapTile::saveTile(World* world)
//! \todo check if nTexEffects == nTextures, correct order etc.
lADTFile.Extend(8 + 4 * mTextureEffects.size());
SetChunkHeader(lADTFile, lCurrentPosition, 'MTFX', 4 * mTextureEffects.size());
lADTFile.GetPointer<MHDR>(lMHDR_Position + 8)->mtfx = lCurrentPosition - 0x14;
lADTFile.GetPointer<MHDR>(lMHDR_Position + 8)->mtxf = lCurrentPosition - 0x14;
uint32_t* lMTFX_Data = lADTFile.GetPointer<uint32_t>(lCurrentPosition + 8);
auto const lMTFX_Data = lADTFile.GetPointer<uint32_t>(lCurrentPosition + 8);
lID = 0;
//they should be in the correct order...
@@ -898,13 +901,12 @@ void MapTile::saveTile(World* world)
}
#endif
lADTFile.Extend(static_cast<long>(lCurrentPosition - lADTFile.data.size())); // cleaning unused nulls at the end of file
{
BlizzardArchive::ClientFile f(_file_key.filepath(), Noggit::Application::NoggitApplication::instance()->clientData()
, BlizzardArchive::ClientFile::NEW_FILE);
f.setBuffer(lADTFile.data);
// \todo This sounds wrong. There shouldn't *be* unused nulls to
// begin with.
f.setBuffer(lADTFile.data_up_to(lCurrentPosition)); // cleaning unused nulls at the end of file
f.save();
}

View File

@@ -208,9 +208,9 @@ namespace misc
}
}
void SetChunkHeader(sExtendableArray& pArray, int pPosition, int pMagix, int pSize)
void SetChunkHeader(util::sExtendableArray& pArray, int pPosition, int pMagix, int pSize)
{
sChunkHeader* Header = pArray.GetPointer<sChunkHeader>(pPosition);
auto const Header = pArray.GetPointer<sChunkHeader>(pPosition);
Header->mMagic = pMagix;
Header->mSize = pSize;
}

View File

@@ -13,6 +13,7 @@
#include <glm/vec4.hpp>
#include <glm/vec2.hpp>
#include <noggit/Selection.h>
#include <util/sExtendableArray.hpp>
// namespace for static helper functions.
@@ -119,49 +120,11 @@ namespace misc
//! \todo collect all lose functions/classes/structs for now, sort them later
class sExtendableArray
{
public:
std::vector<char> data;
void Allocate (unsigned long pSize)
{
data.resize (pSize);
}
void Extend (long pAddition)
{
data.resize (data.size() + pAddition);
}
void Insert (unsigned long pPosition, unsigned long pAddition)
{
std::vector<char> tmp (pAddition);
data.insert (data.begin() + pPosition, tmp.begin(), tmp.end());
}
void Insert (unsigned long pPosition, unsigned long pAddition, const char * pAdditionalData)
{
data.insert (data.begin() + pPosition, pAdditionalData, pAdditionalData + pAddition);
}
template<typename To>
To * GetPointer(unsigned long pPosition = 0)
{
return(reinterpret_cast<To*>(data.data() + pPosition));
}
sExtendableArray() = default;
sExtendableArray(unsigned long pSize, const char *pData)
: data (pData, pData + pSize)
{}
};
struct sChunkHeader
{
int mMagic;
int mSize;
};
void SetChunkHeader(sExtendableArray& pArray, int pPosition, int pMagix, int pSize = 0);
void SetChunkHeader(util::sExtendableArray& pArray, int pPosition, int pMagix, int pSize = 0);

View File

@@ -59,7 +59,20 @@ void TileWater::autoGen(float factor)
}
}
void TileWater::saveToFile(sExtendableArray &lADTFile, int &lMHDR_Position, int &lCurrentPosition)
void TileWater::update_underground_vertices_depth()
{
tagUpdate();
for (int z = 0; z < 16; ++z)
{
for (int x = 0; x < 16; ++x)
{
chunks[z][x]->update_underground_vertices_depth(tile->getChunk(x, z));
}
}
}
void TileWater::saveToFile(util::sExtendableArray &lADTFile, int &lMHDR_Position, int &lCurrentPosition)
{
if (!hasData(0))
{

View File

@@ -7,6 +7,7 @@
#include <opengl/types.hpp>
#include <noggit/rendering/LiquidTextureManager.hpp>
#include <noggit/rendering/LiquidRender.hpp>
#include <util/sExtendableArray.hpp>
#include <memory>
#include <vector>
@@ -15,7 +16,6 @@
class MapTile;
class liquid_layer;
class sExtendableArray;
enum LiquidLayerUpdateFlags;
namespace BlizzardArchive
@@ -39,7 +39,7 @@ public:
ChunkWater* getChunk(int x, int z);
void readFromFile(BlizzardArchive::ClientFile& theFile, size_t basePos);
void saveToFile(sExtendableArray& lADTFile, int& lMHDR_Position, int& lCurrentPosition);
void saveToFile(util::sExtendableArray& lADTFile, int& lMHDR_Position, int& lCurrentPosition);
void draw ( math::frustum const& frustum
, const glm::vec3& camera

View File

@@ -261,7 +261,7 @@ void liquid_layer::create_vertices(float height)
}
}
void liquid_layer::save(sExtendableArray& adt, int base_pos, int& info_pos, int& current_pos) const
void liquid_layer::save(util::sExtendableArray& adt, int base_pos, int& info_pos, int& current_pos) const
{
int min_x = 9, min_z = 9, max_x = 0, max_z = 0;
bool filled = true;
@@ -334,7 +334,7 @@ void liquid_layer::save(sExtendableArray& adt, int base_pos, int& info_pos, int&
{
for (int x = info.xOffset; x <= info.xOffset + info.width; ++x)
{
memcpy(adt.GetPointer<char>(current_pos), &_vertices[z * 9 + x].position.y, sizeof(float));
memcpy(adt.GetPointer<char>(current_pos).get(), &_vertices[z * 9 + x].position.y, sizeof(float));
current_pos += sizeof(float);
}
}
@@ -357,7 +357,7 @@ void liquid_layer::save(sExtendableArray& adt, int base_pos, int& info_pos, int&
uv.x = static_cast<std::uint16_t>(std::min(_vertices[z * 9 + x].uv.x * 255.f, 65535.f));
uv.y = static_cast<std::uint16_t>(std::min(_vertices[z * 9 + x].uv.y * 255.f, 65535.f));
memcpy(adt.GetPointer<char>(current_pos), &uv, sizeof(mh2o_uv));
memcpy(adt.GetPointer<char>(current_pos).get(), &uv, sizeof(mh2o_uv));
current_pos += sizeof(mh2o_uv);
}
}
@@ -372,13 +372,13 @@ void liquid_layer::save(sExtendableArray& adt, int base_pos, int& info_pos, int&
for (int x = info.xOffset; x <= info.xOffset + info.width; ++x)
{
std::uint8_t depth = static_cast<std::uint8_t>(std::min(_vertices[z * 9 + x].depth * 255.0f, 255.f));
memcpy(adt.GetPointer<char>(current_pos), &depth, sizeof(std::uint8_t));
memcpy(adt.GetPointer<char>(current_pos).get(), &depth, sizeof(std::uint8_t));
current_pos += sizeof(std::uint8_t);
}
}
}
memcpy(adt.GetPointer<char>(info_pos), &info, sizeof(MH2O_Information));
memcpy(adt.GetPointer<char>(info_pos).get(), &info, sizeof(MH2O_Information));
info_pos += sizeof(MH2O_Information);
}

View File

@@ -7,9 +7,9 @@
#include <opengl/scoped.hpp>
#include <array>
#include <glm/vec2.hpp>
#include <util/sExtendableArray.hpp>
class MapChunk;
class sExtendableArray;
class ChunkWater;
enum LiquidLayerUpdateFlags
@@ -59,7 +59,7 @@ public:
liquid_layer& operator=(liquid_layer&&);
liquid_layer& operator=(liquid_layer const& other);
void save(sExtendableArray& adt, int base_pos, int& info_pos, int& current_pos) const;
void save(util::sExtendableArray& adt, int base_pos, int& info_pos, int& current_pos) const;
void update_attributes(MH2O_Attributes& attributes);
void changeLiquidID(int id);

View File

@@ -365,7 +365,7 @@ void map_horizon::save_wdl(World* world, bool regenerate)
filename << "World\\Maps\\" << world->basename << "\\" << world->basename << ".wdl";
//Log << "Saving WDL \"" << filename << "\"." << std::endl;
sExtendableArray wdlFile = sExtendableArray();
util::sExtendableArray wdlFile;
int curPos = 0;
// MVER
@@ -475,7 +475,7 @@ void map_horizon::save_wdl(World* world, bool regenerate)
}
BlizzardArchive::ClientFile f(filename.str(), Noggit::Application::NoggitApplication::instance()->clientData(),
BlizzardArchive::ClientFile::NEW_FILE);
f.setBuffer(wdlFile.data);
f.setBuffer(wdlFile.all_data());
f.save();
f.close();

View File

@@ -190,7 +190,7 @@ void MapIndex::save()
//Log << "Saving WDT \"" << filename << "\"." << std::endl;
sExtendableArray wdtFile = sExtendableArray();
util::sExtendableArray wdtFile;
int curPos = 0;
// MVER
@@ -266,7 +266,7 @@ void MapIndex::save()
BlizzardArchive::ClientFile f(filename.str(), Noggit::Application::NoggitApplication::instance()->clientData(),
BlizzardArchive::ClientFile::NEW_FILE);
f.setBuffer(wdtFile.data);
f.setBuffer(wdtFile.all_data());
f.save();
f.close();
@@ -1240,7 +1240,7 @@ void MapIndex::create_empty_wdl() const
filename << "World\\Maps\\" << basename << "\\" << basename << ".wdl"; // mapIndex.basename ?
//Log << "Saving WDL \"" << filename << "\"." << std::endl;
sExtendableArray wdlFile = sExtendableArray();
util::sExtendableArray wdlFile;
int curPos = 0;
// MVER
@@ -1340,7 +1340,7 @@ void MapIndex::create_empty_wdl() const
BlizzardArchive::ClientFile f(filename.str(), Noggit::Application::NoggitApplication::instance()->clientData(),
BlizzardArchive::ClientFile::NEW_FILE);
f.setBuffer(wdlFile.data);
f.setBuffer(wdlFile.all_data());
f.save();
f.close();
}

View File

@@ -0,0 +1,35 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <util/sExtendableArray.hpp>
namespace util
{
void sExtendableArray::Extend (long pAddition)
{
data.resize (data.size() + pAddition);
}
void sExtendableArray::Insert (unsigned long pPosition, unsigned long pAddition)
{
std::vector<char> tmp (pAddition);
data.insert (data.begin() + pPosition, tmp.begin(), tmp.end());
}
void sExtendableArray::Insert (unsigned long pPosition, unsigned long pAddition, const char * pAdditionalData)
{
data.insert (data.begin() + pPosition, pAdditionalData, pAdditionalData + pAddition);
}
std::vector<char> sExtendableArray::all_data() const
{
return data_up_to (data.size());
}
std::vector<char> sExtendableArray::data_up_to (std::size_t position) const
{
return std::vector<char> (data.begin(), data.begin() + position);
}
sExtendableArray::sExtendableArray(unsigned long pSize, const char *pData)
: data (pData, pData + pSize)
{}
}

View File

@@ -0,0 +1,52 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <vector>
namespace util
{
//! \todo This name is horrible. The API is mediocre.
class sExtendableArray
{
std::vector<char> data;
public:
//! Equivalent to `Allocate ($size + pAddition)`.
void Extend (long pAddition);
//! At \a pPosition, insert \a pAddition bytes that are all '\0',
//! moving existing data further back.
void Insert (unsigned long pPosition, unsigned long pAddition);
//! At \a pPosition, insert \a pAddition bytes with the data at \a
//! pAdditionalData, moving existing data further back.
void Insert (unsigned long pPosition, unsigned long pAddition, const char * pAdditionalData);
template<typename T>
struct LazyPointer
{
LazyPointer (std::vector<char>& data, std::size_t position);
T* get() const;
T& operator*() const;
T* operator->() const;
T& operator[] (std::size_t) const;
LazyPointer<T>& operator+= (std::size_t);
private:
std::vector<char>& _data;
std::size_t _position;
};
template<typename To>
LazyPointer<To> GetPointer(unsigned long pPosition = 0);
std::vector<char> all_data() const;
std::vector<char> data_up_to (std::size_t position) const;
sExtendableArray() = default;
sExtendableArray(unsigned long pSize, const char *pData);
};
}
#include <util/sExtendableArray.ipp>

View File

@@ -0,0 +1,47 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
namespace util
{
template<typename To>
sExtendableArray::LazyPointer<To> sExtendableArray::GetPointer
(unsigned long pPosition)
{
return {data, pPosition};
}
template<typename T>
sExtendableArray::LazyPointer<T>::LazyPointer
(std::vector<char>& data, std::size_t position)
: _data (data)
, _position (position)
{}
template<typename T>
T* sExtendableArray::LazyPointer<T>::get() const
{
return reinterpret_cast<T*> (_data.data() + _position);
}
template<typename T>
T& sExtendableArray::LazyPointer<T>::operator*() const
{
return *get();
}
template<typename T>
T* sExtendableArray::LazyPointer<T>::operator->() const
{
return get();
}
template<typename T>
T& sExtendableArray::LazyPointer<T>::operator[] (std::size_t i) const
{
return *(get() + i);
}
template<typename T>
sExtendableArray::LazyPointer<T>&
sExtendableArray::LazyPointer<T>::operator+= (std::size_t num)
{
_position += num * sizeof (T);
return *this;
}
}