diff --git a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp index 977059db..7c02f919 100644 --- a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp +++ b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp @@ -2,6 +2,94 @@ namespace Assets { + void IXAnimParts::Load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) + { + Components::FileSystem::File animFile(Utils::VA("xanim/%s.iw4xAnim", name.data())); + + if (animFile.Exists()) + { + Utils::Stream::Reader reader(builder->GetAllocator(), animFile.GetBuffer()); + + Game::XAnimParts* xanim = reader.ReadArray(); + + if (xanim) + { + if (xanim->name) + { + xanim->name = reader.ReadCString(); + } + + if (xanim->tagnames) + { + xanim->tagnames = builder->GetAllocator()->AllocateArray(xanim->boneCount[Game::XAnimPartType::PART_TYPE_ALL]); + for (int i = 0; i < xanim->boneCount[Game::XAnimPartType::PART_TYPE_ALL]; ++i) + { + xanim->tagnames[i] = Game::SL_GetString(reader.ReadCString(), 0); + } + } + + if (xanim->notetracks) + { + xanim->notetracks = reader.ReadArray(xanim->notetrackCount); + + for (int i = 0; i < xanim->notetrackCount; ++i) + { + xanim->notetracks[i].name = Game::SL_GetString(reader.ReadCString(), 0); + } + } + + if (xanim->dataByte) + { + xanim->dataByte = reader.ReadArray(xanim->dataByteCount); + } + + if (xanim->dataShort) + { + xanim->dataShort = reader.ReadArray(xanim->dataShortCount); + } + + if (xanim->dataInt) + { + xanim->dataInt = reader.ReadArray(xanim->dataIntCount); + } + + if (xanim->randomDataByte) + { + xanim->randomDataByte = reader.ReadArray(xanim->randomDataByteCount); + } + + if (xanim->randomDataShort) + { + xanim->randomDataShort = reader.ReadArray(xanim->randomDataShortCount); + } + + if (xanim->randomDataInt) + { + xanim->randomDataInt = reader.ReadArray(xanim->randomDataIntCount); + } + + if (xanim->indices.data) + { + if (xanim->framecount < 256) + { + xanim->indices._1 = reader.ReadArray(xanim->indexcount); + } + else + { + xanim->indices._2 = reader.ReadArray(xanim->indexcount); + } + } + + if (!reader.End()) + { + Components::Logger::Error(0, "Reading animation '%s' failed, remaining raw data found!", name.data()); + } + + header->xanim = xanim; + } + } + } + void IXAnimParts::Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { Game::XAnimParts* asset = header.xanim; diff --git a/src/Components/Modules/AssetInterfaces/IXAnimParts.hpp b/src/Components/Modules/AssetInterfaces/IXAnimParts.hpp index 201f991a..4b8994f0 100644 --- a/src/Components/Modules/AssetInterfaces/IXAnimParts.hpp +++ b/src/Components/Modules/AssetInterfaces/IXAnimParts.hpp @@ -7,6 +7,7 @@ namespace Assets virtual void Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + virtual void Load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) override; private: void Save_XAnimDeltaPart(Game::XAnimDeltaPart* delta, unsigned short framecount, Components::ZoneBuilder::Zone* builder); diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index bed183da..02f72e30 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -116,7 +116,7 @@ namespace Components info.Set("protocol", Utils::VA("%i", PROTOCOL)); info.Set("shortversion", VERSION_STR); info.Set("mapname", Dvar::Var("mapname").Get()); - info.Set("isPrivate", (Dvar::Var("g_password").Get().size() ? "1" : "0")); + info.Set("isPrivate", (Dvar::Var("g_password").Get().empty() ? "0" : "1")); std::string time = Utils::VA("%u", Game::Com_Milliseconds()); info.Set("checksum", Utils::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(time.data(), time.size()))); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index b1e9f8b3..e6443899 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -1605,7 +1605,7 @@ namespace Game struct XAnimParts { - char * name; // 0 + const char * name; // 0 unsigned short dataByteCount; // 4 unsigned short dataShortCount; // 6 unsigned short dataIntCount; // 8 diff --git a/src/Utils/Stream.cpp b/src/Utils/Stream.cpp index 69460793..db7f5475 100644 --- a/src/Utils/Stream.cpp +++ b/src/Utils/Stream.cpp @@ -2,6 +2,63 @@ namespace Utils { + std::string Stream::Reader::ReadString() + { + std::string str; + + while (char byte = Stream::Reader::ReadByte()) + { + str.append(&byte, 1); + } + + return str; + } + + const char* Stream::Reader::ReadCString() + { + return Stream::Reader::Allocator->DuplicateString(Stream::Reader::ReadString()); + } + + char Stream::Reader::ReadByte() + { + if ((Stream::Reader::Position + 1) <= Stream::Reader::Buffer.size()) + { + return Stream::Reader::Buffer[Stream::Reader::Position++]; + } + + return 0; + } + + void* Stream::Reader::Read(size_t size, size_t count) + { + size_t bytes = size * count; + + if ((Stream::Reader::Position + bytes) <= Stream::Reader::Buffer.size()) + { + void* buffer = Stream::Reader::Allocator->Allocate(bytes); + + std::memcpy(buffer, Stream::Reader::Buffer.data() + Stream::Reader::Position, bytes); + Stream::Reader::Position += bytes; + + return buffer; + } + + return nullptr; + } + + bool Stream::Reader::End() + { + return (Stream::Reader::Buffer.size() == Stream::Reader::Position); + } + + void Stream::Reader::Seek(unsigned int position) + { + if (Stream::Reader::Buffer.size() >= position) + { + Stream::Reader::Position = position; + } + } + Stream::Stream() : CriticalSectionState(0) { memset(Stream::BlockSize, 0, sizeof(Stream::BlockSize)); diff --git a/src/Utils/Stream.hpp b/src/Utils/Stream.hpp index ac6fcca0..143df90d 100644 --- a/src/Utils/Stream.hpp +++ b/src/Utils/Stream.hpp @@ -9,6 +9,31 @@ namespace Utils std::string Buffer; public: + class Reader + { + public: + Reader(Utils::Memory::Allocator* allocator, std::string& buffer) : Buffer(buffer), Allocator(allocator), Position(0) {} + + std::string ReadString(); + const char* ReadCString(); + + char ReadByte(); + + void* Read(size_t size, size_t count = 1); + template T* ReadArray(size_t count = 1) + { + return reinterpret_cast(Read(sizeof(T), count)); + } + + bool End(); + void Seek(unsigned int position); + + private: + unsigned int Position; + std::string Buffer; + Utils::Memory::Allocator* Allocator; + }; + enum Alignment { ALIGN_2,