mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-10 23:08:05 -05:00
Rename ZoneLoader and ZoneWriter components to ZoneLoading and ZoneWriting to make a difference between the executive class and the component class
This commit is contained in:
53
src/ZoneLoading/Loading/AssetLoader.cpp
Normal file
53
src/ZoneLoading/Loading/AssetLoader.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "AssetLoader.h"
|
||||
|
||||
AssetLoader::AssetLoader(const asset_type_t assetType, IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream)
|
||||
{
|
||||
m_asset_type = assetType;
|
||||
m_script_string_provider = scriptStringProvider;
|
||||
m_zone = zone;
|
||||
m_stream = stream;
|
||||
}
|
||||
|
||||
void AssetLoader::AddDependency(const asset_type_t type, std::string& name)
|
||||
{
|
||||
for(auto& existingDependency : m_dependencies)
|
||||
{
|
||||
if(existingDependency.m_type == type
|
||||
&& existingDependency.m_name == name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
XAssetDependency dependency;
|
||||
dependency.m_type = type;
|
||||
dependency.m_name = name;
|
||||
|
||||
m_dependencies.push_back(dependency);
|
||||
}
|
||||
|
||||
scr_string_t AssetLoader::UseScriptString(const scr_string_t scrString)
|
||||
{
|
||||
std::string& scrStringValue = m_script_string_provider->GetZoneScriptString(scrString);
|
||||
|
||||
scr_string_t scriptStringIndex = 0;
|
||||
for(auto& existingScriptString : m_used_script_strings)
|
||||
{
|
||||
if(existingScriptString == scrStringValue)
|
||||
{
|
||||
return scriptStringIndex;
|
||||
}
|
||||
|
||||
scriptStringIndex++;
|
||||
}
|
||||
|
||||
scriptStringIndex = static_cast<scr_string_t>(m_used_script_strings.size());
|
||||
m_used_script_strings.push_back(scrStringValue);
|
||||
|
||||
return scriptStringIndex;
|
||||
}
|
||||
|
||||
void* AssetLoader::LinkAsset(std::string name, void* asset)
|
||||
{
|
||||
return m_zone->GetPools()->AddAsset(m_asset_type, std::move(name), asset, m_used_script_strings, m_dependencies);
|
||||
}
|
22
src/ZoneLoading/Loading/AssetLoader.h
Normal file
22
src/ZoneLoading/Loading/AssetLoader.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "ContentLoader.h"
|
||||
#include "IZoneScriptStringProvider.h"
|
||||
#include "Zone/XAssetDependency.h"
|
||||
|
||||
class AssetLoader : public ContentLoader
|
||||
{
|
||||
asset_type_t m_asset_type;
|
||||
|
||||
IZoneScriptStringProvider* m_script_string_provider;
|
||||
std::vector<std::string> m_used_script_strings;
|
||||
|
||||
std::vector<XAssetDependency> m_dependencies;
|
||||
|
||||
protected:
|
||||
AssetLoader(asset_type_t assetType, IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream);
|
||||
|
||||
void AddDependency(asset_type_t type, std::string& name);
|
||||
scr_string_t UseScriptString(scr_string_t scrString);
|
||||
|
||||
void* LinkAsset(std::string name, void* asset);
|
||||
};
|
42
src/ZoneLoading/Loading/ContentLoader.cpp
Normal file
42
src/ZoneLoading/Loading/ContentLoader.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "ContentLoader.h"
|
||||
#include <cassert>
|
||||
|
||||
const void* ContentLoader::PTR_FOLLOWING = reinterpret_cast<void*>(-1);
|
||||
const void* ContentLoader::PTR_INSERT = reinterpret_cast<void*>(-2);
|
||||
|
||||
ContentLoader::ContentLoader()
|
||||
{
|
||||
m_zone = nullptr;
|
||||
m_stream = nullptr;
|
||||
}
|
||||
|
||||
void ContentLoader::LoadXString(const char** pXString) const
|
||||
{
|
||||
assert(pXString != nullptr);
|
||||
|
||||
if(*pXString != nullptr)
|
||||
{
|
||||
if(*pXString == PTR_FOLLOWING)
|
||||
{
|
||||
*pXString = m_stream->Alloc<const char>();
|
||||
m_stream->LoadNullTerminated();
|
||||
}
|
||||
else
|
||||
{
|
||||
*pXString = m_stream->ConvertOffsetToPointer<const char>(*pXString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContentLoader::LoadXStringArray(const char** pArray, const size_t count, const bool atStreamStart) const
|
||||
{
|
||||
assert(pArray != nullptr);
|
||||
|
||||
if(atStreamStart)
|
||||
m_stream->Load<const char*>(count);
|
||||
|
||||
for(size_t index = 0; index < count; index++)
|
||||
{
|
||||
LoadXString(&pArray[index]);
|
||||
}
|
||||
}
|
22
src/ZoneLoading/Loading/ContentLoader.h
Normal file
22
src/ZoneLoading/Loading/ContentLoader.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/Stream/IZoneInputStream.h"
|
||||
|
||||
class ContentLoader
|
||||
{
|
||||
protected:
|
||||
static const void* PTR_FOLLOWING;
|
||||
static const void* PTR_INSERT;
|
||||
|
||||
Zone* m_zone;
|
||||
IZoneInputStream* m_stream;
|
||||
|
||||
ContentLoader();
|
||||
|
||||
void LoadXString(const char** pXString) const;
|
||||
void LoadXStringArray(const char** pArray, size_t count, bool atStreamStart) const;
|
||||
|
||||
public:
|
||||
virtual ~ContentLoader() = default;
|
||||
};
|
16
src/ZoneLoading/Loading/Exception/BlockOverflowException.cpp
Normal file
16
src/ZoneLoading/Loading/Exception/BlockOverflowException.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "BlockOverflowException.h"
|
||||
|
||||
BlockOverflowException::BlockOverflowException(XBlock* block)
|
||||
{
|
||||
m_block = block;
|
||||
}
|
||||
|
||||
std::string BlockOverflowException::DetailedMessage()
|
||||
{
|
||||
return "XBlock " + m_block->m_name + " overflowed while trying to load zone.";
|
||||
}
|
||||
|
||||
char const* BlockOverflowException::what() const
|
||||
{
|
||||
return "Invalid Zone. XBlock overflowed.";
|
||||
}
|
14
src/ZoneLoading/Loading/Exception/BlockOverflowException.h
Normal file
14
src/ZoneLoading/Loading/Exception/BlockOverflowException.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
#include "Zone/XBlock.h"
|
||||
|
||||
class BlockOverflowException final : public LoadingException
|
||||
{
|
||||
XBlock* m_block;
|
||||
|
||||
public:
|
||||
explicit BlockOverflowException(XBlock* block);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
#include "InvalidChunkSizeException.h"
|
||||
|
||||
InvalidChunkSizeException::InvalidChunkSizeException(const size_t size)
|
||||
{
|
||||
m_size = size;
|
||||
m_max = 0;
|
||||
}
|
||||
|
||||
InvalidChunkSizeException::InvalidChunkSizeException(const size_t size, const size_t max)
|
||||
{
|
||||
m_size = size;
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
std::string InvalidChunkSizeException::DetailedMessage()
|
||||
{
|
||||
if(m_max > 0)
|
||||
{
|
||||
return "Zone chunk size has a chunk size of " + std::to_string(m_size) + " which is larger than the maximum of " + std::to_string(m_max);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Zone chunk size has an invalid chunk size of " + std::to_string(m_size);
|
||||
}
|
||||
}
|
||||
|
||||
char const* InvalidChunkSizeException::what() const
|
||||
{
|
||||
return "Zone has invalid chunk size";
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class InvalidChunkSizeException final : public LoadingException
|
||||
{
|
||||
size_t m_size;
|
||||
size_t m_max;
|
||||
|
||||
public:
|
||||
explicit InvalidChunkSizeException(size_t size);
|
||||
InvalidChunkSizeException(size_t size, size_t max);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
#include "InvalidCompressionException.h"
|
||||
|
||||
std::string InvalidCompressionException::DetailedMessage()
|
||||
{
|
||||
return "Zone has invalid or unsupported compression. Inflate failed";
|
||||
}
|
||||
|
||||
char const* InvalidCompressionException::what() const
|
||||
{
|
||||
return "Zone has invalid or unsupported compression. Inflate failed";
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class InvalidCompressionException final : public LoadingException
|
||||
{
|
||||
public:
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
#include "InvalidFileNameException.h"
|
||||
|
||||
InvalidFileNameException::InvalidFileNameException(std::string& actualFileName, std::string& expectedFileName)
|
||||
{
|
||||
m_actual_file_name = actualFileName;
|
||||
m_expected_file_name = expectedFileName;
|
||||
}
|
||||
|
||||
std::string InvalidFileNameException::DetailedMessage()
|
||||
{
|
||||
return "Name verification failed: The fastfile was created as '" + m_expected_file_name + "' but loaded as '" + m_actual_file_name + "'";
|
||||
}
|
||||
|
||||
char const* InvalidFileNameException::what() const
|
||||
{
|
||||
return "The filename when created and when loaded does not match";
|
||||
}
|
14
src/ZoneLoading/Loading/Exception/InvalidFileNameException.h
Normal file
14
src/ZoneLoading/Loading/Exception/InvalidFileNameException.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class InvalidFileNameException final : public LoadingException
|
||||
{
|
||||
std::string m_actual_file_name;
|
||||
std::string m_expected_file_name;
|
||||
|
||||
public:
|
||||
InvalidFileNameException(std::string& actualFileName, std::string& expectedFileName);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
16
src/ZoneLoading/Loading/Exception/InvalidMagicException.cpp
Normal file
16
src/ZoneLoading/Loading/Exception/InvalidMagicException.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "InvalidMagicException.h"
|
||||
|
||||
InvalidMagicException::InvalidMagicException(const char* expectedMagic)
|
||||
{
|
||||
m_expected_magic = expectedMagic;
|
||||
}
|
||||
|
||||
std::string InvalidMagicException::DetailedMessage()
|
||||
{
|
||||
return "Expected magic '" + std::string(m_expected_magic) + "'";
|
||||
}
|
||||
|
||||
char const* InvalidMagicException::what() const
|
||||
{
|
||||
return "Encountered invalid magic when loading.";
|
||||
}
|
13
src/ZoneLoading/Loading/Exception/InvalidMagicException.h
Normal file
13
src/ZoneLoading/Loading/Exception/InvalidMagicException.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class InvalidMagicException final : public LoadingException
|
||||
{
|
||||
const char* m_expected_magic;
|
||||
|
||||
public:
|
||||
explicit InvalidMagicException(const char* expectedMagic);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
#include "InvalidOffsetBlockException.h"
|
||||
|
||||
InvalidOffsetBlockException::InvalidOffsetBlockException(const block_t referencedBlock)
|
||||
{
|
||||
m_referenced_block = referencedBlock;
|
||||
}
|
||||
|
||||
std::string InvalidOffsetBlockException::DetailedMessage()
|
||||
{
|
||||
return "Zone tried to reference invalid block " + std::to_string(m_referenced_block);
|
||||
}
|
||||
|
||||
char const* InvalidOffsetBlockException::what() const
|
||||
{
|
||||
return "Zone referenced invalid block";
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
#include "Zone/ZoneTypes.h"
|
||||
|
||||
class InvalidOffsetBlockException final : public LoadingException
|
||||
{
|
||||
block_t m_referenced_block;
|
||||
|
||||
public:
|
||||
explicit InvalidOffsetBlockException(block_t referencedBlock);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
#include "InvalidOffsetBlockOffsetException.h"
|
||||
|
||||
InvalidOffsetBlockOffsetException::InvalidOffsetBlockOffsetException(XBlock* block, const size_t referencedOffset)
|
||||
{
|
||||
m_referenced_block = block;
|
||||
m_referenced_offset = referencedOffset;
|
||||
}
|
||||
|
||||
std::string InvalidOffsetBlockOffsetException::DetailedMessage()
|
||||
{
|
||||
return "Zone referenced offset" + std::to_string(m_referenced_offset) + " of block " + m_referenced_block->m_name
|
||||
+ " which is larger than its size " + std::to_string(m_referenced_block->m_buffer_size);
|
||||
}
|
||||
|
||||
char const* InvalidOffsetBlockOffsetException::what() const
|
||||
{
|
||||
return "Zone referenced offset of block that is out of bounds";
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
#include "Zone/XBlock.h"
|
||||
|
||||
class InvalidOffsetBlockOffsetException final : public LoadingException
|
||||
{
|
||||
XBlock* m_referenced_block;
|
||||
size_t m_referenced_offset;
|
||||
|
||||
public:
|
||||
InvalidOffsetBlockOffsetException(XBlock* block, size_t referencedOffset);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
#include "InvalidSignatureException.h"
|
||||
|
||||
std::string InvalidSignatureException::DetailedMessage()
|
||||
{
|
||||
return "Loaded fastfile has an invalid signature.";
|
||||
}
|
||||
|
||||
char const* InvalidSignatureException::what() const
|
||||
{
|
||||
return "Loaded fastfile has an invalid signature.";
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class InvalidSignatureException final : public LoadingException
|
||||
{
|
||||
public:
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
#include "InvalidVersionException.h"
|
||||
|
||||
InvalidVersionException::InvalidVersionException(const unsigned int expectedVersion, const unsigned int actualVersion)
|
||||
{
|
||||
m_expected_version = expectedVersion;
|
||||
m_actual_version = actualVersion;
|
||||
}
|
||||
|
||||
std::string InvalidVersionException::DetailedMessage()
|
||||
{
|
||||
return "Expected version " + std::to_string(m_expected_version) + " but encountered version " + std::to_string(m_actual_version);
|
||||
}
|
||||
|
||||
char const* InvalidVersionException::what() const
|
||||
{
|
||||
return "Encountered invalid version when loading.";
|
||||
}
|
14
src/ZoneLoading/Loading/Exception/InvalidVersionException.h
Normal file
14
src/ZoneLoading/Loading/Exception/InvalidVersionException.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class InvalidVersionException final : public LoadingException
|
||||
{
|
||||
unsigned int m_expected_version;
|
||||
unsigned int m_actual_version;
|
||||
|
||||
public:
|
||||
InvalidVersionException(unsigned int expectedVersion, unsigned int actualVersion);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
#include "InvalidXBlockSizeException.h"
|
||||
|
||||
InvalidXBlockSizeException::InvalidXBlockSizeException(const uint64_t size, const uint64_t max)
|
||||
{
|
||||
m_size = size;
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
std::string InvalidXBlockSizeException::DetailedMessage()
|
||||
{
|
||||
return "Zone uses more XBlock memory than allowed: " + std::to_string(m_size) + " (max is " + std::to_string(m_max) + ")";
|
||||
}
|
||||
|
||||
char const* InvalidXBlockSizeException::what() const
|
||||
{
|
||||
return "Zone has invalid block size";
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class InvalidXBlockSizeException final : public LoadingException
|
||||
{
|
||||
uint64_t m_size;
|
||||
uint64_t m_max;
|
||||
|
||||
public:
|
||||
InvalidXBlockSizeException(uint64_t size, uint64_t max);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
9
src/ZoneLoading/Loading/Exception/LoadingException.h
Normal file
9
src/ZoneLoading/Loading/Exception/LoadingException.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
class LoadingException : public std::exception
|
||||
{
|
||||
public:
|
||||
virtual std::string DetailedMessage() = 0;
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
#include "UnexpectedEndOfFileException.h"
|
||||
|
||||
UnexpectedEndOfFileException::UnexpectedEndOfFileException() = default;
|
||||
|
||||
std::string UnexpectedEndOfFileException::DetailedMessage()
|
||||
{
|
||||
return "Unexpected end of file";
|
||||
}
|
||||
|
||||
char const* UnexpectedEndOfFileException::what() const
|
||||
{
|
||||
return "Unexpected end of file";
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class UnexpectedEndOfFileException final : public LoadingException
|
||||
{
|
||||
public:
|
||||
UnexpectedEndOfFileException();
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
#include "UnsupportedAssetTypeException.h"
|
||||
|
||||
UnsupportedAssetTypeException::UnsupportedAssetTypeException(const int assetType)
|
||||
{
|
||||
m_asset_type = assetType;
|
||||
}
|
||||
|
||||
std::string UnsupportedAssetTypeException::DetailedMessage()
|
||||
{
|
||||
return "Zone has an unsupported asset type " + std::to_string(m_asset_type) + " and therefore cannot be loaded.";
|
||||
}
|
||||
|
||||
char const* UnsupportedAssetTypeException::what() const
|
||||
{
|
||||
return "Zone has unsupported asset type.";
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "LoadingException.h"
|
||||
|
||||
class UnsupportedAssetTypeException final : public LoadingException
|
||||
{
|
||||
int m_asset_type;
|
||||
|
||||
public:
|
||||
explicit UnsupportedAssetTypeException(int assetType);
|
||||
|
||||
std::string DetailedMessage() override;
|
||||
char const* what() const override;
|
||||
};
|
12
src/ZoneLoading/Loading/IContentLoadingEntryPoint.h
Normal file
12
src/ZoneLoading/Loading/IContentLoadingEntryPoint.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/Stream/IZoneInputStream.h"
|
||||
|
||||
class IContentLoadingEntryPoint
|
||||
{
|
||||
public:
|
||||
virtual ~IContentLoadingEntryPoint() = default;
|
||||
|
||||
virtual void Load(Zone* zone, IZoneInputStream* stream) = 0;
|
||||
};
|
14
src/ZoneLoading/Loading/ILoadingStep.h
Normal file
14
src/ZoneLoading/Loading/ILoadingStep.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ZoneLoader.h"
|
||||
#include "ILoadingStream.h"
|
||||
|
||||
class ZoneLoader;
|
||||
|
||||
class ILoadingStep
|
||||
{
|
||||
public:
|
||||
virtual ~ILoadingStep() = default;
|
||||
|
||||
virtual void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) = 0;
|
||||
};
|
9
src/ZoneLoading/Loading/ILoadingStream.h
Normal file
9
src/ZoneLoading/Loading/ILoadingStream.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
class ILoadingStream
|
||||
{
|
||||
public:
|
||||
virtual ~ILoadingStream() = default;
|
||||
|
||||
virtual size_t Load(void* buffer, size_t length) = 0;
|
||||
};
|
8
src/ZoneLoading/Loading/ISignatureDataProvider.h
Normal file
8
src/ZoneLoading/Loading/ISignatureDataProvider.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
class ISignatureDataProvider
|
||||
{
|
||||
public:
|
||||
virtual void GetSignatureData(const uint8_t** pSignatureData, size_t* pSize) = 0;
|
||||
};
|
8
src/ZoneLoading/Loading/ISignatureProvider.h
Normal file
8
src/ZoneLoading/Loading/ISignatureProvider.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
class ISignatureProvider
|
||||
{
|
||||
public:
|
||||
virtual void GetSignature(const uint8_t** pSignature, size_t* pSize) = 0;
|
||||
};
|
12
src/ZoneLoading/Loading/IZoneLoaderFactory.h
Normal file
12
src/ZoneLoading/Loading/IZoneLoaderFactory.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/ZoneTypes.h"
|
||||
#include "ZoneLoader.h"
|
||||
|
||||
class IZoneLoaderFactory
|
||||
{
|
||||
public:
|
||||
virtual ~IZoneLoaderFactory() = default;
|
||||
|
||||
virtual ZoneLoader* CreateLoaderForHeader(ZoneHeader& header, std::string& fileName) = 0;
|
||||
};
|
10
src/ZoneLoading/Loading/IZoneScriptStringProvider.h
Normal file
10
src/ZoneLoading/Loading/IZoneScriptStringProvider.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/ZoneTypes.h"
|
||||
#include <string>
|
||||
|
||||
class IZoneScriptStringProvider
|
||||
{
|
||||
public:
|
||||
virtual std::string& GetZoneScriptString(scr_string_t scrString) = 0;
|
||||
};
|
11
src/ZoneLoading/Loading/LoadingFileStream.cpp
Normal file
11
src/ZoneLoading/Loading/LoadingFileStream.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "LoadingFileStream.h"
|
||||
|
||||
LoadingFileStream::LoadingFileStream(FileAPI::File* file)
|
||||
{
|
||||
m_file = file;
|
||||
}
|
||||
|
||||
size_t LoadingFileStream::Load(void* buffer, const size_t length)
|
||||
{
|
||||
return m_file->Read(buffer, 1, length);
|
||||
}
|
13
src/ZoneLoading/Loading/LoadingFileStream.h
Normal file
13
src/ZoneLoading/Loading/LoadingFileStream.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "ILoadingStream.h"
|
||||
#include "Utils/FileAPI.h"
|
||||
|
||||
class LoadingFileStream : public ILoadingStream
|
||||
{
|
||||
FileAPI::File* m_file;
|
||||
|
||||
public:
|
||||
explicit LoadingFileStream(FileAPI::File* file);
|
||||
|
||||
size_t Load(void* buffer, size_t length) override;
|
||||
};
|
73
src/ZoneLoading/Loading/Processor/ProcessorInflate.cpp
Normal file
73
src/ZoneLoading/Loading/Processor/ProcessorInflate.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "ProcessorInflate.h"
|
||||
#include "zlib.h"
|
||||
#include <exception>
|
||||
#include "zutil.h"
|
||||
#include <cstdint>
|
||||
|
||||
class ProcessorInflate::ProcessorInflateImpl
|
||||
{
|
||||
z_stream m_stream{};
|
||||
uint8_t m_in_buffer[0x800];
|
||||
ProcessorInflate* m_base;
|
||||
|
||||
public:
|
||||
ProcessorInflateImpl(ProcessorInflate* baseClass)
|
||||
{
|
||||
m_base = baseClass;
|
||||
|
||||
m_stream.zalloc = Z_NULL;
|
||||
m_stream.zfree = Z_NULL;
|
||||
m_stream.opaque = Z_NULL;
|
||||
m_stream.avail_in = 0;
|
||||
m_stream.next_in = Z_NULL;
|
||||
|
||||
const int ret = inflateInit2(&m_stream, -DEF_WBITS);
|
||||
|
||||
if(ret != Z_OK)
|
||||
{
|
||||
throw std::exception("Initializing inflate failed");
|
||||
}
|
||||
}
|
||||
|
||||
~ProcessorInflateImpl()
|
||||
{
|
||||
inflateEnd(&m_stream);
|
||||
}
|
||||
|
||||
size_t Load(void* buffer, size_t length)
|
||||
{
|
||||
m_stream.next_out = static_cast<Bytef*>(buffer);
|
||||
m_stream.avail_out = length;
|
||||
|
||||
while(m_stream.avail_out > 0)
|
||||
{
|
||||
if(m_stream.avail_in == 0)
|
||||
{
|
||||
m_stream.avail_in = m_base->m_base_stream->Load(m_in_buffer, sizeof(m_in_buffer));
|
||||
|
||||
if(m_stream.avail_in == 0) // EOF
|
||||
return length - m_stream.avail_out;
|
||||
}
|
||||
|
||||
inflate(&m_stream, Z_FULL_FLUSH);
|
||||
}
|
||||
|
||||
return m_stream.avail_out;
|
||||
}
|
||||
};
|
||||
|
||||
ProcessorInflate::ProcessorInflate()
|
||||
{
|
||||
m_impl = new ProcessorInflateImpl(this);
|
||||
}
|
||||
|
||||
ProcessorInflate::~ProcessorInflate()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
size_t ProcessorInflate::Load(void* buffer, const size_t length)
|
||||
{
|
||||
return m_impl->Load(buffer, length);
|
||||
}
|
14
src/ZoneLoading/Loading/Processor/ProcessorInflate.h
Normal file
14
src/ZoneLoading/Loading/Processor/ProcessorInflate.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "Loading/StreamProcessor.h"
|
||||
|
||||
class ProcessorInflate final : public StreamProcessor
|
||||
{
|
||||
class ProcessorInflateImpl;
|
||||
ProcessorInflateImpl* m_impl;
|
||||
|
||||
public:
|
||||
ProcessorInflate();
|
||||
~ProcessorInflate() override;
|
||||
|
||||
size_t Load(void* buffer, size_t length) override;
|
||||
};
|
28
src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.cpp
Normal file
28
src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "ProcessorStreamCipher.h"
|
||||
|
||||
ProcessorStreamCipher::ProcessorStreamCipher(IStreamCipher* cipher)
|
||||
{
|
||||
m_cipher = cipher;
|
||||
}
|
||||
|
||||
ProcessorStreamCipher::~ProcessorStreamCipher()
|
||||
{
|
||||
delete m_cipher;
|
||||
m_cipher = nullptr;
|
||||
}
|
||||
|
||||
|
||||
size_t ProcessorStreamCipher::Load(void* buffer, const size_t length)
|
||||
{
|
||||
if(m_base_stream != nullptr)
|
||||
{
|
||||
const size_t readSize = m_base_stream->Load(buffer, length);
|
||||
|
||||
if(readSize > 0)
|
||||
m_cipher->Process(buffer, buffer, readSize);
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
14
src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.h
Normal file
14
src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "Loading/StreamProcessor.h"
|
||||
#include "Crypto.h"
|
||||
|
||||
class ProcessorStreamCipher final : public StreamProcessor
|
||||
{
|
||||
IStreamCipher* m_cipher;
|
||||
|
||||
public:
|
||||
explicit ProcessorStreamCipher(IStreamCipher* cipher);
|
||||
~ProcessorStreamCipher() override;
|
||||
|
||||
size_t Load(void* buffer, size_t length) override;
|
||||
};
|
310
src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp
Normal file
310
src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp
Normal file
@ -0,0 +1,310 @@
|
||||
#include "ProcessorXChunks.h"
|
||||
#include "Zone/ZoneTypes.h"
|
||||
#include "Loading/Exception/InvalidChunkSizeException.h"
|
||||
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <cassert>
|
||||
|
||||
class DBLoadStream
|
||||
{
|
||||
int m_index;
|
||||
|
||||
uint8_t* m_input_buffer;
|
||||
size_t m_input_size;
|
||||
|
||||
uint8_t* m_output_buffer;
|
||||
size_t m_output_size;
|
||||
|
||||
size_t m_chunk_size;
|
||||
|
||||
bool m_is_loading;
|
||||
std::mutex m_load_mutex;
|
||||
std::condition_variable m_loading_finished;
|
||||
std::thread m_load_thread;
|
||||
|
||||
std::vector<IXChunkProcessor*>& m_processors;
|
||||
|
||||
void Load()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_load_mutex);
|
||||
|
||||
bool firstProcessor = true;
|
||||
|
||||
for(auto processor : m_processors)
|
||||
{
|
||||
if(!firstProcessor)
|
||||
{
|
||||
uint8_t* previousInputBuffer = m_input_buffer;
|
||||
m_input_buffer = m_output_buffer;
|
||||
m_output_buffer = previousInputBuffer;
|
||||
|
||||
m_input_size = m_output_size;
|
||||
m_output_size = 0;
|
||||
}
|
||||
|
||||
m_output_size = processor->Process(m_index, m_input_buffer, m_input_size, m_output_buffer, m_chunk_size);
|
||||
|
||||
firstProcessor = false;
|
||||
}
|
||||
|
||||
m_is_loading = false;
|
||||
m_loading_finished.notify_all();
|
||||
}
|
||||
|
||||
public:
|
||||
DBLoadStream(const int streamIndex, const size_t chunkSize, std::vector<IXChunkProcessor*>& chunkProcessors) : m_processors(chunkProcessors)
|
||||
{
|
||||
m_index = streamIndex;
|
||||
m_chunk_size = chunkSize;
|
||||
|
||||
m_input_buffer = new uint8_t[chunkSize];
|
||||
m_output_buffer = new uint8_t[chunkSize];
|
||||
|
||||
m_input_size = 0;
|
||||
m_output_size = 0;
|
||||
|
||||
m_is_loading = false;
|
||||
}
|
||||
|
||||
~DBLoadStream()
|
||||
{
|
||||
delete[] m_input_buffer;
|
||||
m_input_buffer = nullptr;
|
||||
|
||||
delete[] m_output_buffer;
|
||||
m_output_buffer = nullptr;
|
||||
}
|
||||
|
||||
uint8_t* GetInputBuffer() const
|
||||
{
|
||||
return m_input_buffer;
|
||||
}
|
||||
|
||||
void StartLoading(const size_t inputSize)
|
||||
{
|
||||
if(inputSize > 0)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_load_mutex);
|
||||
|
||||
if(m_is_loading)
|
||||
{
|
||||
m_loading_finished.wait(lock);
|
||||
}
|
||||
|
||||
m_input_size = inputSize;
|
||||
m_is_loading = true;
|
||||
m_load_thread = std::thread(&DBLoadStream::Load, this);
|
||||
m_load_thread.detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_output_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GetOutput(const uint8_t** pBuffer, size_t* pSize)
|
||||
{
|
||||
assert(pBuffer != nullptr);
|
||||
assert(pSize != nullptr);
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_load_mutex);
|
||||
if(m_is_loading)
|
||||
{
|
||||
m_loading_finished.wait(lock);
|
||||
}
|
||||
|
||||
*pBuffer = m_output_buffer;
|
||||
*pSize = m_output_size;
|
||||
}
|
||||
};
|
||||
|
||||
class ProcessorXChunks::ProcessorXChunksImpl
|
||||
{
|
||||
ProcessorXChunks* m_base;
|
||||
|
||||
std::vector<DBLoadStream*> m_streams;
|
||||
size_t m_chunk_size;
|
||||
std::vector<IXChunkProcessor*> m_chunk_processors;
|
||||
|
||||
bool m_initialized_streams;
|
||||
unsigned int m_current_stream;
|
||||
const uint8_t* m_current_chunk;
|
||||
size_t m_current_chunk_size;
|
||||
size_t m_current_chunk_offset;
|
||||
|
||||
bool m_eof_reached;
|
||||
unsigned int m_eof_stream;
|
||||
|
||||
void AdvanceStream(const unsigned int streamNum)
|
||||
{
|
||||
assert(streamNum >= 0 && streamNum < m_streams.size());
|
||||
|
||||
if(m_eof_reached)
|
||||
return;
|
||||
|
||||
xchunk_size_t chunkSize;
|
||||
const size_t readSize = m_base->m_base_stream->Load(&chunkSize, sizeof(chunkSize));
|
||||
|
||||
if(readSize == 0)
|
||||
{
|
||||
m_eof_reached = true;
|
||||
m_eof_stream = streamNum;
|
||||
return;
|
||||
}
|
||||
|
||||
if(chunkSize > m_chunk_size)
|
||||
{
|
||||
throw InvalidChunkSizeException(chunkSize, m_chunk_size);
|
||||
}
|
||||
|
||||
auto* stream = m_streams[streamNum];
|
||||
const size_t loadedChunkSize = m_base->m_base_stream->Load(stream->GetInputBuffer(), chunkSize);
|
||||
|
||||
if(loadedChunkSize != chunkSize)
|
||||
{
|
||||
throw InvalidChunkSizeException(chunkSize);
|
||||
}
|
||||
|
||||
stream->StartLoading(loadedChunkSize);
|
||||
}
|
||||
|
||||
void NextStream()
|
||||
{
|
||||
AdvanceStream(m_current_stream);
|
||||
|
||||
m_current_stream = (m_current_stream + 1) % m_streams.size();
|
||||
m_current_chunk_offset = 0;
|
||||
m_streams[m_current_stream]->GetOutput(&m_current_chunk, &m_current_chunk_size);
|
||||
}
|
||||
|
||||
void InitStreams()
|
||||
{
|
||||
m_initialized_streams = true;
|
||||
|
||||
const unsigned int streamCount = m_streams.size();
|
||||
for(unsigned int streamNum = 0; streamNum < streamCount; streamNum++)
|
||||
{
|
||||
AdvanceStream(streamNum);
|
||||
}
|
||||
|
||||
m_current_stream = 0;
|
||||
m_current_chunk_offset = 0;
|
||||
m_streams[0]->GetOutput(&m_current_chunk, &m_current_chunk_size);
|
||||
}
|
||||
|
||||
bool EndOfStream() const
|
||||
{
|
||||
return m_eof_reached && m_eof_stream == m_current_stream;
|
||||
}
|
||||
|
||||
public:
|
||||
ProcessorXChunksImpl(ProcessorXChunks* base, const int numStreams, const size_t xChunkSize)
|
||||
{
|
||||
assert(base != nullptr);
|
||||
assert(numStreams > 0);
|
||||
assert(xChunkSize > 0);
|
||||
|
||||
m_base = base;
|
||||
|
||||
for(int streamIndex = 0; streamIndex < numStreams; streamIndex++)
|
||||
{
|
||||
m_streams.push_back(new DBLoadStream(streamIndex, xChunkSize, m_chunk_processors));
|
||||
}
|
||||
|
||||
m_chunk_size = xChunkSize;
|
||||
|
||||
m_initialized_streams = false;
|
||||
m_current_stream = 0;
|
||||
m_current_chunk = nullptr;
|
||||
m_current_chunk_size = 0;
|
||||
m_current_chunk_offset = 0;
|
||||
|
||||
m_eof_reached = false;
|
||||
m_eof_stream = 0;
|
||||
}
|
||||
|
||||
~ProcessorXChunksImpl()
|
||||
{
|
||||
for(auto* stream : m_streams)
|
||||
{
|
||||
delete stream;
|
||||
}
|
||||
m_streams.clear();
|
||||
|
||||
for(auto* processor : m_chunk_processors)
|
||||
{
|
||||
delete processor;
|
||||
}
|
||||
m_chunk_processors.clear();
|
||||
}
|
||||
|
||||
void AddChunkProcessor(IXChunkProcessor* streamProcessor)
|
||||
{
|
||||
assert(streamProcessor != nullptr);
|
||||
|
||||
m_chunk_processors.push_back(streamProcessor);
|
||||
}
|
||||
|
||||
size_t Load(void* buffer, const size_t length)
|
||||
{
|
||||
assert(buffer != nullptr);
|
||||
|
||||
if(!m_initialized_streams)
|
||||
{
|
||||
InitStreams();
|
||||
}
|
||||
|
||||
size_t loadedSize = 0;
|
||||
while(!EndOfStream() && loadedSize < length)
|
||||
{
|
||||
auto* bufferPos = static_cast<uint8_t*>(buffer) + loadedSize;
|
||||
const size_t sizeToRead = length - loadedSize;
|
||||
const size_t bytesLeftInCurrentChunk = m_current_chunk_size - m_current_chunk_offset;
|
||||
|
||||
if(sizeToRead > bytesLeftInCurrentChunk)
|
||||
{
|
||||
memcpy_s(bufferPos, sizeToRead, &m_current_chunk[m_current_chunk_offset], bytesLeftInCurrentChunk);
|
||||
loadedSize += bytesLeftInCurrentChunk;
|
||||
|
||||
NextStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy_s(bufferPos, sizeToRead, &m_current_chunk[m_current_chunk_offset], sizeToRead);
|
||||
loadedSize += sizeToRead;
|
||||
m_current_chunk_offset += sizeToRead;
|
||||
|
||||
if(m_current_chunk_offset == m_current_chunk_size)
|
||||
{
|
||||
NextStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loadedSize;
|
||||
}
|
||||
};
|
||||
|
||||
ProcessorXChunks::ProcessorXChunks(const int numStreams, const size_t xChunkSize)
|
||||
{
|
||||
m_impl = new ProcessorXChunksImpl(this, numStreams, xChunkSize);
|
||||
}
|
||||
|
||||
ProcessorXChunks::~ProcessorXChunks()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
void ProcessorXChunks::AddChunkProcessor(IXChunkProcessor* chunkProcessor) const
|
||||
{
|
||||
m_impl->AddChunkProcessor(chunkProcessor);
|
||||
}
|
||||
|
||||
size_t ProcessorXChunks::Load(void* buffer, const size_t length)
|
||||
{
|
||||
return m_impl->Load(buffer, length);
|
||||
}
|
17
src/ZoneLoading/Loading/Processor/ProcessorXChunks.h
Normal file
17
src/ZoneLoading/Loading/Processor/ProcessorXChunks.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "Loading/StreamProcessor.h"
|
||||
#include "XChunks/IXChunkProcessor.h"
|
||||
|
||||
class ProcessorXChunks : public StreamProcessor
|
||||
{
|
||||
class ProcessorXChunksImpl;
|
||||
ProcessorXChunksImpl* m_impl;
|
||||
|
||||
public:
|
||||
ProcessorXChunks(int numStreams, size_t xChunkSize);
|
||||
~ProcessorXChunks() override;
|
||||
|
||||
size_t Load(void* buffer, size_t length) override;
|
||||
|
||||
void AddChunkProcessor(IXChunkProcessor* chunkProcessor) const;
|
||||
};
|
@ -0,0 +1,36 @@
|
||||
#include "ChunkProcessorInflate.h"
|
||||
#include "zlib.h"
|
||||
#include "zutil.h"
|
||||
#include <exception>
|
||||
#include "Loading/Exception/InvalidCompressionException.h"
|
||||
|
||||
size_t ChunkProcessorInflate::Process(int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize)
|
||||
{
|
||||
z_stream stream{};
|
||||
stream.zalloc = Z_NULL;
|
||||
stream.zfree = Z_NULL;
|
||||
stream.opaque = Z_NULL;
|
||||
|
||||
int ret = inflateInit2(&stream, -DEF_WBITS);
|
||||
if(ret != Z_OK)
|
||||
{
|
||||
throw std::exception("Initializing inflate failed.");
|
||||
}
|
||||
|
||||
stream.avail_in = inputLength;
|
||||
stream.next_in = input;
|
||||
stream.avail_out = outputBufferSize;
|
||||
stream.next_out = output;
|
||||
|
||||
ret = inflate(&stream, Z_FULL_FLUSH);
|
||||
if(ret != Z_STREAM_END)
|
||||
{
|
||||
throw InvalidCompressionException();
|
||||
}
|
||||
|
||||
const size_t outputSize = stream.total_out;
|
||||
|
||||
inflateEnd(&stream);
|
||||
|
||||
return outputSize;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "IXChunkProcessor.h"
|
||||
|
||||
class ChunkProcessorInflate : public IXChunkProcessor
|
||||
{
|
||||
public:
|
||||
size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override;
|
||||
};
|
@ -0,0 +1,156 @@
|
||||
#include "ChunkProcessorSalsa20.h"
|
||||
#include "Crypto.h"
|
||||
#include <cassert>
|
||||
|
||||
class StreamContextSalsa20
|
||||
{
|
||||
public:
|
||||
IStreamCipher* m_salsa20;
|
||||
IHashFunction* m_sha1;
|
||||
|
||||
StreamContextSalsa20()
|
||||
{
|
||||
m_salsa20 = nullptr;
|
||||
m_sha1 = nullptr;
|
||||
}
|
||||
|
||||
~StreamContextSalsa20()
|
||||
{
|
||||
delete m_salsa20;
|
||||
m_salsa20 = nullptr;
|
||||
|
||||
delete m_sha1;
|
||||
m_sha1 = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class ChunkProcessorSalsa20::ChunkProcessorSalsa20Impl
|
||||
{
|
||||
static const int BLOCK_HASHES_COUNT = 200;
|
||||
static const int SHA1_HASH_SIZE = 20;
|
||||
static const int SALSA20_IV_SIZE = 8;
|
||||
|
||||
int m_stream_count;
|
||||
StreamContextSalsa20* m_stream_contexts;
|
||||
|
||||
// m_block_hashes[BLOCK_HASHES_COUNT][numStreams][HASH_SIZE]
|
||||
uint8_t* m_block_hashes;
|
||||
unsigned int* m_stream_block_indices;
|
||||
|
||||
uint8_t* GetHashBlock(const int streamNumber) const
|
||||
{
|
||||
const size_t blockIndexOffset = m_stream_block_indices[streamNumber] * m_stream_count * SHA1_HASH_SIZE;
|
||||
const size_t streamOffset = streamNumber * SHA1_HASH_SIZE;
|
||||
|
||||
return &m_block_hashes[blockIndexOffset + streamOffset];
|
||||
}
|
||||
|
||||
public:
|
||||
ChunkProcessorSalsa20Impl(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize)
|
||||
{
|
||||
m_stream_count = streamCount;
|
||||
m_stream_contexts = new StreamContextSalsa20[streamCount];
|
||||
m_block_hashes = new uint8_t[BLOCK_HASHES_COUNT * streamCount * SHA1_HASH_SIZE];
|
||||
m_stream_block_indices = new unsigned int[streamCount];
|
||||
|
||||
InitStreams(zoneName, salsa20Key, keySize);
|
||||
}
|
||||
|
||||
~ChunkProcessorSalsa20Impl()
|
||||
{
|
||||
delete[] m_stream_contexts;
|
||||
|
||||
delete[] m_block_hashes;
|
||||
m_block_hashes = nullptr;
|
||||
|
||||
delete[] m_stream_block_indices;
|
||||
m_stream_block_indices = nullptr;
|
||||
}
|
||||
|
||||
void InitStreams(std::string& zoneName, const uint8_t* salsa20Key, size_t keySize) const
|
||||
{
|
||||
const int zoneNameLength = zoneName.length();
|
||||
const size_t blockHashBufferSize = BLOCK_HASHES_COUNT * m_stream_count * SHA1_HASH_SIZE;
|
||||
|
||||
assert(blockHashBufferSize % 4 == 0);
|
||||
|
||||
size_t zoneNameOffset = 0;
|
||||
for(size_t i = 0; i < blockHashBufferSize; i += 4)
|
||||
{
|
||||
*reinterpret_cast<uint32_t*>(&m_block_hashes[i]) = 0x1010101 * zoneName[zoneNameOffset++];
|
||||
|
||||
zoneNameOffset %= zoneNameLength;
|
||||
}
|
||||
|
||||
for(int stream = 0; stream < m_stream_count; stream++)
|
||||
{
|
||||
m_stream_block_indices[stream] = 0;
|
||||
|
||||
m_stream_contexts[stream].m_salsa20 = Crypto::CreateSalsa20(salsa20Key, keySize);
|
||||
m_stream_contexts[stream].m_sha1 = Crypto::CreateSHA1();
|
||||
}
|
||||
}
|
||||
|
||||
size_t Process(const int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize) const
|
||||
{
|
||||
assert(streamNumber >= 0 && streamNumber < m_stream_count);
|
||||
assert(input != nullptr);
|
||||
assert(output != nullptr);
|
||||
assert(inputLength <= outputBufferSize);
|
||||
|
||||
StreamContextSalsa20& streamContext = m_stream_contexts[streamNumber];
|
||||
|
||||
// Initialize Salsa20 with an IV of the first 8 bytes of the current hash block
|
||||
streamContext.m_salsa20->SetIV(GetHashBlock(streamNumber), SALSA20_IV_SIZE);
|
||||
streamContext.m_salsa20->Process(input, output, inputLength);
|
||||
|
||||
// Hash decrypted XChunk
|
||||
uint8_t blockSha1Hash[SHA1_HASH_SIZE];
|
||||
streamContext.m_sha1->Init();
|
||||
streamContext.m_sha1->Process(output, inputLength);
|
||||
streamContext.m_sha1->Finish(&blockSha1Hash);
|
||||
|
||||
// Advance index to next hash block
|
||||
m_stream_block_indices[streamNumber] = (m_stream_block_indices[streamNumber] + 1) % BLOCK_HASHES_COUNT;
|
||||
|
||||
uint8_t* nextHashBlock = GetHashBlock(streamNumber);
|
||||
|
||||
// XOR the upcoming hash block with the hash of the XChunk utilizing the previous hash block
|
||||
for(unsigned int hashOffset = 0; hashOffset < sizeof(blockSha1Hash); hashOffset++)
|
||||
{
|
||||
nextHashBlock[hashOffset] ^= blockSha1Hash[hashOffset];
|
||||
}
|
||||
|
||||
return inputLength;
|
||||
}
|
||||
|
||||
void GetSignatureData(const uint8_t** pSignatureData, size_t* pSize) const
|
||||
{
|
||||
assert(pSignatureData != nullptr);
|
||||
assert(pSize != nullptr);
|
||||
|
||||
*pSignatureData = m_block_hashes;
|
||||
*pSize = BLOCK_HASHES_COUNT * m_stream_count * SHA1_HASH_SIZE;
|
||||
}
|
||||
};
|
||||
|
||||
ChunkProcessorSalsa20::ChunkProcessorSalsa20(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize)
|
||||
{
|
||||
m_impl = new ChunkProcessorSalsa20Impl(streamCount, zoneName, salsa20Key, keySize);
|
||||
}
|
||||
|
||||
ChunkProcessorSalsa20::~ChunkProcessorSalsa20()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
size_t ChunkProcessorSalsa20::Process(const int streamNumber, const uint8_t* input, const size_t inputLength, uint8_t* output, const size_t outputBufferSize)
|
||||
{
|
||||
return m_impl->Process(streamNumber, input, inputLength, output, outputBufferSize);
|
||||
}
|
||||
|
||||
void ChunkProcessorSalsa20::GetSignatureData(const uint8_t** pSignatureData, size_t* pSize)
|
||||
{
|
||||
m_impl->GetSignatureData(pSignatureData, pSize);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "IXChunkProcessor.h"
|
||||
#include "Loading/ISignatureDataProvider.h"
|
||||
#include <string>
|
||||
|
||||
class ChunkProcessorSalsa20 : public IXChunkProcessor, public ISignatureDataProvider
|
||||
{
|
||||
class ChunkProcessorSalsa20Impl;
|
||||
ChunkProcessorSalsa20Impl* m_impl;
|
||||
|
||||
public:
|
||||
ChunkProcessorSalsa20(int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize);
|
||||
~ChunkProcessorSalsa20() override;
|
||||
|
||||
size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override;
|
||||
void GetSignatureData(const uint8_t** pSignatureData, size_t* pSize) override;
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
class IXChunkProcessor
|
||||
{
|
||||
public:
|
||||
virtual ~IXChunkProcessor() = default;
|
||||
virtual size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) = 0;
|
||||
};
|
22
src/ZoneLoading/Loading/Steps/StepAddProcessor.cpp
Normal file
22
src/ZoneLoading/Loading/Steps/StepAddProcessor.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "StepAddProcessor.h"
|
||||
#include <cassert>
|
||||
|
||||
StepAddProcessor::StepAddProcessor(StreamProcessor* streamProcessor)
|
||||
{
|
||||
m_stream_processor = streamProcessor;
|
||||
}
|
||||
|
||||
StepAddProcessor::~StepAddProcessor()
|
||||
{
|
||||
delete m_stream_processor;
|
||||
m_stream_processor = nullptr;
|
||||
}
|
||||
|
||||
void StepAddProcessor::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
assert(zoneLoader != nullptr);
|
||||
assert(m_stream_processor != nullptr);
|
||||
|
||||
zoneLoader->AddStreamProcessor(m_stream_processor);
|
||||
m_stream_processor = nullptr;
|
||||
}
|
14
src/ZoneLoading/Loading/Steps/StepAddProcessor.h
Normal file
14
src/ZoneLoading/Loading/Steps/StepAddProcessor.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
|
||||
class StepAddProcessor final : public ILoadingStep
|
||||
{
|
||||
StreamProcessor* m_stream_processor;
|
||||
|
||||
public:
|
||||
explicit StepAddProcessor(StreamProcessor* streamProcessor);
|
||||
~StepAddProcessor() override;
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
};
|
30
src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp
Normal file
30
src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "StepAllocXBlocks.h"
|
||||
#include "Loading/Exception/InvalidXBlockSizeException.h"
|
||||
|
||||
const uint64_t StepAllocXBlocks::MAX_XBLOCK_SIZE = 0x3C000000;
|
||||
|
||||
void StepAllocXBlocks::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
const unsigned int blockCount = zoneLoader->m_blocks.size();
|
||||
|
||||
auto* blockSizes = new xblock_size_t[blockCount];
|
||||
stream->Load(blockSizes, sizeof(xblock_size_t) * blockCount);
|
||||
|
||||
uint64_t totalMemory = 0;
|
||||
for(unsigned int block = 0; block < blockCount; block++)
|
||||
{
|
||||
totalMemory += blockSizes[block];
|
||||
}
|
||||
|
||||
if(totalMemory > MAX_XBLOCK_SIZE)
|
||||
{
|
||||
throw InvalidXBlockSizeException(totalMemory, MAX_XBLOCK_SIZE);
|
||||
}
|
||||
|
||||
for(unsigned int block = 0; block < blockCount; block++)
|
||||
{
|
||||
zoneLoader->m_blocks[block]->Alloc(blockSizes[block]);
|
||||
}
|
||||
|
||||
delete[] blockSizes;
|
||||
}
|
11
src/ZoneLoading/Loading/Steps/StepAllocXBlocks.h
Normal file
11
src/ZoneLoading/Loading/Steps/StepAllocXBlocks.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
|
||||
class StepAllocXBlocks final : public ILoadingStep
|
||||
{
|
||||
static const uint64_t MAX_XBLOCK_SIZE;
|
||||
|
||||
public:
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
};
|
34
src/ZoneLoading/Loading/Steps/StepLoadSignature.cpp
Normal file
34
src/ZoneLoading/Loading/Steps/StepLoadSignature.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "StepLoadSignature.h"
|
||||
#include "Loading/Exception/UnexpectedEndOfFileException.h"
|
||||
#include <cassert>
|
||||
|
||||
StepLoadSignature::StepLoadSignature(const size_t signatureSize)
|
||||
{
|
||||
m_signature_size = signatureSize;
|
||||
m_signature = new uint8_t[signatureSize];
|
||||
}
|
||||
|
||||
StepLoadSignature::~StepLoadSignature()
|
||||
{
|
||||
delete[] m_signature;
|
||||
m_signature = nullptr;
|
||||
}
|
||||
|
||||
void StepLoadSignature::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
assert(stream != nullptr);
|
||||
|
||||
if(stream->Load(m_signature, m_signature_size) != m_signature_size)
|
||||
throw UnexpectedEndOfFileException();
|
||||
}
|
||||
|
||||
void StepLoadSignature::GetSignature(const uint8_t** pSignature, size_t* pSize)
|
||||
{
|
||||
assert(pSignature != nullptr);
|
||||
assert(pSize != nullptr);
|
||||
|
||||
assert(m_signature != nullptr);
|
||||
|
||||
*pSignature = m_signature;
|
||||
*pSize = m_signature_size;
|
||||
}
|
17
src/ZoneLoading/Loading/Steps/StepLoadSignature.h
Normal file
17
src/ZoneLoading/Loading/Steps/StepLoadSignature.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
#include "Loading/ISignatureProvider.h"
|
||||
|
||||
class StepLoadSignature final : public ILoadingStep, public ISignatureProvider
|
||||
{
|
||||
uint8_t* m_signature;
|
||||
size_t m_signature_size;
|
||||
|
||||
public:
|
||||
explicit StepLoadSignature(size_t signatureSize);
|
||||
~StepLoadSignature() override;
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
void GetSignature(const uint8_t** pSignature, size_t* pSize) override;
|
||||
};
|
26
src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp
Normal file
26
src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "StepLoadZoneContent.h"
|
||||
#include "Zone/Stream/Impl/XBlockInputStream.h"
|
||||
#include <cassert>
|
||||
|
||||
StepLoadZoneContent::StepLoadZoneContent(IContentLoadingEntryPoint* entryPoint, Zone* zone, const int offsetBlockBitCount, const block_t insertBlock)
|
||||
{
|
||||
m_content_loader = entryPoint;
|
||||
m_zone = zone;
|
||||
m_offset_block_bit_count = offsetBlockBitCount;
|
||||
m_insert_block = insertBlock;
|
||||
}
|
||||
|
||||
StepLoadZoneContent::~StepLoadZoneContent()
|
||||
{
|
||||
delete m_content_loader;
|
||||
m_content_loader = nullptr;
|
||||
}
|
||||
|
||||
void StepLoadZoneContent::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
auto* inputStream = new XBlockInputStream(zoneLoader->m_blocks, stream, m_offset_block_bit_count, m_insert_block);
|
||||
|
||||
m_content_loader->Load(m_zone, inputStream);
|
||||
|
||||
delete inputStream;
|
||||
}
|
18
src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h
Normal file
18
src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
#include "Loading/IContentLoadingEntryPoint.h"
|
||||
|
||||
class StepLoadZoneContent final : public ILoadingStep
|
||||
{
|
||||
IContentLoadingEntryPoint* m_content_loader;
|
||||
Zone* m_zone;
|
||||
int m_offset_block_bit_count;
|
||||
block_t m_insert_block;
|
||||
|
||||
public:
|
||||
StepLoadZoneContent(IContentLoadingEntryPoint* entryPoint, Zone* zone, int offsetBlockBitCount, block_t insertBlock);
|
||||
~StepLoadZoneContent();
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
};
|
30
src/ZoneLoading/Loading/Steps/StepSkipBytes.cpp
Normal file
30
src/ZoneLoading/Loading/Steps/StepSkipBytes.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "StepSkipBytes.h"
|
||||
|
||||
StepSkipBytes::StepSkipBytes(const unsigned int skipCount)
|
||||
{
|
||||
m_skip_count = skipCount;
|
||||
}
|
||||
|
||||
void StepSkipBytes::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
uint8_t tempBuffer[128];
|
||||
unsigned int skippedBytes = 0;
|
||||
|
||||
while(skippedBytes < m_skip_count)
|
||||
{
|
||||
unsigned int toSkip;
|
||||
|
||||
if(m_skip_count - skippedBytes < sizeof(tempBuffer))
|
||||
{
|
||||
toSkip = m_skip_count - skippedBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
toSkip = sizeof(tempBuffer);
|
||||
}
|
||||
|
||||
stream->Load(tempBuffer, toSkip);
|
||||
|
||||
skippedBytes += toSkip;
|
||||
}
|
||||
}
|
13
src/ZoneLoading/Loading/Steps/StepSkipBytes.h
Normal file
13
src/ZoneLoading/Loading/Steps/StepSkipBytes.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
|
||||
class StepSkipBytes final : public ILoadingStep
|
||||
{
|
||||
unsigned int m_skip_count;
|
||||
|
||||
public:
|
||||
explicit StepSkipBytes(unsigned int skipCount);
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
};
|
42
src/ZoneLoading/Loading/Steps/StepVerifyFileName.cpp
Normal file
42
src/ZoneLoading/Loading/Steps/StepVerifyFileName.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "StepVerifyFileName.h"
|
||||
#include "Loading/Exception/InvalidFileNameException.h"
|
||||
|
||||
StepVerifyFileName::StepVerifyFileName(std::string fileName, const size_t fileNameBufferSize)
|
||||
{
|
||||
m_file_name = std::move(fileName);
|
||||
m_file_name_buffer_size = fileNameBufferSize;
|
||||
|
||||
if(m_file_name.length() > m_file_name_buffer_size)
|
||||
m_file_name.erase(m_file_name_buffer_size);
|
||||
}
|
||||
|
||||
void StepVerifyFileName::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
std::string originalFileName;
|
||||
unsigned bufferOffset = 0;
|
||||
char c;
|
||||
|
||||
for(; bufferOffset < m_file_name_buffer_size; bufferOffset++)
|
||||
{
|
||||
|
||||
stream->Load(&c, sizeof(char));
|
||||
|
||||
if(c == '\00')
|
||||
{
|
||||
bufferOffset++;
|
||||
break;
|
||||
}
|
||||
|
||||
originalFileName += c;
|
||||
}
|
||||
|
||||
// Skip the rest of the buffer which should be null bytes
|
||||
while(bufferOffset < m_file_name_buffer_size)
|
||||
{
|
||||
stream->Load(&c, sizeof(char));
|
||||
bufferOffset++;
|
||||
}
|
||||
|
||||
if(originalFileName != m_file_name)
|
||||
throw InvalidFileNameException(m_file_name, originalFileName);
|
||||
}
|
14
src/ZoneLoading/Loading/Steps/StepVerifyFileName.h
Normal file
14
src/ZoneLoading/Loading/Steps/StepVerifyFileName.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
|
||||
class StepVerifyFileName final : public ILoadingStep
|
||||
{
|
||||
std::string m_file_name;
|
||||
size_t m_file_name_buffer_size;
|
||||
|
||||
public:
|
||||
explicit StepVerifyFileName(std::string fileName, size_t fileNameBufferSize);
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
};
|
21
src/ZoneLoading/Loading/Steps/StepVerifyMagic.cpp
Normal file
21
src/ZoneLoading/Loading/Steps/StepVerifyMagic.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "StepVerifyMagic.h"
|
||||
#include "Loading/Exception/InvalidMagicException.h"
|
||||
|
||||
StepVerifyMagic::StepVerifyMagic(const char* magic)
|
||||
{
|
||||
m_magic = magic;
|
||||
}
|
||||
|
||||
void StepVerifyMagic::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
const size_t magicLength = strlen(m_magic);
|
||||
char currentCharacter;
|
||||
|
||||
for(unsigned i = 0; i < magicLength; i++)
|
||||
{
|
||||
stream->Load(¤tCharacter, sizeof(char));
|
||||
|
||||
if(currentCharacter != m_magic[i])
|
||||
throw InvalidMagicException(m_magic);
|
||||
}
|
||||
}
|
13
src/ZoneLoading/Loading/Steps/StepVerifyMagic.h
Normal file
13
src/ZoneLoading/Loading/Steps/StepVerifyMagic.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
|
||||
class StepVerifyMagic final : public ILoadingStep
|
||||
{
|
||||
const char* m_magic;
|
||||
|
||||
public:
|
||||
explicit StepVerifyMagic(const char* magic);
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
};
|
36
src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp
Normal file
36
src/ZoneLoading/Loading/Steps/StepVerifySignature.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "StepVerifySignature.h"
|
||||
#include "Loading/Exception/InvalidSignatureException.h"
|
||||
#include <cassert>
|
||||
|
||||
StepVerifySignature::StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ISignatureDataProvider* signatureDataProvider)
|
||||
{
|
||||
m_algorithm = signatureAlgorithm;
|
||||
m_signature_provider = signatureProvider;
|
||||
m_signature_data_provider = signatureDataProvider;
|
||||
}
|
||||
|
||||
StepVerifySignature::~StepVerifySignature()
|
||||
{
|
||||
delete m_algorithm;
|
||||
m_algorithm = nullptr;
|
||||
}
|
||||
|
||||
void StepVerifySignature::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
assert(m_algorithm != nullptr);
|
||||
assert(m_signature_provider != nullptr);
|
||||
assert(m_signature_data_provider != nullptr);
|
||||
|
||||
const uint8_t* signature;
|
||||
size_t signatureSize;
|
||||
m_signature_provider->GetSignature(&signature, &signatureSize);
|
||||
|
||||
const uint8_t* signatureData;
|
||||
size_t signatureDataSize;
|
||||
m_signature_data_provider->GetSignatureData(&signatureData, &signatureDataSize);
|
||||
|
||||
if(!m_algorithm->Verify(signatureData, signatureDataSize, signature, signatureSize))
|
||||
{
|
||||
throw InvalidSignatureException();
|
||||
}
|
||||
}
|
19
src/ZoneLoading/Loading/Steps/StepVerifySignature.h
Normal file
19
src/ZoneLoading/Loading/Steps/StepVerifySignature.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loading/ILoadingStep.h"
|
||||
#include "Crypto.h"
|
||||
#include "Loading/ISignatureProvider.h"
|
||||
#include "Loading/ISignatureDataProvider.h"
|
||||
|
||||
class StepVerifySignature final : public ILoadingStep
|
||||
{
|
||||
IPublicKeyAlgorithm* m_algorithm;
|
||||
ISignatureProvider* m_signature_provider;
|
||||
ISignatureDataProvider* m_signature_data_provider;
|
||||
|
||||
public:
|
||||
StepVerifySignature(IPublicKeyAlgorithm* signatureAlgorithm, ISignatureProvider* signatureProvider, ISignatureDataProvider* signatureDataProvider);
|
||||
~StepVerifySignature();
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
};
|
11
src/ZoneLoading/Loading/StreamProcessor.cpp
Normal file
11
src/ZoneLoading/Loading/StreamProcessor.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "StreamProcessor.h"
|
||||
|
||||
StreamProcessor::StreamProcessor()
|
||||
{
|
||||
m_base_stream = nullptr;
|
||||
}
|
||||
|
||||
void StreamProcessor::SetBaseStream(ILoadingStream* baseStream)
|
||||
{
|
||||
m_base_stream = baseStream;
|
||||
}
|
13
src/ZoneLoading/Loading/StreamProcessor.h
Normal file
13
src/ZoneLoading/Loading/StreamProcessor.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "ILoadingStream.h"
|
||||
|
||||
class StreamProcessor : public ILoadingStream
|
||||
{
|
||||
protected:
|
||||
ILoadingStream* m_base_stream;
|
||||
|
||||
public:
|
||||
StreamProcessor();
|
||||
|
||||
void SetBaseStream(ILoadingStream* baseStream);
|
||||
};
|
94
src/ZoneLoading/Loading/ZoneLoader.cpp
Normal file
94
src/ZoneLoading/Loading/ZoneLoader.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "ZoneLoader.h"
|
||||
#include "Exception/LoadingException.h"
|
||||
#include "LoadingFileStream.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
ZoneLoader::ZoneLoader(Zone* zone)
|
||||
{
|
||||
m_zone = zone;
|
||||
m_processor_chain_dirty = false;
|
||||
}
|
||||
|
||||
ZoneLoader::~ZoneLoader()
|
||||
{
|
||||
for(auto step : m_steps)
|
||||
{
|
||||
delete step;
|
||||
}
|
||||
m_steps.clear();
|
||||
|
||||
for(auto processor : m_processors)
|
||||
{
|
||||
delete processor;
|
||||
}
|
||||
m_processors.clear();
|
||||
}
|
||||
|
||||
ILoadingStream* ZoneLoader::BuildLoadingChain(ILoadingStream* rootStream)
|
||||
{
|
||||
ILoadingStream* currentStream = rootStream;
|
||||
|
||||
for(auto processor : m_processors)
|
||||
{
|
||||
processor->SetBaseStream(currentStream);
|
||||
|
||||
currentStream = processor;
|
||||
}
|
||||
|
||||
m_processor_chain_dirty = false;
|
||||
return currentStream;
|
||||
}
|
||||
|
||||
void ZoneLoader::AddXBlock(XBlock* block)
|
||||
{
|
||||
m_blocks.push_back(block);
|
||||
|
||||
std::sort(m_blocks.begin(), m_blocks.end(), [](XBlock* b1, XBlock* b2) -> bool
|
||||
{
|
||||
return b1->m_index < b2->m_index;
|
||||
});
|
||||
}
|
||||
|
||||
void ZoneLoader::AddLoadingStep(ILoadingStep* step)
|
||||
{
|
||||
m_steps.push_back(step);
|
||||
}
|
||||
|
||||
void ZoneLoader::AddStreamProcessor(StreamProcessor* streamProcessor)
|
||||
{
|
||||
m_processors.push_back(streamProcessor);
|
||||
m_processor_chain_dirty = true;
|
||||
}
|
||||
|
||||
Zone* ZoneLoader::LoadZone(FileAPI::File* file)
|
||||
{
|
||||
LoadingFileStream fileStream(file);
|
||||
ILoadingStream* endStream = BuildLoadingChain(&fileStream);
|
||||
|
||||
try
|
||||
{
|
||||
for(auto step : m_steps)
|
||||
{
|
||||
step->PerformStep(this, endStream);
|
||||
|
||||
if(m_processor_chain_dirty)
|
||||
{
|
||||
endStream = BuildLoadingChain(&fileStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (LoadingException& e)
|
||||
{
|
||||
const std::string detailedMessage = e.DetailedMessage();
|
||||
printf("Loading fastfile failed: %s\n", detailedMessage.c_str());
|
||||
|
||||
delete m_zone;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_zone->m_game->AddZone(m_zone);
|
||||
|
||||
return m_zone;
|
||||
}
|
35
src/ZoneLoading/Loading/ZoneLoader.h
Normal file
35
src/ZoneLoading/Loading/ZoneLoader.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "ILoadingStep.h"
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/XBlock.h"
|
||||
#include "Utils/FileAPI.h"
|
||||
#include "StreamProcessor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ILoadingStep;
|
||||
|
||||
class ZoneLoader
|
||||
{
|
||||
std::vector<ILoadingStep*> m_steps;
|
||||
std::vector<StreamProcessor*> m_processors;
|
||||
|
||||
bool m_processor_chain_dirty;
|
||||
|
||||
Zone* m_zone;
|
||||
|
||||
ILoadingStream* BuildLoadingChain(ILoadingStream* rootStream);
|
||||
|
||||
public:
|
||||
std::vector<XBlock*> m_blocks;
|
||||
|
||||
explicit ZoneLoader(Zone* zone);
|
||||
~ZoneLoader();
|
||||
|
||||
void AddXBlock(XBlock* block);
|
||||
void AddLoadingStep(ILoadingStep* step);
|
||||
void AddStreamProcessor(StreamProcessor* streamProcessor);
|
||||
|
||||
Zone* LoadZone(FileAPI::File* file);
|
||||
};
|
Reference in New Issue
Block a user