mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
ZoneFileLog keeps the .luz, .lvl, .lutriggers, terrain .raw and navmesh a world read while loading its zone: absolute path of the loose file (or the name in the pack), size and an FNV-1a hash of the bytes read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
119 lines
2.9 KiB
C++
119 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include <filesystem>
|
|
#include <optional>
|
|
#include <string_view>
|
|
|
|
#include "Pack.h"
|
|
#include "PackIndex.h"
|
|
|
|
enum class eAssetBundleType {
|
|
None,
|
|
Unpacked,
|
|
Packed
|
|
};
|
|
|
|
struct AssetMemoryBuffer : std::streambuf {
|
|
char* m_Base;
|
|
bool m_Success;
|
|
|
|
AssetMemoryBuffer(char* base, std::ptrdiff_t n, bool success) {
|
|
m_Base = base;
|
|
m_Success = success;
|
|
if (!m_Success) return;
|
|
this->setg(base, base, base + n);
|
|
}
|
|
|
|
~AssetMemoryBuffer() {
|
|
if (m_Success) free(m_Base);
|
|
}
|
|
|
|
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
|
|
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
|
|
}
|
|
|
|
pos_type seekoff(off_type off,
|
|
std::ios_base::seekdir dir,
|
|
std::ios_base::openmode which = std::ios_base::in) override {
|
|
if (dir == std::ios_base::cur)
|
|
gbump(off);
|
|
else if (dir == std::ios_base::end)
|
|
setg(eback(), egptr() + off, egptr());
|
|
else if (dir == std::ios_base::beg)
|
|
setg(eback(), eback() + off, egptr());
|
|
return gptr() - eback();
|
|
}
|
|
|
|
// Every byte of the file (empty when it wasn't found)
|
|
std::string_view Bytes() const {
|
|
if (!m_Success) return {};
|
|
return std::string_view(eback(), static_cast<size_t>(egptr() - eback()));
|
|
}
|
|
};
|
|
|
|
struct AssetStream : std::istream {
|
|
AssetStream(char* base, std::ptrdiff_t n, bool success) : std::istream(new AssetMemoryBuffer(base, n, success)) {}
|
|
|
|
~AssetStream() {
|
|
delete rdbuf();
|
|
}
|
|
|
|
operator bool() {
|
|
return reinterpret_cast<AssetMemoryBuffer*>(rdbuf())->m_Success;
|
|
}
|
|
|
|
// Every byte of the file, whatever has been read of it so far
|
|
std::string_view Bytes() const {
|
|
return reinterpret_cast<const AssetMemoryBuffer*>(rdbuf())->Bytes();
|
|
}
|
|
};
|
|
|
|
class AssetManager {
|
|
public:
|
|
AssetManager(const std::filesystem::path& path);
|
|
|
|
[[nodiscard]]
|
|
const std::filesystem::path& GetResPath() const {
|
|
return m_ResPath;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
eAssetBundleType GetAssetBundleType() const {
|
|
return m_AssetBundleType;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
bool HasFile(std::string name) const;
|
|
|
|
[[nodiscard]]
|
|
bool GetFile(std::string name, char** data, uint32_t* len) const;
|
|
|
|
// Where GetFile reads name from when it is a loose file in res; nullopt when it comes from a pack or isn't there
|
|
[[nodiscard]]
|
|
std::optional<std::filesystem::path> GetLoosePath(std::string name) const;
|
|
|
|
[[nodiscard]]
|
|
AssetStream GetFile(const char* name) const;
|
|
|
|
[[nodiscard]]
|
|
AssetStream GetFile(const std::string& name) const { return GetFile(name.c_str()); };
|
|
|
|
private:
|
|
void LoadPackIndex();
|
|
|
|
// Modified crc algorithm (mpeg2)
|
|
// Reference: https://stackoverflow.com/questions/54339800/how-to-modify-crc-32-to-crc-32-mpeg-2
|
|
static inline uint32_t crc32b(uint32_t crc, std::string_view message);
|
|
|
|
std::filesystem::path m_Path;
|
|
std::filesystem::path m_RootPath;
|
|
std::filesystem::path m_ResPath;
|
|
|
|
eAssetBundleType m_AssetBundleType = eAssetBundleType::None;
|
|
|
|
std::optional<PackIndex> m_PackIndex;
|
|
};
|